1. Spring的事务管理机制

  1. Spring事务管理高层抽象主要包括3个接口,Spring的事务主要是由他们共同完成的:
  2. PlatformTransactionManager:事务管理器—主要用于平台相关事务的管理
  3. TransactionDefinition 事务定义信息(隔离、传播、超时、只读)—通过配置如何进行事务管理。
  4. TransactionStatus:事务具体运行状态—事务管理过程中,每个时间点事务的状态信息。

1.1. PlatformTransactionManager事务管理器

该接口提供三个方法:

lcommit:提交事务

lrollback:回滚事务

lgetTransaction:获取事务状态

Spring为不同的持久化框架提供了不同PlatformTransactionManager接口实现类:

事务

说明

org.springframework.jdbc.datasource.DataSourceTransactionManager

使用Spring JDBC或iBatis 进行持久化数据时使用

org.springframework.orm.hibernate3.HibernateTransactionManager

使用Hibernate3.0版本进行持久化数据时使用

org.springframework.orm.jpa.JpaTransactionManager

使用JPA进行持久化时使用

org.springframework.jdo.JdoTransactionManager

当持久化机制是Jdo时使用

org.springframework.transaction.jta.JtaTransactionManager

使用一个JTA实现来管理事务,在一个事务跨越多个资源时必须使用

lDataSourceTransactionManager针对JdbcTemplate、MyBatis 事务控制 ,使用Connection(连接)进行事务控制 :

开启事务 connection.setAutoCommit(false);

提交事务 connection.commit();

回滚事务 connection.rollback();

lHibernateTransactionManager针对Hibernate框架进行事务管理, 使用Session的Transaction相关操作进行事务控制 :

开启事务 session.beginTransaction();

提交事务 session.getTransaction().commit();

回滚事务 session.getTransaction().rollback();

事务管理器的选择?

用户根据选择和使用的持久层技术,来选择对应的事务管理器。

1.2. TransactionDefinition事务定义信息

用来定义事务相关的属性的,给事务管理器用。

该接口主要提供的方法:

lgetIsolationLevel:获取隔离级别

lgetPropagationBehavior:获取传播行为

lgetTimeout:获取超时时间(事务的有效期)

lisReadOnly 是否只读(保存、更新、删除—对数据进行操作-变成可读写的,查询-设置这个属性为true,只能读不能写),事务管理器能够根据这个返回值进行优化。

这些事务的定义信息,都可以在配置文件中配置和定制。

1.2.1. 事务的隔离级别IsolationLevel

隔离级别

含义

DEFAULT

使用后端数据库默认的隔离级别(spring中的默认选择项)

READ_UNCOMMITED

允许你读取还未提交的改变了的数据。可能导致脏、幻、不可重复读

READ_COMMITTED

允许在并发事务已经提交后读取。可防止脏读,但幻读和 不可重复读仍可发生

REPEATABLE_READ

对相同字段的多次读取是一致的,除非数据被事务本身改变。可防止脏、不可重复读,但幻读仍可能发生。

SERIALIZABLE

完全服从ACID的隔离级别,确保不发生脏、幻、不可重复读。这在所有的隔离级别中是最慢的,它是典型的通过完全锁定在事务中涉及的数据表来完成的。

隔离级别

含义

DEFAULT

使用后端数据库默认的隔离级别(spring中的默认选择项)

READ_UNCOMMITED

允许你读取还未提交的改变了的数据。可能导致脏、幻、不可重复读

READ_COMMITTED

允许在并发事务已经提交后读取。可防止脏读,但幻读和 不可重复读仍可发生

REPEATABLE_READ

对相同字段的多次读取是一致的,除非数据被事务本身改变。可防止脏、不可重复读,但幻读仍可能发生。

SERIALIZABLE

完全服从ACID的隔离级别,确保不发生脏、幻、不可重复读。这在所有的隔离级别中是最慢的,它是典型的通过完全锁定在事务中涉及的数据表来完成的。

  1. 脏读:一个事务读取了另一个事务改写但还未提交的数据,如果这些数据被回滚,则读到的数据是无效的。
  2.  
  3. 不可重复读:在同一事务中,多次读取同一数据返回的结果有所不同。换句话说就是,后续读取可以读到另一事务已提交的更新数据。
  4.  
  5. 相反,“可重复读”在同一事务中多次读取数据时,能够保证所读数据一样,也就是,后续读取不能读到另一事务已提交的更新数据。
  6.  
  7. 幻读:一个事务读取了几行记录后,另一个事务插入一些记录,幻读就发生了。再后来的查询中,第一个事务就会发现有些原来没有的记录。

