Spring学习8-Spring事务管理(编程式事务管理)
一、Spring事务的相关知识
1、事务是指一系列独立的操作,但在概念上具有原子性。 比如转账:A账号-100,
B账号+100,完成。这两个操作独立是没问题的。 但在逻辑上,要么全部完成,要么一起失败。
1)jdbc事务:每个Connection都带有一个事务,只是默认被设置为自动提交。一个连接可以有多个事务。对于JDBC,只有在同一个连接内,才有讨论是否提交的前提。
2)Hibernate事务:本质上也是使用JDBC来处理事务。但是不是直接操作,而是使用Session来操作事务。Session.getTranction();
####事务应该要在service层(也可以叫事务层)进行控制。
为什么用Spring来进行事务控制?
如果要手动进行控制事务的话,对于JDBC,service层需要Connection;对于Hibernate,serivice层需要
Session。若一个项目要实现JDBC和Hibernate或其他的互换,我们要做Service层修改很多东西;而且对于Service层来说,他
应该关心的不应该是这些,而是业务逻辑。因此,首先手动控制不能实现组件的替换,其次这些API也不应该出现在service层,但是Spring的
IOC很好的解决了这样的问题。
2、JavaEE传统事务有两种策略:全局事务和局部事务。全局事务由应用服务器管理,需要底层服务器JTA支持(如WebLogic、JBoss等)。局部事务和底层采用的持久化技术有关:当采用JDBC持久化技术时,需要使用Connetion对象来操作事务;而采用Hibernate持久化技术时,需要使用Session对象来操作事务。
全局事务可以跨多个事务性的资源(典型例子是关系数据库和消息队列);使用局部事务,应用服务器不需要参与事务管理,因此不能保证跨多个事务性资源的事务的正确性。当然,实际上大部分应用都使用单一事务性的资源。
Spring事务策略是通过PlatformTransactionManager接口体现的,该接口是Spring事务策略的核心,是一个与任何事务策略分离的接口,随着底层不同事务策略的切换,应用必须采用不同的实现类。结合Spring的IoC容器,可以向该接口注入相关的平台特性。
3、Spring的事务管理,主要有两种方式实现,一种是在代码中编写(编程式事务管理),一种是声明式事务(又可分为AOP式事务管理和注解式事务管理)。在代码中编写要更加细粒度,而很多时候我们只需要简单的事务处理,那就可以用声明式事务。
Spring的事务管理器:
事务管理器实现 |
目标 |
org.springframework.jdbc.datasource.DataSourceTransactionManager |
在JDBC DataSource中管理事务 (须注入数据源datasource |
org.springframework.orm.hibernate.HibernateTransactionManager |
管理Hibernate事务 (须注入SessionFactory |
org.springframework.orm.jdo.JdoTransactionManager |
管理JDO事务 |
org.springframework.transaction.jta.JtaTransactionManager |
使用一个JTA管理事务,在一个事务跨越多个资源时必须使用 (无须注入参数) |
org.springframework.orm.ojb.PersistenceBrokerTransactionManager |
管理Apache的OJB事务 |
这些事务管理器的的父接口都是PlatformTransactionManager.Spring的事务管理机制是一种典型的策略模式,PlatformTransactionManager
代表事务管理接口(该接口定义了下面所说的三个方法),他并不知道底层如何管理事务,他只要求事务管理的实现类提供开始事务
(getTransaction())、提交事务(commit())、回滚事务(rollback()),但具体如何实现则交给具体的实现类完成——不
同的实现类代表不同的事务管理策略。
说明:
1、JTA事务管理器无须注入参数,是因为全局事务的JTA资源由JAVA
EE服务器提供,而Spring容器能自行从JAVA EE服务器中获取该事务资源,所以无须使用依赖注入来配置。
2、当使用JTA全局事务策略时,实际底层须应用服务器支持,而不同的应用服务器所提供的JTA全局事务可能存在细节上的差异,因此实际配置全局事务管理器是可能需要使用JtaTransactionManager的子类,如:OC4JtaTransactionManager(Oracle提供的应用服务器)、WebLogicJtaTransactionManager(Bea提供的WebLogic)、UowJtaTransactionManager(IBM提供的WebSphere)等
二、Spring编程式事务示例
步骤一、编写spring配置文件
下面实例使用DataSourceTransactionManager来管理JDBC事务。
查看Spring的配置信息:(applicationContext.xml):
<?xml version="1.0"
encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="propertyConfig"
class="org.springframework.beans.factory.config.
PropertyPlaceholderConfigurer">
<property name="location">
<value>connect.properties</value>
</property>
</bean>
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property
name="driverClassName">
<value>${db.driver}</value>
</property>
<property name="url">
<value>${db.url}</value>
</property>
<property name="username">
<value>${db.username}</value>
</property>
<property name="password">
<value>${db.password}</value>
</property>
</bean>
<bean id="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource">
<ref bean="dataSource" />
</property>
</bean>
<!-- JDBC事务管理器 注意:事务管理器传的参数是数据源-->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.
DataSourceTransactionManager" scope="singleton">
<property name="dataSource">
<ref bean="dataSource" />
</property>
</bean>
<!-- 声明事务模板 -->
<bean id="transactionTemplate"
class="org.springframework.transaction.support.
TransactionTemplate">
<property
name="transactionManager">
<ref bean="transactionManager"
/>
</property>
</bean>
<bean id="bankDao"
class="com.sunflower.dao.BankDaoImp">
<property name="jdbcTemplate">
<ref bean="jdbcTemplate" />
</property>
<property
name="transactionTemplate">
<ref bean="transactionTemplate"
/>
</property>
</bean>
</beans>
上
面代码中配置了一个org.springframework.transaction.support.TransactionTemplate实例,要
在代码中添加事务,Spring为我们提供了一种方法就是使用TransactionTemplate类。我们要为
TransactionTemplate装配一个TransactionManager,
如果是要配置Hibernate事务,要进行如下配置:(配置一个sessionFactory):
<!-- Hibernate事务管理器 注意:此事务管理器参数是sessionFactory-->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.
HibernateTransactionManager"
scope="singleton">
<property
name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
如果是要配置JTA事务,要进行如下配置(无须参数):
<bean
id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager"
scope="singleton" >
</bean>
步骤二、使用TransactionTemplate进行事务管理:
package com.sunflower.dao;
import java.sql.ResultSet;
import java.sql.SQLException;
import
org.springframework.jdbc.core.JdbcTemplate;
import
org.springframework.jdbc.core.RowCallbackHandler;
import
org.springframework.transaction.TransactionStatus;
import
org.springframework.transaction.support.TransactionCallback;
import
org.springframework.transaction.support.TransactionTemplate;
import com.sunflower.entity.People;
public class BankDaoImp implements BankDao
{
private JdbcTemplate jdbcTemplate;
private TransactionTemplate transactionTemplate;
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public TransactionTemplate getTransactionTemplate() {
return transactionTemplate;
}
public void setTransactionTemplate(TransactionTemplate
transactionTemplate) {
this.transactionTemplate = transactionTemplate;
}
@Override
public double getMoney(final People people) {
double money = people.getMoney();
// 开始事务,如果出现状况则回滚
transactionTemplate.execute(new
TransactionCallback<People>()
{
@Override
public People doInTransaction(TransactionStatus ts) {
try {
final People people2 = new People();
// 使用JdbcTemplate进行持久化层操作
String sql = "select money from bank where name = ?";
Object[] params = new Object[] { people.getName() };
// 查询
jdbcTemplate.query(sql, params, new RowCallbackHandler() {
@Override
public void processRow(ResultSet rs)
throws SQLException {
people2.setMoney(rs.getDouble("money"));
System.out.println(people.getName() + "用户还有"
+ rs.getDouble("money") + "元余款");
System.out.println(people.getName() + "要从账户中取出"
+ people.getMoney() + "元");
if (people2.getMoney() < people.getMoney()) {
System.out.println("余额不足");
people.setMoney(-1);
return;
}
}
});
if (people.getMoney() < 0)
return null;
else {
sql = "update bank set money = ? where name = ?";
Object[] params2 = new Object[] {
people2.getMoney() - people.getMoney(),
people.getName() };
jdbcTemplate.update(sql, params2);
System.out.println("剩余余额:"
+ (people2.getMoney() - people.getMoney()));
}
}
catch (Exception e) {
ts.setRollbackOnly();
}
// 如果成功,事务被提交
return people;
}
});
return people.getMoney();
}
}
调
用TransactionTemplate实例的execute()方法将执行包含在TransactionCallback实例里的代码。如果代码出现
异常,调用TransactionStatus对象的setRollbackOnly()将事务回滚。否则,如果doInTransaction()方法
正常返回,事务将被提交。
Spring学习8-Spring事务管理(编程式事务管理)的更多相关文章
- spring事务管理——编程式事务、声明式事务
本教程将深入讲解 Spring 简单而强大的事务管理功能,包括编程式事务和声明式事务.通过对本教程的学习,您将能够理解 Spring 事务管理的本质,并灵活运用之. 先决条件 本教程假定您已经掌握了 ...
- Spring 声明式事务与编程式事务详解
本文转载自IBM开发者论坛:https://developer.ibm.com/zh/articles/os-cn-spring-trans 根据自己的学习理解有所调整,用于学习备查. 事务管理对于企 ...
- 【spring 6】Spring和Hibernate的整合:编程式事务
一.编程式事务简介 在 Spring 出现以前,编程式事务管理对基于 POJO 的应用来说是唯一选择.用过 Hibernate 的人都知道,我们需要在代码中显式调用beginTransaction() ...
- spring的声明式事务和编程式事务
事务管理对于企业应用来说是至关重要的,当出现异常情况时,它可以保证数据的一致性. Spring事务管理的两种方式 1.编程式事务 使用Transaction Ttempleate或者直接使用底层的Pl ...
- 用Java+xml配置方式实现Spring数据事务(编程式事务)
一.用Java配置的方式 1.实体类: Role public class Role { private int id; private String roleName; private String ...
- Spring事务管理实现方式之编程式事务与声明式事务详解(转)
原文:https://blog.csdn.net/liaohaojian/article/details/70139151 编程式事务 编码方式实现事务管理(代码演示为JDBC事务管理) Spring ...
- Spring笔记(4) - Spring的编程式事务和声明式事务详解
一.背景 事务管理对于企业应用而言至关重要.它保证了用户的每一次操作都是可靠的,即便出现了异常的访问情况,也不至于破坏后台数据的完整性.就像银行的自助取款机,通常都能正常为客户服务,但是也难免遇到操作 ...
- Spring学习笔记(五):JDBCTemplate+事务管理
1 概述 Spring为开发者提供了JDBCTemplate,可以简化很多数据库操作相关的代码,本文主要介绍JDBCTemplate的使用以及事务管理功能. 2 JDBC Template 2.1 配 ...
- 全面分析 Spring 的编程式事务管理及声明式事务管理
开始之前 关于本教程 本教程将深入讲解 Spring 简单而强大的事务管理功能,包括编程式事务和声明式事务.通过对本教程的学习,您将能够理解 Spring 事务管理的本质,并灵活运用之. 先决条件 本 ...
随机推荐
- viewmodel
[ExtJS5学习笔记]第十节 Extjs5新增特性之ViewModel和DataBinding 2015-05-29 96 本文地址:http://blog.csdn.net/susheng ...
- 14SpringMvc_在业务控制方法中写入HttpServletRequest,HttpServletResponse等传统web参数(这个知识点知道就好了,不推荐这么去做)
这篇文章解决的问题是怎么在业务方法里面引入我们熟悉的HttpServletRequest和HttpServletRespon? 答案:这种引入传统的web参数的做法不推荐去做,因为这么做会实行高度耦合 ...
- sqlSQL2008如何创建定时作业(代理服务)(转)
SQL2008如何创建定时作业?此方法也适应于Sql Server2005数据库,有兴趣的可以来看下! 1.打开[SQL Server Management Studio],在[对象资源管理器]列表中 ...
- 【转】【WPF】wpf 图片指针处理
我一直用GDI+做Winform 的基于指针的图片处理,这次下决心全部移到wpf上(主要是显示布局很方便)采用的图片是2512*3307 的大图 830万像素类库基于WritableBitmapEx ...
- C语言 文件操作3--文件重定向与扫描
//文件重定向和扫描 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> //fprint ...
- Android Studio介绍
参考资料:http://www.cnblogs.com/smyhvae/p/4390905.html 第一次使用Android Studio时你应该知道的一切配置 as是一种不错的开发Androi ...
- Word 文档插入时间日期禁止自动更新
前些天写了点总结并插入时间和日期,记得勾掉了那个自动更新的,但是刚才打开时发现当时的日期和时间变成现在的了,我就纳闷了,然后我去看那插入日期和时间的那个框,里面确实没有勾选自动更新,于是百度, 百度都 ...
- 20145215《Java程序设计》第1周学习总结
20145215<Java程序设计>第一周学习总结 教材学习内容总结 本周先学习了最基本的java环境的搭建. 首先从官网上下载了jdk(jdk与jre的区别在于如果只需要运行一个开发好的 ...
- TableCell高度的控制
TableCell高度的控制 计算并指定行高rowHeight 强制指定:self.tableView.rowHeight = 88 或实现UITableViewDelegate.tableView( ...
- sql server 2008 基础知识
一.配置管理器 1.管理服务 使用配置管理器可以启动.停止.重新启动.继续或暂停服务. 服务器和客户端网络协议 2.SQLSMS 简介:SQLSMS是一个集成环境,用于访问.配置.管理和开发SQL ...