1、getTimeout()方法,它返回事务必须在多少秒内完成。isReadOnly(),事务是否只读,事务管理器能够根据这个返回值进行优化,确保事务是只读的。getIsolationLevel()方法返回事务的隔离级别,事务管理器根据它来控制另外一个事务可以看到本事务内的哪些数据。在TransactionDefinition接口中定义了五个不同的事务隔离级别 ISOLATION_DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.另外四个与JDBC的隔离级别相对应 ISOLATION_READ_UNCOMMITTED 这是事务
2、最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。 例如: Mary的原工资为1000,财务人员将Mary的工资改为了8000,但未提交事务 1. Connectioncon1=getConnection();2. con.setAutoCommit(false);3. updateemployeesetsalary8000whereempId=Mary; Connection con1 = getConnection(); con.setAutoCommit(false); update employee set salary = 8
3、000 where empId =与此同时,Mary正在读取自己的工资 con22. selectfrom3. mit();Connection con2 = getConnection();select salary from employee where empId =mit();Mary发现自己的工资变为了8000,欢天喜地!而财务发现操作有误,而回滚了事务,Mary的工资又变为了1000 1. /con1 2. con1.rollback();/con1 con1.rollback();像这样,Mary记取的工资数8000是一个脏数据。ISOLATION_READ_COMMITTED
4、保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。ISOLATION_REPEATABLE_READ 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。在事务1中,Mary 读取了自己的工资为1000,操作并没有完成 1. con1con1 = getConnection();select salary from employee empId =在事务2中,这时财务人员修改了Mar
5、y的工资为2000,并提交了事务. 1. con22. update2000;con2 = getConnection();update employee set salary = 2000;在事务1中,Mary 再次读取自己的工资时,工资变为了2000 在一个事务中前后两次读取的结果并不致,导致了不可重复读。使用ISOLATION_REPEATABLE_READ可以避免这种情况发生。ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。目前工资为1000的员工有10人。事务1,读取所有工资为1
6、000的员工。2. Select*=1000;Select * from employee where salary =1000;共读取10条记录 这时另一个事务向employee表插入了一条员工记录,工资也为1000 2. Insertintoemployee(empId,salary)values(Lili,1000);Insert into employee(empId,salary) values(事务1再次读取所有工资为1000的员工 select * from employee where salary =1000;共读取到了11条记录,这就产生了幻像读。ISOLATION_SER
7、IALIZABLE能避免这样的情况发生。但是这样也耗费了最大的资源。getPropagationBehavior()返回事务的传播行为,由是否有一个活动的事务来决定一个事务调用。在TransactionDefinition接口中定义了七个事务传播行为。PROPAGATION_REQUIRED 如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。1. /事务属性PROPAGATION_REQUIRED 2. methodA 3. 4. methodB();5. 6. 7. 8. /事务属性9. methodB 10. 11. /事务属性 PROPAGATION_REQUIREDme
8、thodAmethodB();methodB 使用spring声明式事务,spring使用AOP来支持声明式事务,会根据事务属性,自动在方法调用之前决定是否开启一个事务,并在方法执行之后决定事务提交或回滚事务。单独调用methodB方法 1. main metodB();3. main metodB();相当于 1. Main 2. Connectioncon=null;rry concon.setAutoCommit(false);7. /方法调用 8. methodB();9. /提交事务 10. mit();11. 12. Catch(RuntimeExceptionex) 13. /回
9、滚事务 14. con.rollback();15. 16. finally 17. /释放资源 18. closeCon();19. 20. MainConnection con=null; rry con = getConnection();/方法调用/提交事务Catch(RuntimeException ex) /回滚事务 con.rollback();finally /释放资源 closeCon();Spring保证在methodB方法中所有的调用都获得到一个相同的连接。在调用methodB时,没有一个存在的事务,所以获得一个新的连接,开启了一个新的事务。单独调用MethodA时,在M
10、ethodA内又会调用MethodB. 执行效果相当于 Connectionnull;try methodA();7. 8. cathc(RuntimeException9. 10. 11. finally 12. 13. 14. Connection con = null; try methodA(); mit();cathc(RuntimeException ex) 调用MethodA时,环境中没有事务,所以开启一个新的事务. 当在MethodA中调用MethodB时,环境中已经有了一个事务,所以methodB就加入当前事务。PROPAGATION_SUPPORTS 如果存在一个事务,支持
11、当前事务。如果没有事务,则非事务的执行。但是对于事务同步的事务管理器,PROPAGATION_SUPPORTS与不使用事务有少许不同。PROPAGATION_REQUIRED2. methodA() 4. 6. /事务属性PROPAGATION_SUPPORTS7. methodB() 8. 9. /事务属性 PROPAGATION_REQUIRED methodA() methodB();/事务属性 PROPAGATION_SUPPORTS methodB()单纯的调用methodB时,methodB方法是非事务的执行的。当调用methdA时,methodB则加入了methodA的事务中,事
12、务地执行。PROPAGATION_MANDATORY 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。PROPAGATION_MANDATORY/事务属性 PROPAGATION_MANDATORY 当单独调用methodB时,因为当前没有一个活动的事务,则会抛出异常 throw new IllegalTransactionStateException(Transaction propagation mandatory but no existing transaction found);当调用methodA时,methodB则加入到methodA的事务中,事务地执行。
13、PROPAGATION_REQUIRES_NEW 总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。doSomeThingA();5. doSomeThingB();PROPAGATION_REQUIRES_NEW9. methodB() doSomeThingA();doSomeThingB();/事务属性 PROPAGATION_REQUIRES_NEW 当单独调用methodB时,相当于把methodb声明为REQUIRED。开启一个新的事务,事务地执行。当调用methodA时 1. main() main()情况有些大不一样.相当于下面的效果。TransactionM
14、anagertm3. try /获得一个JTA事务管理器 getTransactionManager();tm.begin();/开启一个新的事务 Transactionts1tm.getTransaction();doSomeThing();tm.suspend();/挂起当前事务 11. /重新开启第二个事务 ts2/提交第二个事务 15. 16. Catch(RunTimeExceptionts2.rollback();/回滚第二个事务 19. 20. finally 21. 22. 23. /methodB执行完后,复恢第一个事务 24. tm.resume(ts1);25. doSo
15、meThingB();26. /提交第一个事务 27. 28. catch(RunTimeException29. ts1.rollback();/回滚第一个事务 30. 31. finally 32. 33. 34. TransactionManager tm = null;try /获得一个JTA事务管理器 tm = getTransactionManager(); tm.begin();/开启一个新的事务 Transaction ts1 = tm.getTransaction(); doSomeThing(); tm.suspend();/挂起当前事务/重新开启第二个事务 Transac
16、tion ts2 = tm.getTransaction();/提交第二个事务 Catch(RunTimeException ex) ts2.rollback();/回滚第二个事务 finally /methodB执行完后,复恢第一个事务 tm.resume(ts1);/提交第一个事务catch(RunTimeException ex) ts1.rollback();/回滚第一个事务在这里,我把ts1称为外层事务,ts2称为内层事务。从上面的代码可以看出,ts2与ts1是两个独立的事务,互不相干。Ts2是否成功并不依赖于ts1。如果methodA方法在调用methodB方法后的doSomeTh
17、ingB方法失败了,而methodB方法所做的结果依然被提交。而除了methodB之外的其它代码导致的结果却被回滚了。使用PROPAGATION_REQUIRES_NEW,需要使用JtaTransactionManager作为事务管理器。PROPAGATION_NOT_SUPPORTED 总是非事务地执行,并挂起任何存在的事务。/事务属性 PROPAGATION_NOT_SUPPORTED 当单独调用methodB时,不启用任何事务机制,非事务地执行。当调用methodA时,相当于下面的效果 13. doSomeThingB();16. catch(RunTimeException18. 19. finally 21. 22. do
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1