事务四大特性 ACID ---隔离性引发问题 ---- 解决事务的隔离问题 隔离级别

Mysql 默认隔离级别 REPEATABLE_READ

Oracle 默认隔离级别 READ_COMMITTED

1.2.2. 事务的传播行为PropagationBehavior

什么是事务的传播行为? 有什么作用?

事务传播行为用于解决两个被事务管理的方法互相调用问题

业务层两个方法面临的事务问题:

* 有些时候需要处于同一个事务(删除用户删除完成之后,需要同时删除用户对应的订单,需要事务回滚,例如商场工作人员删除订单业务),

* 有些时候不能在同一个事务(取款是一个事务操作,打印凭条是一个事务操作,例如ATM取款业务) !

事务的传播行为的7种类型:

事务传播行为类型

说明

PROPAGATION_REQUIRED

支持当前事务,如果不存在 就新建一个

PROPAGATION_SUPPORTS

支持当前事务,如果不存在,就不使用事务

PROPAGATION_MANDATORY

支持当前事务,如果不存在,抛出异常

PROPAGATION_REQUIRES_NEW

如果有事务存在,挂起当前事务,创建一个新的事务

PROPAGATION_NOT_SUPPORTED

以非事务方式运行,如果有事务存在,挂起当前事务

PROPAGATION_NEVER

以非事务方式运行,如果有事务存在,抛出异常

PROPAGATION_NESTED

如果当前事务存在,则嵌套事务执行只对DataSourceTransactionManager 起效

主要分为三大类:

l PROPAGATION_REQUIRED(默认值)、PROPAGATION_SUPPORTS、PROPAGATION_MANDATORY

支持当前事务, A调用B,如果A事务存在,B和A处于同一个事务 。

事务默认传播行为 REQUIRED。最常用的。

l PROPAGATION_REQUIRES_NEW、PROPAGATION_NOT_SUPPORTED、PROPAGATION_NEVER

不会支持原来的事务 ,A调用B, 如果A事务存在, B肯定不会和A处于同一个事务。

常用的事务传播行为:PROPAGATION_REQUIRES_NEW

l PROPAGATION_NESTED

嵌套事务 ,只对DataSourceTransactionManager有效 ,底层使用JDBC的SavePoint机制,允许在同一个事务设置保存点,回滚保存点

【面试题】REQUIRED、REQUIRES_NEW、NESTED 区分

REQUIRED:只有一个事务(默认,推荐)

REQUIRES_NEW:存在两个事务,如果事务存在,挂起事务,重新又开启了一个新的事务

NESTED:嵌套事务,事务可以设置保存点,回滚到保存点 ,选择提交或者回滚

1.3. TransactionStatus 事务状态

事务运行过程中,每个时间点事务状态信息 !

  flush(),给hibernate使用,底层发出sql的

  hasSavepoint():判断是否有保留点

  isCompleted():判断事务是否结束

  isNewTransaction():判断当前事务是否是新开的一个事务。

  isRollbackOnly():判断事务是否只能回滚

  setRollbackOnly():设置事务是否回滚

事务的结束:必须通过commit 确认事务提交,rollback作用标记为回滚。

数据库操作中,如果只是回滚,后面不操作,数据库在关闭连接的时候,自动发出了commit。

  1. try {
  2. 操作
  3. } catch (){
  4. rollback
  5. } finally {
  6. commit
  7. }

【三个事务超级接口对象之间的关系】

1) 首先用户管理事务,需要先配置TransactionManager(事务管理器)进行事务管理;

2)然后根据TransactionDefinition(事务定义信息、事务的管理方案),通过TransactionManager(事务管理器)进行事务管理;

3)最后事务运行过程中,每个时刻都可以通过获取TransactionStatus(事务状态)来了解事务的运行状态。

1.4. Spring事务管理两种方式

Spring 支持两种方式事务管理

一:编程式的事务管理

通过TransactionTemplate手动管理事务

在实际应用中很少使用,原因是要修改原来的代码,加入事务管理代码 (侵入性 )

二:声明式事务管理(XML配置文件方式或注解方式)

Spring的声明式事务是通过AOP实现的(环绕通知)

