




已阅读5页,还剩6页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Spring声明式事务让我们从复杂的事务处理中得到解脱。使得我们再也无需要去处理获得连接、关闭连接、事务提交和回滚等这些操作。再也无需要我们在与事务相关的方法中处理大量的trycatchfinally代码。我们在使用Spring声明式事务时,有一个非常重要的概念就是事务属性。事务属性通常由事务的传播行为,事务的隔离级别,事务的超时值和事务只读标志组成。我们在进行事务划分时,需要进行事务定义,也就是配置事务的属性。Spring在TransactionDefinition接口中定义这些属性,以供PlatfromTransactionManager使用, PlatfromTransactionManager是spring事务管理的核心接口。Java代码1. TransactionDefinition2. publicinterfaceTransactionDefinition3. intgetPropagationBehavior();4. intgetIsolationLevel();5. intgetTimeout();6. booleanisReadOnly();7. getTimeout()方法,它返回事务必须在多少秒内完成。isReadOnly(),事务是否只读,事务管理器能够根据这个返回值进行优化,确保事务是只读的。getIsolationLevel()方法返回事务的隔离级别,事务管理器根据它来控制另外一个事务可以看到本事务内的哪些数据。在TransactionDefinition接口中定义了五个不同的事务隔离级别ISOLATION_DEFAULT这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.另外四个与JDBC的隔离级别相对应ISOLATION_READ_UNCOMMITTED这是事务最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。 例如: Mary的原工资为1000,财务人员将Mary的工资改为了8000,但未提交事务Java代码1. Connectioncon1=getConnection();2. con.setAutoCommit(false);3. updateemployeesetsalary=8000whereempId=Mary;与此同时,Mary正在读取自己的工资Java代码1. Connectioncon2=getConnection();2. selectsalaryfromemployeewhereempId=Mary;3. mit();Mary发现自己的工资变为了8000,欢天喜地!而财务发现操作有误,而回滚了事务,Mary的工资又变为了1000Java代码1. /con12. con1.rollback();像这样,Mary记取的工资数8000是一个脏数据。ISOLATION_READ_COMMITTED保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。ISOLATION_REPEATABLE_READ这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。在事务1中,Mary 读取了自己的工资为1000,操作并没有完成Java代码1. con1=getConnection();2. selectsalaryfromemployeeempId=Mary;在事务2中,这时财务人员修改了Mary的工资为2000,并提交了事务.Java代码1. con2=getConnection();2. updateemployeesetsalary=2000;3. mit();在事务1中,Mary 再次读取自己的工资时,工资变为了2000Java代码1. /con12. selectsalaryfromemployeeempId=Mary;在一个事务中前后两次读取的结果并不致,导致了不可重复读。使用ISOLATION_REPEATABLE_READ可以避免这种情况发生。ISOLATION_SERIALIZABLE这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。目前工资为1000的员工有10人。事务1,读取所有工资为1000的员工。Java代码1. con1=getConnection();2. Select*fromemployeewheresalary=1000;共读取10条记录这时另一个事务向employee表插入了一条员工记录,工资也为1000Java代码1. con2=getConnection();2. Insertintoemployee(empId,salary)values(Lili,1000);3. mit();事务1再次读取所有工资为1000的员工Java代码1. /con12. select*fromemployeewheresalary=1000;共读取到了11条记录,这就产生了幻像读。ISOLATION_SERIALIZABLE能避免这样的情况发生。但是这样也耗费了最大的资源。getPropagationBehavior()返回事务的传播行为,由是否有一个活动的事务来决定一个事务调用。在TransactionDefinition接口中定义了七个事务传播行为。PROPAGATION_REQUIRED如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。Java代码1. /事务属性PROPAGATION_REQUIRED2. methodA3. 4. methodB();5. 6. 7. 8. /事务属性PROPAGATION_REQUIRED9. methodB10. 11. 使用spring声明式事务,spring使用AOP来支持声明式事务,会根据事务属性,自动在方法调用之前决定是否开启一个事务,并在方法执行之后决定事务提交或回滚事务。单独调用methodB方法Java代码1. main2. metodB();3. 相当于Java代码1. Main2. Connectioncon=null;3. 4. rry5. con=getConnection();6. con.setAutoCommit(false);7. /方法调用8. methodB();9. /提交事务10. mit();11. 12. Catch(RuntimeExceptionex)13. /回滚事务14. con.rollback();15. 16. finally17. /释放资源18. closeCon();19. 20. Spring保证在methodB方法中所有的调用都获得到一个相同的连接。在调用methodB时,没有一个存在的事务,所以获得一个新的连接,开启了一个新的事务。单独调用MethodA时,在MethodA内又会调用MethodB.执行效果相当于Java代码1. main2. Connectioncon=null;3. try4. con=getConnection();5. methodA();6. mit();7. 8. cathc(RuntimeExceptionex)9. con.rollback();10. 11. finally12. closeCon();13. 14. 调用MethodA时,环境中没有事务,所以开启一个新的事务.当在MethodA中调用MethodB时,环境中已经有了一个事务,所以methodB就加入当前事务。PROPAGATION_SUPPORTS如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行。但是对于事务同步的事务管理器,PROPAGATION_SUPPORTS与不使用事务有少许不同。Java代码1. /事务属性PROPAGATION_REQUIRED2. methodA()3. methodB();4. 5. 6. /事务属性PROPAGATION_SUPPORTS7. methodB()8. 9. 单纯的调用methodB时,methodB方法是非事务的执行的。当调用methdA时,methodB则加入了methodA的事务中,事务地执行。PROPAGATION_MANDATORY 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。Java代码1. /事务属性PROPAGATION_REQUIRED2. methodA()3. methodB();4. 5. 6. /事务属性PROPAGATION_MANDATORY7. methodB()8. 9. 当单独调用methodB时,因为当前没有一个活动的事务,则会抛出异常throw new IllegalTransactionStateException(Transaction propagation mandatory but no existing transaction found);当调用methodA时,methodB则加入到methodA的事务中,事务地执行。PROPAGATION_REQUIRES_NEW总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。Java代码1. /事务属性PROPAGATION_REQUIRED2. methodA()3. doSomeThingA();4. methodB();5. doSomeThingB();6. 7. 8. /事务属性PROPAGATION_REQUIRES_NEW9. methodB()10. 11. 当单独调用methodB时,相当于把methodb声明为REQUIRED。开启一个新的事务,事务地执行。当调用methodA时Java代码1. main()2. methodA();3. 情况有些大不一样.相当于下面的效果。Java代码1. main()2. TransactionManagertm=null;3. try4. /获得一个JTA事务管理器5. tm=getTransactionManager();6. tm.begin();/开启一个新的事务7. Transactionts1=tm.getTransaction();8. doSomeThing();9. tm.suspend();/挂起当前事务10. try11. tm.begin();/重新开启第二个事务12. Transactionts2=tm.getTransaction();13. methodB();14. mit();/提交第二个事务15. 16. 17. Catch(RunTimeExceptionex)18. ts2.rollback();/回滚第二个事务19. 20. finally21. /释放资源22. 23. /methodB执行完后,复恢第一个事务24. tm.resume(ts1);25. doSomeThingB();26. mit();/提交第一个事务27. 28. catch(RunTimeExceptionex)29. ts1.rollback();/回滚第一个事务30. 31. finally32. /释放资源33. 34. 在这里,我把ts1称为外层事务,ts2称为内层事务。从上面的代码可以看出,ts2与ts1是两个独立的事务,互不相干。Ts2是否成功并不依赖于ts1。如果methodA方法在调用methodB方法后的doSomeThingB方法失败了,而methodB方法所做的结果依然被提交。而除了methodB之外的其它代码导致的结果却被回滚了。使用PROPAGATION_REQUIRES_NEW,需要使用JtaTransactionManager作为事务管理器。PROPAGATION_NOT_SUPPORTED 总是非事务地执行,并挂起任何存在的事务。Java代码1. /事务属性PROPAGATION_REQUIRED2. methodA()3. doSomeThingA();4. methodB();5. doSomeThingB();6. 7. 8. /事务属性PROPAGATION_NOT_SUPPORTED9. methodB()10. 11. 当单独调用methodB时,不启用任何事务机制,非事务地执行。当调用methodA时,相当于下面的效果Java代码1. main()2. TransactionManagertm=null;3. try4. /获得一个JTA事务管理器5. tm=getTransactionManager();6. tm.begin();/开启一个新的事务7. Transactionts1=tm.getTransaction();8. doSomeThing();9. tm.suspend();/挂起当前事务10. methodB();11. /methodB执行完后,复恢第一个事务12. tm.resume(ts1);13. doSomeThingB();14. mit();/提交第一个事务15. 16. catch(RunTimeExceptionex)17. ts1.rollback();/回滚第一个事务18. 19. finally20. /释放资源21. 22. 使用PROPAGATION_NOT_SUPPORTED,也需要使用JtaTransactionManager作为事务管理器。PROPAGATION_NEVER总是非事务地执行,如果存在一个活动事务,则抛出异常Java代码1. /事务属性PROPAGATION_REQUIRED2. methodA()3. doSomeThingA();4. methodB();5. doSomeThingB();6. 7. 8. /事务属性PROPAGATION_NEVER9. methodB()10. 11. 单独调用methodB,则非事务的执行。调用methodA则会抛出异常throw new IllegalTransactionStateException(Transaction propagation never but existing transaction found);PROPAGATION_NESTED如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行这是一个嵌套事务,使用JDBC 3.0驱动时,仅仅支持DataSourceTransactionManager作为事务管理器。需要JDBC 驱动的java.sql.Savepoint类。有一些JTA的事务管理器实现可能也提供了同样的功能。使用PROPAGATION_NESTED,还需要把PlatformTransactionManager的nestedTransactionAllowed属性设为true;而nestedTransactionAllowed属性值默认为false;Java代码1. /事务属性PROPAGATION_REQUIRED2. methodA()3. doSomeThingA();4. methodB();5. doSomeThingB();6. 7. 8. /事务属性PROPAGATION_NESTED9. methodB()10. 11. 如果单独调用methodB方法,则按REQUIRED属性执行。如果调用methodA方法,相当于下面的效果Java代码1. main()2. Connectioncon=null;3. Savepointsavepoint=null;4. try5. con=getConnection();6. con.setAutoCommit(false);7. doSomeThingA();8. savepoint=con2.setSavepoint();9. try10. methodB();11. catch(RuntimeExceptionex)12. con.rollback(savepoint);13. 14. finally15. /释放资源16. 17. 18. doSomeThingB();19. con.
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 稀土储氢材料工技能操作考核试卷及答案
- 激光头制造工5S管理考核试卷及答案
- 玻璃釉膜电阻器、电位器制造工抗压考核试卷及答案
- 在线学习服务师成本控制考核试卷及答案
- 2024版2025春新人音版艺术唱游音乐二年级上册(简谱)教学课件:第一单元 第2课 乃哟乃
- 中国特色社会主义建设及企业财务测试卷附答案
- 中医专业考研试题及答案
- 仓管员专业试题及答案
- 机车专业面试题目及答案
- 土壤专业试题及答案
- 工程流体力学教案
- 工业产品生产单位落实质量安全主体责任相关制度模板
- 七年级英语上册(人教版2024)新教材解读课件
- 中医师承跟师笔记50篇
- 血液透析高钾血症的护理查房
- 装配式建筑装饰装修技术 课件 模块六 集成厨房
- DZ/T 0461.3-2023 矿产资源定期调查规范 第3部分:外业工作(正式版)
- ISO28000:2022供应链安全管理体系
- 建筑与小区海绵城市建设技术规范
- 公司质量培训计划方案
- 供应商审计培训课件
评论
0/150
提交评论