一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - 詳解Java的MyBatis框架中的事務處理

詳解Java的MyBatis框架中的事務處理

2020-05-08 11:53fhd001 JAVA教程

利用MyBatis框架的配置管理比直接使用JDBC API編寫事務控制要來得更加輕松,這里我們就來詳解Java的MyBatis框架中的事務處理,尤其是和Spring框架集成后更加exciting

一、MyBatis單獨使用時,使用SqlSession來處理事務

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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對象:

?
1
2
3
4
<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的事務命名空間:

?
1
<tx:jta-transaction-manager/>

在這種配置中,MyBatis將會和其它由容器管理事務配置的Spring事務資源一樣。Spring會自動使用任意存在的容器事務,在上面附加一個SqlSession。 如果沒有開始事務,或者需要基于事務配置,Spring會開啟一個新的容器管理事務。
注意,如果你想使用容器管理事務,而不想使用Spring的事務管理,你就必須配置SqlSessionFactoryBean來使用基本的MyBatis的ManagedTransactionFactory而不是其它任意的Spring事務管理器: 

?
1
2
3
4
5
6
<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事務之外任意調用映射器方法都將會自動被提交。下面是一個編程式事務示例:

?
1
2
3
4
5
6
7
8
9
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(系列五)的基礎上加入事務配置:

?
1
2
3
4
5
6
7
8
9
10
<!-- 事務管理器 -->
<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" />

服務類:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@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;
  }
}

在測試類中加入:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@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中添加:

?
1
2
3
<bean id="txTemplate" class="org.springframework.transaction.support.TransactionTemplate">
  <constructor-arg type="org.springframework.transaction.PlatformTransactionManager" ref="transactionManager" />
</bean>

在UserService類加入:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@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類中加入:

?
1
2
3
4
@Test
public void updateUsersWhenExceptionViaTxTemplateTest() {
  userService.txUpdateUsersWhenExceptionViaTxTemplate(); // 
}

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@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;
}

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 久久婷婷丁香五月色综合啪免费 | 欧美一区二区三区不卡视频 | 无人区尖叫之夜美女姐姐视频 | 日韩在线1 | 午夜办公室在线观看高清电影 | 国产拍拍拍| 黑帮少爷爱上我第8集在线观看 | 日本高清中文 | 天堂成人在线 | 欧美日韩一区二区三区免费 | 丝袜兔女郎被啪在线观看91 | 青青青草国产 | 80s在线| 国产精品吹潮香蕉在线观看 | 国产成人精品福利色多多 | 精品久久久久久午夜 | 欧美国产日本高清不卡 | 青青草原免费在线视频 | 男人捅女人漫画 | 性刺激欧美三级在线现看中文 | 精品欧美一区二区在线观看欧美熟 | 高清一区| 我的奶头被客人吸的又肿又红 | 高h文道具 | 国产成人在线视频 | 国产精品二区高清在线 | 精品免费久久久久久成人影院 | 欧美国产精品 | 欧美一级特黄aaa大片 | 99ri在线精品视频在线播放 | 麻豆资源| 日韩在线1 | 日本最新伦中文字幕 | 亚洲国产精品无码中文字满 | 男人疯狂擦进女人下面 | 国产裸舞在线一区二区 | 免费在线视频观看 | ak福利午夜在线观看 | 欧美大陆日韩一区二区三区 | 公交车揉捏大乳呻吟喘娇 | 福利片中文 |