开发中经常使用(代码侵入性最小)--推荐使用!

注:后面会演示声明式事务管理的两种方式:xml配置文件方式和注解方式,不演示编程式方式

2.  声明式事务管理案例-转账(xml、注解)

2.1. 编写转账案例,引出事务管理问题

需求:账号转账,Tom账号取出1000元,存放到Jack账号上

第一步:创建工程(略)

第二步:配置文件

spring的配置文件:applicationContext.xml

  1. <!-- 引入外部文件 -->
  2. <context:property-placeholder location="classpath:db.properties" />
  3.  
  4. <!-- 配置数据源 -->
  5. <!-- c3p0连接池 -->
  6. <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
  7. <!-- 设置连接字符串 -->
  8. <property name="driverClass" value="${jdbcClass}" />
  9. <property name="jdbcUrl" value="${jdbcUrl}" />
  10. <property name="user" value="${user}" />
  11. <property name="password" value="${password}" />
  12. </bean>
  13.  
  14. <!-- 配置dao,注入jdbctemplate 对象-->
  15. <bean id="AccounDaoImpl" class="cn.itcast.spring.dao.AccounDaoImpl">
  16. <!-- 方案二:BookDao类继承JdbcDaoSupport,直接注入数据源,就拥有了jdbctempate对象 -->
  17. <property name="dataSource" ref="dataSource"/>
  18. </bean>

第三步:创建IAccountDao接口

  1. public interface IAccountDao {
  2. //转入
  3. public void in(String name,Double money);
  4. //转出
  5. public void out(String name,Double money);
  6. }

创建AccounDaoImpl实现类,实现了IAccountDao接口

  1. //账户操作持久层
  2. //技术方案:jdbctempate
  3. public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao {
  4.  
  5. //转入
  6. public void in(String name,Double money){
  7. String sql="update t_account set money = money+ ? where name = ?";
  8. super.getJdbcTemplate().update(sql, money,name);
  9. }
  10.  
  11. //转出
  12. public void out(String name,Double money){
  13. String sql="update t_account set money = money- ? where name = ?";
  14. super.getJdbcTemplate().update(sql, money,name);
  15. }
  16. }

第四步:建立service层,创建IAccountService接口,编写转账的业务代码:

  1. public interface IAccountService {
  2. //转账业务
  3. void transfer(String outName,String inName,Double money);
  4. }

创建AccountServiceImpl实现类,实现了IAccountService接口,编写转账的业务操作

  1. //掌握操作的业务层
  2. public class AccountServiceImpl implements IAccountService{
  3.  
  4. //注入dao(xml方式)
  5. private IAccountDao accountDao;
  6.  
  7. public void setAccountDao(IAccountDao accountDao) {
  8. this.accountDao = accountDao;
  9. }
  10.  
  11. //转账操作的业务逻辑
  12. public void transfer(String outName,String inName,Double money){
  13. //调用dao层
  14. //先取出
  15. accountDao.out(outName, money);
  16. //再转入
  17. accountDao.in(inName, money);
  18. }
  19. }

继续配置applicationContext.xml文件:

  1. <!-- 配置dao-->
  2. <bean id="accountDao" class="cn.dao.AccountDaoImpl">
  3. <!--注入数据源 -->
  4. <property name="dataSource" ref="dataSource"></property>
  5. </bean>
  6.  
  7. <!-- 配置service -->
  8. <bean id="accountService" class="cn.itcast.service.AccountServiceImpl">
  9. <!-- 注入dao -->
  10. <property name="accountDao" ref="accountDao"></property>
  11. </bean>

第五步:使用SpringTest进行测试

  1. @RunWith(SpringJUnit4ClassRunner.class)
  2. @ContextConfiguration(locations={"classpath:applicationContext.xml"})
  3. public class SpringTest {
  4. //注入测试的service
  5. @Autowired
  6. private IAccountService accountService;
  7.  
  8. //需求:账号转账,Tom账号取出1000元,存放到Jack账号上
  9. @Test
  10. public void testTransfer(){
  11. accountService.transfer("Tom", "Jack", 1000d);
  12. System.out.println("转账成功!");
  13. }
  14. }

但是发现问题:

事务管理问题:在Service层没有事务的情况下,如果出现异常,则会转账不成功,数据异常。

扩展:如果不配置事务,那么每一个数据库的操作都是单独的一个事务。

2.2. 方式一:XML配置方式

