詳解Java的MyBatis框架中的事務處置。本站提示廣大學習愛好者:(詳解Java的MyBatis框架中的事務處置)文章只能為提供參考,不一定能成為您想要的結果。以下是詳解Java的MyBatis框架中的事務處置正文
1、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(); // 封閉會話,釋放資本 } } }
2、和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對象:
<bean id="transactionManager" class="org.springframework.jdbc.datasource .DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
指定的DataSource普通可所以你應用Spring的隨意率性JDBC DataSource。這包括了銜接池和經由過程JNDI查找取得的DataSource。
要留意,為事務治理器指定的DataSource必需和用來創立SqlSessionFactoryBean的是統一個數據源,不然事務治理器就沒法任務了。
2.容器治理事務
假如你正應用一個JEE容器並且想讓Spring介入到容器治理事務中,那末Spring應當應用JtaTransactionManager或它的容器指定的子類來設置裝備擺設。做這件工作的最便利的方法是用Spring的事務定名空間:
<tx:jta-transaction-manager/>
在這類設置裝備擺設中,MyBatis將會和其它由容器治理事務設置裝備擺設的Spring事務資本一樣。Spring會主動應用隨意率性存在的容器事務,在下面附加一個SqlSession。 假如沒有開端事務,或許須要基於事務設置裝備擺設,Spring會開啟一個新的容器治理事務。
留意,假如你想應用容器治理事務,而不想應用Spring的事務治理,你就必需設置裝備擺設SqlSessionFactoryBean來應用根本的MyBatis的ManagedTransactionFactory而不是其它隨意率性的Spring事務治理器:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="transactionFactoryClass"> <value>org.apache.ibatis.transaction.managed.ManagedTransactionFactory"/> </property> </bean>
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(系列五)的基本上參加事務設置裝備擺設:
<!-- 事務治理器 --> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 事務注解驅動,標注@Transactional的類和辦法將具有事務性 --> <tx:annotation-driven transaction-manager="txManager" /> <bean id="userService" class="com.john.hbatis.service.UserService" />
辦事類:
@Service("userService") public class UserService { @Autowired IUserMapper mapper; public int batchUpdateUsersWhenException() { // 非事務性 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中添加:
<bean id="txTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <constructor-arg type="org.springframework.transaction.PlatformTransactionManager" ref="transactionManager" /> </bean>
在UserService類參加:
@Autowired(required = false) TransactionTemplate txTemplate; public int txUpdateUsersWhenExceptionViaTxTemplate() { int retVal = txTemplate.execute(new TransactionCallback<Integer>() { @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; }