• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

详解Java的MyBatis框架中的事务处理

java 搞代码 4年前 (2022-01-05) 28次浏览 已收录 0个评论

利用MyBatis框架的配置管理比直接使用JDBC API编写事务控制要来得更加轻松,这里我们就来详解Java的MyBatis框架中的事务处理,尤其是和Spring框架集成后更加exciting

一、MyBatis单独使用时,使用SqlSession来处理事务:

 public class MyBatisTxTest { private static SqlSessionFactory sqlSessionFactory; private static Reader reader; @BeforeClass public static void setUpBeforeClass() throws Exception { try { reader = Resources.getResourceAsReader("Configuration.xml"); sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); } finally { if (reader != null) { reader.close(); } } } @Test public void updateUserTxTest() { SqlSession session = sqlSessionFactory.openSession(false); // 打开会话,事务开始 try { IUserMapper mapper = session.getMapper(IUserMapper.class); User user = new User(9, "Test transaction"); int affectedCount = mapper.updateUser(user); // 因后面的异常而未执行commit语句 User user = new User(10, "Test transaction continuously"); int affectedCount2 = mapper.updateUser(user2); // 因后面的异常而未执行commit语句 int i = 2 / 0; // 触发运行时异常 session.commit(); // 提交会话,即事务提交 } finally { session.close(); // 关闭会话,释放资源 } } } 

二、和Spring集成后,使用Spring的事务管理:
一个使用MyBatis-Spring的主要原因是它允许MyBatis参与到Spring的事务管理中。而不是给MyBatis创建一个新的特定的事务管理器,MyBatis-Spring利用了存在于Spring中的DataSourceTransactionManager。
一旦DataSourceTransactionManager配置好了,你可以在Spring中以你通常的做法来配置事务。@Transactional注解和AOP样式的配置都是支持的。在事务处理期间,一个单独的SqlSession对象将会被创建和使用。当事务完成时,这个session会以合适的方式提交或回滚。
一旦事务创建之后,MyBatis-Spring将会透明的管理事务。在你的DAO或Service类中就不需要额外的代码了。

1.标准配置
要开启Spring的事务处理,在Spring的XML配置文件中简单创建一个DataSourceTransactionManager对象:

  

指定的DataSource一般可以是你使用Spring的任意JDBC DataSource。这包含了连接池和通过JNDI查找获得的DataSource。
要注意,为事务管理器指定的DataSource必须和用来创建SqlSessionFactoryBean的是同一个数据源,否则事务管理器就无法工作了。
 
2.容器管理事务
如果你正使用一个JEE容器而且想让Spring参与到容器管理事务中,那么Spring应该使用JtaTransactionManager或它的容器指定的子类来配置。做这件事情的最方便的方式是用Spring的事务命名空间:

 

在这种配置中,MyBatis将会和其它由容器管理事务配置的Spring事务资源一样。Spring会自动使用任意存在的容器事务,在上面附加一个SqlSession。 如果没有开始事务,或者需要基于事务配置,Spring会开启一个新的容器管理事务。
注意,如果你想使用容器管理事务,而不想使用Spring的事务管理,你就必须配置SqlSessionFactoryBean来使用基本的MyBatis的ManagedTransactionFactory而不是其它任意的Spring事务管理器: 

   org.apache.ibatis.transaction.managed.ManagedTransactionFactory"/> 

 
3.编程式事务管理
MyBatis的SqlSession提供指定的方法来处理编程式的事务。但是当使用MyBatis-Spring时,bean将会使用Spring管理的SqlSession或映射器来注入。那就是说Spring通常是处理事务的。你不能在Spring管理的SqlSession上调用SqlSession.commit(),SqlSession.rollback()或SqlSession.close()方法。如果这样做了,就会抛出UnsupportedOperationException异常。注意在使用注入的映射器时不能访问那些方法。无论连接是否设置为自动提交,SqlSession数据方法的执行或在Spring事务之外任意调用映射器方法都将会自动被提交。下面是一个编程式事务示例:

 DefaultTransactionDefinition def = new DefaultTransactionDefinition(); def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); TransactionStatus status = txManager.getTransaction(def); try{ userMapper.insertUser(user); }catch(MyException ex){ throw ex; } txManager.commit(status); 

4.@Transactional方式:

在类路径下创建beans-da-tx.xml文件,在beans-da.xml(系列五)的基础上加入事务配置:

 <!-- 事务管理器 --> <!-- 事务注解驱动,标注@Transactional的类和方法将具有事务性 -->

服务类:

 @Service("userService") public class UserService { @Autowired IUserMapper mapper; public int batchUpdateUsersWh<a style="color:transparent">来源gao($daima.com搞@代@#码网</a>enException() { // 非事务性 User user = new User(9, "Before exception"); int affectedCount = mapper.updateUser(user); // 执行成功 User user2 = new User(10, "After exception"); int i = 1 / 0; // 抛出运行时异常 int affectedCount2 = mapper.updateUser(user2); // 未执行 if (affectedCount == 1 && affectedCount2 == 1) { return 1; } return 0; } @Transactional public int txUpdateUsersWhenException() { // 事务性 User user = new User(9, "Before exception"); int affectedCount = mapper.updateUser(user); // 因后面的异常而回滚 User user2 = new User(10, "After exception"); int i = 1 / 0; // 抛出运行时异常,事务回滚 int affectedCount2 = mapper.updateUser(user2); // 未执行 if (affectedCount == 1 && affectedCount2 == 1) { return 1; } return 0; } } 

在测试类中加入:

 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:beans-da-tx.xml" }) public class SpringIntegrateTxTest { @Resource UserService userService; @Test public void updateUsersExceptionTest() { userService.batchUpdateUsersWhenException(); } @Test public void txUpdateUsersExceptionTest() { userService.txUpdateUsersWhenException(); } } 

5.TransactionTemplate方式

在beans-da-tx.xml中添加:

  

在UserService类加入:

 @Autowired(required = false) TransactionTemplate txTemplate; public int txUpdateUsersWhenExceptionViaTxTemplate() { int retVal = txTemplate.execute(new TransactionCallback() { @Override public Integer doInTransaction(TransactionStatus status) { // 事务操作 User user = new User(9, "Before exception"); int affectedCount = mapper.updateUser(user); // 因后面的异常而回滚 User user2 = new User(10, "After exception"); int i = 1 / 0; // 抛出运行时异常并回滚 int affectedCount2 = mapper.updateUser(user2); // 未执行 if (affectedCount == 1 && affectedCount2 == 1) { return 1; } return 0; } }); return retVal; } 

在SpringIntegrateTxTest类中加入:

 @Test public void updateUsersWhenExceptionViaTxTemplateTest() { userService.txUpdateUsersWhenExceptionViaTxTemplate(); // } 

注:不可catch Exception或RuntimeException而不抛出:

 @Transactional public int txUpdateUsersWhenExceptionAndCatch() { // 事务性操作,但是外围框架捕获不到异常,认为执行正确而提交。 try { User user = new User(9, "Before exception"); int affectedCount = mapper.updateUser(user); // 执行成功 User user2 = new User(10, "After exception"); int i = 1 / 0; // 抛出运行时异常 int affectedCount2 = mapper.updateUser(user2); // 未执行 if (affectedCount == 1 && affectedCount2 == 1) { return 1; } } catch (Exception e) { // 所有异常被捕获而未抛出 e.printStackTrace(); } return 0; } 

以上就是详解Java的MyBatis框架中的事务处理的详细内容,更多请关注gaodaima搞代码网其它相关文章!


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:详解Java的MyBatis框架中的事务处理

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址