【操作思路】:

1、 确定目标:需要对AccountService 的 transfer方法,配置切入点

2、 需要Advice (环绕通知),方法前开启事务,方法后提交关闭事务

3、 配置切面和切入点

配置Advice通知:

Spring为简化事务的配置,提供了<tx:advice>来配置事务管理,也可以理解为该标签是spring为你实现好了的事务的通知增强方案。

第一步:导入jar包:

其中:

  1. com.springsource.org.aopalliance-1.0.0.jaraop切面编程
  2. com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar:注解开发切面
  3. spring-aop-3.2.0.RELEASE.jaraop切面编程
  4. spring-aspects-3.2.0.RELEASE.jar:注解开发切面
  5. spring-tx-3.2.0.RELEASE.jar:事务处理

第二步:配置spring文件applicationContext.xml

  1. <!-- 引入外部属性配置文件-->
  2. <context:property-placeholder location="classpath:db.properties"/>
  3.  
  4. <!-- 配置数据源 -->
  5. <!-- c3p0连接池 -->
  6. <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
  7. <property name="driverClass" value="${jdbc.className}" />
  8. <property name="jdbcUrl" value="${jdbc.url}" />
  9. <property name="user" value="${jdbc.user}" />
  10. <property name="password" value="${jdbc.password}" />
  11. </bean>
  12.  
  13. <!-- 配置dao -->
  14. <bean id="accountDao" class="cn.itcast.spring.dao.AccountDaoImpl">
  15. <!-- 注入数据源,才拥有jdbctemplate -->
  16. <property name="dataSource" ref="dataSource"/>
  17. </bean>
  18. <!-- 配置service -->
  19. <bean id="accountService" class="cn.itcast.spring.service.AccountServiceImpl">
  20. <!-- 注入dao -->
  21. <property name="accountDao" ref="accountDao"/>
  22. </bean>
  23.  
  24. <!-- 第一步:定义具体的平台事务管理器(DataSource事务管理器) -->
  25. <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  26. <!-- 注入数据源 -->
  27. <property name="dataSource" ref="dataSource"/>
  28. </bean>
  29.  
  30. <!-- 第二步:定义通知,通知中要处理的就是事务 -->
  31. <tx:advice id="txAdvice" transaction-manager="transactionManager">
  32. //注意:如果第一步的事务管理器id设为transactionManager,transaction-manager属性可以省略,默认
  33. <!-- 配置事务的属性定义 -->
  34. <tx:attributes>
  35. <!-- 配置具体的方法的事务属性
  36. name:事务添加在哪个方法上,需要自己定义
  37. Isolation:事务的隔离级别,默认是按数据库的隔离级别来
  38. Propagation:事务的传播行为,默认是同一个事务
  39. timeout="-1": 事务的超时时间,默认值使用数据库的超时时间。
  40. read-only="false": 事务是否只读,默认可读写。
  41. rollback-for: 遇到哪些异常就回滚,其他的都不回滚
  42. no-rollback-for:遇到哪些异常不回滚,其他的都回滚。和上面互斥的
  43. -->
  44. //method定义的方法都会添加事务管理
  45. <tx:method name="transfer" isolation="DEFAULT" propagation="REQUIRED" timeout="-1" read-only="false"/>
  46.  
  47. <!-- 支持通配符:切面中 方法名字符合下面规则的方法都会添加事务管理 -->
  48. <tx:method name="save*"/>
  49. <tx:method name="update*"/>
  50. <tx:method name="delete*"/>
  51. <tx:method name="find*" read-only="true"/>
  52. </tx:attributes>
  53. </tx:advice>
  54.  
  55. <!-- 第三步:配置切入点,让通知关联切入点,即事务控制业务层的方法 -->
  56. <aop:config>
  57. <!-- 切入点 -->
  58. <aop:pointcut expression="bean(*Service)" id="txPointcut"/>
  59. <!-- 切面 -->
  60. <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
  61. </aop:config>

使用SpringTest.java测试:

  1. @RunWith(SpringJUnit4ClassRunner.class)
  2. @ContextConfiguration(locations={"classpath:applicationContext.xml"})
  3. public class SpringTest {
  4. //注入测试的service
  5. @Autowired
  6. private IAccountService accountService;
  7.  
  8. //需求:账号转账,Tom账号取出1000元,存放到Jack账号上
  9. @Test
  10. public void testTransfer(){
  11. accountService.transfer("Tom", "Jack", 1000d);
  12. System.out.println("转账成功!");
  13. }
  14.  
  15. }

