詳解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;
}