作者:郭無心
鏈接:https://www.zhihu.com/question/30206875/answer/84675373
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
http://czj4451.iteye.com/blog/2037759
一、單獨使用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的事務管理: <!-- 數據源 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" lazy-init="true">
<property name="driverClassName">
<value>org.logicalcobwebs.proxool.ProxoolDriver</value>
</property>
<property name="url">
<value>proxool.gcld</value>
</property>
</bean>
<!-- sessionFactory -->
<bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:mybatis-config.xml">
</property>
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 事務管理器 -->
<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();
}
}
================================================================================
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="yourDataSource" />
</bean>
@Transactional
public void blabla(){
}