数据正常!

【声明式事务处理的原理图】

【注意】

如果不配置,则走默认的事务(默认事务是每个数据库操作都是一个事务,相当于没事务),所以我们开发时需要配置事务。

【补充了解】:

rollback-for属性:

注意事项:声明式事务处理对运行时异常有效,任何 RuntimeException 将触发事务回滚,但是任何 checked Exception 将不触发事务回滚

测试:applicationContext.xml:

遇到该异常事务不会回滚:

2.3. 方式二:注解方式

步骤:

1.在需要管理事务的方法或者类上面 添加@Transactional 注解

2.配置注解驱动事务管理(事务管理注解生效的作用)(需要配置对特定持久层框架使用的事务管理器)

第一步:确定目标(bean的方法):创建IAccountDao和AccountDaoImpl类

(1)IAccountDao接口

  1. public interface IAccountDao {
  2. //(存入)转入
  3. public void in(String name,Double money);
  4. //(取出)转出
  5. public void out(String name,Double money);
  6. }

(2)AccountDaoImpl

  1. //账户操作持久层
  2. //技术方案:jdbctempate
  3. /**
  4. * @Repository("accountDao")
  5. * 相当于容易中定义<bean id="accountDao" class="cn.itcast.spring.anntx.dao.AccountDaoImpl"/>
  6. */
  7. @Repository("accountDao")
  8. public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao {
  9.  
  10. /*
  11. 演示:注入数据源的错误方式:
  12. //注入数据源
  13. /*@Autowired
  14. private DataSource dataSource;
  15. //注入失败,@Autowired的原理是为属性生成setter方法通过setter方法注入,但是JdbcDaoSupport 类有setter方法方法且为最终方法,不可重写
  16. 注意:xml配置与注解注入数据源的区别:xml配置是在配置文件中注入数据源到dao,不生成setter方法,注解注入的@Autowired会底层生成setter方法,
  17. */
  18.  
  19. //注入数据源的正确方式:自定义方法,在方法内调用父类方法注入数据源
  20. @Autowired //当初始化dao的时候,会调用该方法,通过set方法的形参注入数据源
  21. public void setSuperDataSource(DataSource dataSource){ //方法名自定义
  22. //调用父类的setDataSource方法,注入数据源
  23. super.setDataSource(dataSource);
  24. }
  25.  
  26. //(存入)转入
  27. public void in(String name,Double money){
  28. String sql="update t_account set money = money+ ? where name = ?";
  29. super.getJdbcTemplate().update(sql, money,name);
  30. }
  31.  
  32. //(取出)转出
  33. public void out(String name,Double money){
  34. String sql="update t_account set money = money- ? where name = ?";
  35. super.getJdbcTemplate().update(sql, money,name);
  36. }
  37. }

创建IAccountService和AccountServiceImpl类

(1)IAccountService接口

  1. public interface IAccountService {
  2. void transfer(String outName,String inName,Double money);
  3. }

(2)AccountServiceImpl

  1. //掌握操作的业务层
  2. /**
  3. * @Service("accountService")
  4. * 相当于spring容器中定义:<bean id="accountService" class="cn.itcast.spring.anntx.service.AccountServiceImpl">
  5. */
  6. @Service("accountService")
  7. @Transactional //在类上添加事务管理,自动对类中所有的公有的方法添加事务
  8. public class AccountServiceImpl implements IAccountService{
  9.  
  10. //注入dao
  11. @Autowired
  12. private IAccountDao accountDao;
  13.  
  14. //转账操作的业务逻辑
  15. @Transactional //在方法上添加事务管理,事务管理只在此方法上
  16. public void transfer(String outName,String inName,Double money){
  17.  
  18. //调用dao层
  19. //先取出
  20. accountDao.out(outName, money);
  21. //异常
  22. int d = 1/0;
  23. //再转入
  24. accountDao.in(inName, money);
  25. }
  26.  
  27. @Transactional(readOnly=true) //在方法和类上同时定义了事务的属性,且属性值不同,局部会覆盖全局
  28. public void findAccount(){
  29. System.out.println("查询帐号的信息了");
  30. }
  31. }

