已阅读5页,还剩4页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
spring事务属性 Spring声明式事务让我们从复杂的事务处理中得到解脱。使得我们再也无需要去处理获得连接、关闭连接、事务提交和回滚等这些操作。再也无需要我们在与事务相关的方法中处理大量的trycatchfinally代码。 我们在使用Spring声明式事务时,有一个非常重要的概念就是事务属性。事务属性通常由事务的传播行为,事务的隔离级别,事务的超时值和事务只读标志组成。我们在进行事务划分时,需要进行事务定义,也就是配置事务的属性。 Spring在TransactionDefinition接口中定义这些属性,以供PlatfromTransactionManager使用, PlatfromTransactionManager是spring事务管理的核心接口。 代码 1. TransactionDefinition 2. public interface TransactionDefinition 3. int getPropagationBehavior(); 4. int getIsolationLevel(); 5. int getTimeout(); 6. boolean isReadOnly(); 7. getTimeout()方法,它返回事务必须在多少秒内完成。 isReadOnly(),事务是否只读,事务管理器能够根据这个返回值进行优化,确保事务是只读的。 getIsolationLevel()方法返回事务的隔离级别,事务管理器根据它来控制另外一个事务可以看到本事务内的哪些数据。 在TransactionDefinition接口中定义了五个不同的事务隔离级别 ISOLATION_DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.另外四个与JDBC的隔离级别相对应 ISOLATION_READ_UNCOMMITTED 这是事务最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。 例如: Mary的原工资为1000,财务人员将Mary的工资改为了8000,但未提交事务 代码 1. Connection con1 = getConnection(); 2. con.setAutoCommit(false); 3. update employee set salary = 8000 where empId =Mary; 与此同时,Mary正在读取自己的工资 代码 1. Connection con2 = getConnection(); 2. select salary from employee where empId =Mary; 3. mit(); Mary发现自己的工资变为了8000,欢天喜地! 而财务发现操作有误,而回滚了事务,Mary的工资又变为了1000 代码 1. /con1 2. con1.rollback(); 像这样,Mary记取的工资数8000是一个脏数据。 ISOLATION_READ_COMMITTED 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。 ISOLATION_REPEATABLE_READ 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。 在事务1中,Mary 读取了自己的工资为1000,操作并没有完成 代码 1. con1 = getConnection(); 2. select salary from employee empId =Mary; 在事务2中,这时财务人员修改了Mary的工资为2000,并提交了事务. 代码 1. con2 = getConnection(); 2. update employee set salary = 2000; 3. mit(); 在事务1中,Mary 再次读取自己的工资时,工资变为了2000 代码 1. /con1 2. select salary from employee empId =Mary; 在一个事务中前后两次读取的结果并不一致,导致了不可重复读。 使用ISOLATION_REPEATABLE_READ可以避免这种情况发生。 ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。 目前工资为1000的员工有10人。 事务1,读取所有工资为1000的员工。 代码 1. con1 = getConnection(); 2. Select * from employee where salary =1000; 共读取10条记录 这时另一个事务向employee表插入了一条员工记录,工资也为1000 代码 1. con2 = getConnection(); 2. Insert into employee(empId,salary) values(Lili,1000); 3. mit(); 事务1再次读取所有工资为1000的员工 代码 1. /con1 2. select * from employee where salary =1000; 共读取到了11条记录,这就产生了幻像读。 ISOLATION_SERIALIZABLE能避免这样的情况发生。但是这样也耗费了最大的资源。 getPropagationBehavior()返回事务的传播行为,由是否有一个活动的事务来决定一个事务调用。 在TransactionDefinition接口中定义了七个事务传播行为。 PROPAGATION_REQUIRED 如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。 代码 1. /事务属性 PROPAGATION_REQUIRED 2. methodA 3. 4. methodB(); 5. 6. 7. 8. /事务属性 PROPAGATION_REQUIRED 9. methodB 10. 11. 使用spring声明式事务,spring使用AOP来支持声明式事务,会根据事务属性,自动在方法调用之前决定是否开启一个事务,并在方法执行之后决定事务提交或回滚事务。 单独调用methodB方法 代码 1. main 2. metodB(); 3. 相当于 代码 1. Main 2. Connection con=null; 3. 4. rry 5. con = getConnection(); 6. con.setAutoCommit(false); 7. /方法调用 8. methodB(); 9. /提交事务 10. mit(); 11. 12. Catch(RuntimeException ex) 13. /回滚事务 14. con.rollback(); 15. 16. finally 17. /释放资源 18. closeCon(); 19. 20. Spring保证在methodB方法中所有的调用都获得到一个相同的连接。在调用methodB时,没有一个存在的事务,所以获得一个新的连接,开启了一个新的事务。 单独调用MethodA时,在MethodA内又会调用MethodB. 执行效果相当于 代码 1. main 2. Connection con = null; 3. try 4. con = getConnection(); 5. methodA(); 6. mit(); 7. 8. cathc(RuntimeException ex) 9. con.rollback(); 10. 11. finally 12. closeCon(); 13. 14. 调用MethodA时,环境中没有事务,所以开启一个新的事务. 当在MethodA中调用MethodB时,环境中已经有了一个事务,所以methodB就加入当前事务。 PROPAGATION_SUPPORTS 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行。但是对于事务同步的事务管理器,PROPAGATION_SUPPORTS与不使用事务有少许不同。 代码d 1. /事务属性 PROPAGATION_REQUIRED 2. methodA() 3. methodB(); 4. 5. 6. /事务属性 PROPAGATION_SUPPORTS 7. methodB() 8. 9. 单纯的调用methodB时,methodB方法是非事务的执行的。 当调用methdA时,methodB则加入了methodA的事务中,事务地执行。 PROPAGATION_MANDATORY 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。 代码 1. /事务属性 PROPAGATION_REQUIRED 2. methodA() 3. methodB(); 4. 5. 6. /事务属性 PROPAGATION_MANDATORY 7. methodB() 8. 9. 当单独调用methodB时,因为当前没有一个活动的事务,则会抛出异常 throw new IllegalTransactionStateException(Transaction propagation mandatory but no existing transaction found); 当调用methodA时,methodB则加入到methodA的事务中,事务地执行。 PROPAGATION_REQUIRES_NEW 总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。 代码 1. /事务属性 PROPAGATION_REQUIRED 2. methodA() 3. doSomeThingA(); 4. methodB(); 5. doSomeThingB(); 6. 7. 8. /事务属性 PROPAGATION_REQUIRES_NEW 9. methodB() 10. 11. 当单独调用methodB时,相当于把methodb声明为REQUIRED。开启一个新的事务,事务地执行。 当调用methodA时 代码 1. main() 2. methodA(); 3. 情况有些大不一样.相当于下面的效果。 代码 1. main() 2. TransactionManager tm = null; 3. try 4. /获得一个JTA事务管理器 5. tm = getTransactionManager(); 6. tm.begin();/开启一个新的事务 7. Transaction ts1 = tm.getTransaction(); 8. doSomeThing(); 9. tm.suspend();/挂起当前事务 10. try 11. tm.begin();/重新开启第二个事务 12. Transaction ts2 = tm.getTransaction(); 13. methodB(); 14. mit();/提交第二个事务 15. 16. 17. Catch(RunTimeException ex) 18. ts2.rollback();/回滚第二个事务 19. 20. finally 21. /释放资源 22. 23. /methodB执行完后,复恢第一个事务 24. tm.resume(ts1); 25. doSomeThingB(); 26. mit();/提交第一个事务 27. 28. catch(RunTimeException ex) 29. ts1.rollback();/回滚第一个事务 30. 31. finally 32. /释放资源 33. 34. 在这里,我把ts1称为外层事务,ts2称为内层事务。从上面的代码可以看出,ts2与ts1是两个独立的事务,互不相干。Ts2是否成功并不依赖于ts1。如果methodA方法在调用methodB方法后的doSomeThingB方法失败了,而methodB方法所做的结果依然被提交。而除了methodB之外的其它代码导致的结果却被回滚了。 使用PROPAGATION_REQUIRES_NEW,需要使用JtaTransactionManager作为事务管理器。 PROPAGATION_NOT_SUPPORTED 总是非事务地执行,并挂起任何存在的事务。 代码 1. /事务属性 PROPAGATION_REQUIRED 2. methodA() 3. doSomeThingA(); 4. methodB(); 5. doSomeThingB(); 6. 7. 8. /事务属性 PROPAGATION_NOT_SUPPORTED 9. methodB() 10. 11. 当单独调用methodB时,不启用任何事务机制,非事务地执行。 当调用methodA时,相当于下面的效果 代码 1. main() 2. TransactionManager tm = null; 3. try 4. /获得一个JTA事务管理器 5. tm = getTransactionManager(); 6. tm.begin();/开启一个新的事务 7. Transaction ts1 = tm.getTransaction(); 8. doSomeThing(); 9. tm.suspend();/挂起当前事务 10. methodB(); 11. /methodB执行完后,复恢第一个事务 12. tm.resume(ts1); 13. doSomeThingB(); 14. mit();/提交第一个事务 15. 16. catch(RunTimeException ex) 17. ts1.rollback();/回滚第一个事务 18. 19. finally 20. /释放资源 21. 22. 使用PROPAGATION_NOT_SUPPORTED,也需要使用JtaTransactionManager作为事务管理器。 PROPAGATION_NEVER 总是非事务地执行,如果存在一个活动事务,则抛出异常 代码 1. /事务属性 PROPAGATION_REQUIRED 2. methodA() 3. doSomeThingA(); 4. methodB(); 5. doSomeThingB(); 6. 7. 8. /事务属性 PROPAGATION_NEVER 9. 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; 代码 1. /事务属性 PROPAGATION_REQUIRED 2. methodA() 3. doSomeThingA(); 4. methodB(); 5. doSomeThingB(); 6. 7. 8. /事务属性 PROPAGATION_NESTED 9. methodB() 10. 11. 如果单独调用methodB方法,则按REQUIRED属性执行。 如果调用methodA方法,相当于下面的效果 代码 1. main() 2. Connection con = null; 3. Savepoint savepoint = null; 4. try 5. con = getConnection(); 6. con.setAutoCommit(false); 7. doSomeThingA(); 8. savepoint = con2.setSavepoint(); 9. try 10. methodB(); 11. catch(RuntimeException ex) 12. con.rollback(savepoint); 13. 14. finally 15. /释放资源 16. 17. 18. doSo
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 水生动物苗种繁育工岗前潜力考核试卷含答案
- 水产捕捞工操作知识模拟考核试卷含答案
- 钢筋混凝土预制桩施工质量保证措施
- 装配式过街天桥速装指南
- 智慧斑马线车路协同系统建设方案
- 智能道路病害检测机器人应用手册
- 化工吸收工岗中实施考核试卷含答案
- 生漆加工工安全宣贯竞赛考核试卷含答案
- 劳务派遣管理员技巧竞赛考核试卷含答案
- 水下钻井设备操作工安全行为水平考核试卷含答案
- 2026年中心血站采血医技岗医疗卫生事业招聘考试笔试试题(含答案)
- 山东能源定向委培考试题
- 无水乙醇在脏器囊肿硬化治疗中合理性应用的专家共识
- 癫痫患者发作急救流程及日常护理建议
- 银行-从年报透析上市银行资产质量
- 山西省长治市2026年重点学校小升初入学分班考试英语考试试题及答案
- 2025年全国青少年信息素养大赛C++算法创意实践挑战赛(小学组-复赛)真题(含答案)
- 上海国际货币经纪有限责任公司招聘笔试题库2026
- NB-T31129-2018风力发电机组振动状态评价导则
- 城镇低效用地再开发信息管理平台建设解决方案
- 细胞与分子生物学
评论
0/150
提交评论