第二步:创建applicationContext-tx.xml在applicationContext-tx.xml中配置:

  1. <!-- 引入外部属性文件 -->
  2. <context:property-placeholder location="classpath:db.properties" />
  3.  
  4. <!-- 配置数据源 -->
  5. <!-- c3p0连接池 -->
  6. <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
  7. <property name="driverClass" value="${jdbc.className}" />
  8. <property name="jdbcUrl" value="${jdbc.url}" />
  9. <property name="user" value="${jdbc.user}" />
  10. <property name="password" value="${jdbc.password}" />
  11. </bean>
  12.  
  13. <!-- 配置bean注解扫描 -->
  14. <context:component-scan base-package="cn.itcast.spring.anntx"/>
  15.  
  16. <!-- 事务管理 -->
  17. <!-- 配置事务管理器(DataSource事务管理器) -->
  18. <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  19. <!-- 注入数据源 -->
  20. <property name="dataSource" ref="dataSource"/>
  21. </bean>
  22.  
  23. <!-- 配置事务注解驱动 :识别事务的注解@tr
  24. transaction-manager:具体的平台事务管理器
  25. -->
  26. <!-- 默认的平台事务管理器的名字叫:transactionManager,如果与自定义的事务管理器id相同,transaction-manager="transactionManager"可以省略 -->
  27. <tx:annotation-driven transaction-manager="transactionManager"/>

【注意】:方法与类添加事务管理:

(1)在需要管理事务的方法或者类上面 添加@Transactional 注解

(2)配置事务的定义属性信息,在注解中直接配置:

[扩展]

如果 @Transactional 标注在 Class 上面, 那么将会对这个 Class 里面所有的 public 方法都包装事务方法。等同于该类的每个公有方法都放上了@Transactional。

如果某方法需要单独的事务定义,则需要在方法上加@Transactional来覆盖类上的标注声明。 记住:方法级别的事务覆盖类级别的事务

  1. //掌握操作的业务层
  2. /**
  3. * @Service("accountService")
  4. * 相当于spring容器中定义:<bean id="accountService" class="cn.itcast.spring.anntx.service.AccountServiceImpl">
  5. */
  6. @Service("accountService")
  7. @Transactional() //会对该类中,所有的共有的方法,自动加上事务--全局的设置,默认是可写
  8. public class AccountServiceImpl implements IAccountService{
  9.  
  10. //注入dao
  11. @Autowired
  12. private IAccountDao accountDao;
  13.  
  14. //转账操作的业务逻辑
  15. @Transactional(readOnly=false)//在方法上添加事务
  16. public void transfer(String outName,String inName,Double money){
  17. //调用dao层
  18. //先取出
  19. accountDao.out(outName, money);
  20. int d = 1/0;
  21. //再转入
  22. accountDao.in(inName, money);
  23.  
  24. }
  25.  
  26. @Transactional(readOnly=true) //使用局部覆盖全局的
  27. public void findAccount(){
  28. System.out.println("查询帐号的信息了");
  29. }
  30. }

2.4. 小结-xml和注解的选择

XML配置方式和注解配置方式 进行事务管理 哪种用的多?

XML方式,集中式维护,统一放置到applicationContext.xml文件中,缺点在于配置文件中的内容太多。

使用@Transactional注解进行事务管理,配置太分散,使用XML进行事务管理,属性集中配置,便于管理和维护

注意:以后的service的方法名字的命名,必须是上面规则,否则,不能被spring事务管理。!!!!

即以save开头的方法,update开头的方法,delete开头的方法,表示增删改的操作,故事务为可写

以find开头的方法,表示查询,故事务为只读

(1)xml方式小结

(2)注解方式小结

spring3-spring的事务管理机制的更多相关文章

  1. [转]Spring3核心技术之事务管理机制

    原文地址:http://chouyi.iteye.com/blog/1675199 Spring对事务的解决办法其实分为2种:编程式实现事务,AOP配置声明式解决方案. http://jinnians ...

  2. Spring事务管理机制的实现原理-动态代理

    之前在做项目中遇到spring无法进行事务代理问题,最后发现是因为没有写接口,原因当时明白了,看到这篇文章写的清楚些,转过来 我们先来分析一下Spring事务管理机制的实现原理.由于Spring内置A ...

  3. spring笔记--事务管理之声明式事务

    事务简介: 事务管理是企业级应用开发中必不可少的技术,主要用来确保数据的完整性和一致性, 事务:就是一系列动作,它们被当作一个独立的工作单元,这些动作要么全部完成,要么全部不起作用. Spring中使 ...

  4. 关于spring中事务管理的几件小事

    1.Spring中的事务管理 作为企业级应用程序框架,Spring在不同的事务管理API之上定义了一个抽象层.而应用程序开发人员不必了解底层的事务管理API,就可以使用Spring的事务管理机制. S ...

  5. 【Spring】Spring的事务管理 - 2、声明式事务管理(实现基于XML、Annotation的方式。)

    声明式事务管理 文章目录 声明式事务管理 基于XML方式的声明式事务 基于Annotation方式的声明式事务 简单记录 - 简单记录-Java EE企业级应用开发教程(Spring+Spring M ...

  6. Spring入门5.事务管理机制

    Spring入门5.事务管理机制 20131126 代码下载 : 链接: http://pan.baidu.com/s/1kYc6c 密码: 233t 回顾之前的知识,Spring 最为核心的两个部分 ...

  7. spring 事务管理机制

    1. spring 事务管理抽象 spring 的事务策略机制的核心就是 org.springframework.transaction.PlatformTransactionManager 接口. ...

  8. Spring入门6事务管理2 基于Annotation方式的声明式事务管理机制

    Spring入门6事务管理2 基于Annotation方式的声明式事务管理机制 201311.27 代码下载 链接: http://pan.baidu.com/s/1kYc6c 密码: 233t 前言 ...

  9. Spring 框架基础(05):事务管理机制,和实现方式

    本文源码:GitHub·点这里 || GitEE·点这里 一.Spring事务管理 1.基础描述 Spring事务管理的本质就是封装了数据库对事务支持的操作,使用JDBC的事务管理机制,就是利用jav ...

随机推荐

  1. libnl3.2.25安装编译

    1,tar zxvf libnl-3.2.25.tar.gz 2,cd libnl-3.2.25 3,./configure --prefix=/usr  --sysconfdir=/etc  --d ...

  2. CPU测试--通过proc获取CPU信息

    adb shell cat /proc/stat | grep cpu > totalcpu0 此处第一行的数值表示的是CPU总的使用情况,所以我们只要用第一行的数字计算就可以了.下表解析第一行 ...

  3. 第181天:HTML5——视频、音频

    一.HTML5新增的video.source标签 <video width="320" height="240" controls="contr ...

  4. Qt中父子widget的事件传递

    以前我一直以为:在父widget上摆一个子widget后,当click子widget时:只会进入到子widget的相关事件处理函数中,比如进入到mousePressEvent()中, 而不会进入到父w ...

  5. bzoj1211-树的计数

    题意 给出 \(n\) 和长度为 \(n\) 的数列 \(d\) 表示每个点的度数,问有多少颗满足要求的树. 分析 这题是prufer编码的应用. prufer编码是对一个带标号无根树的刻画,生成方式 ...

  6. 【bzoj3130】[Sdoi2013]费用流 二分+网络流最大流

    题目描述 Alice和Bob做游戏,给出一张有向图表示运输网络,Alice先给Bob一种最大流方案,然后Bob在所有边上分配总和等于P的非负费用.Alice希望总费用尽量小,而Bob希望总费用尽量大. ...

  7. 【poj2409】Let it Bead Polya定理

    题目描述 用 $c$ 种颜色去染 $r$ 个点的环,如果两个环在旋转或翻转后是相同的,则称这两个环是同构的.求不同构的环的个数. $r·c\le 32$ . 题解 Polya定理 Burnside引理 ...

  8. wp开发(二)--获取用户篇

    本文从个人开发者的角度来谈如何让wp应用获得尽可能多的用户.当然前提是你的app有一定的竞争性,如果不具备竞争力,那再多的用户下载也是白扯,所以最关键的还是要保证app的质量. 一. 程序图标 千万不 ...

  9. Count the string HDU - 3336

    题意: 求一个字符串的每个前缀在这个字符串中出现次数的加和 解析: 默默的骂一句...傻xkmp..博主心里气愤... 拓展kmp就好多了... 因为拓展kmp每匹配一次   就相当于这些前缀出现了一 ...

  10. 分治FFT

    目录 分治FFT 目的 算法 代码 分治FFT 目的 解决这样一类式子: \[f[n] = \sum_{i = 0}^{n - 1}f[i]g[n - i]\] 算法 看上去跟普通卷积式子挺像的,但是 ...