Mybatis Spring-交易管理

时间:2018-12-15 20:00:03

标签: spring mybatis spring-mybatis

说我有以下代码。请查阅。我在下面添加了我的问题:

Mybatis配置:

@Configuration
@ConfigurationProperties
public class MyMybatisConfiguration{

     @Bean
     public DataSource datasource(){
        //configure some db
     }

     @Bean
     public SqlSessionFactory sessionFactory(){
         SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
         ssfb.setDataSource(dataSource())
         return ssfb;
     }

     @Bean
     public SqlSessionTemplate sessionTemplate(){
         return new SqlSessionTemplate(sessionFactory());
     }


 }

服务层:

@Service
public class MyService{

    public MyDao myDao;

    public MyService(MyDao myDao){
       this.myDao = myDao;
    }

    public addItems(List<Item> items){

       for(Item item : items)
       {
           myDao.insertItem(item);
       }  

    }

    public addItemsBulk(List<String> items){

        myDao.insertItems(items)

    }

}

Dao层:

 @Repository
 public class MyDao {

      private SqlSessionTemplate tmp;

      @Autowired
      public MyDao(SqlSessionTemplate tmp){
          this.tmp = tmp;
      }


      public insertItem(Item item){
         sst.insert("insertItem", item)
      }

      public insertItems(List<Item> items){
         sst.insert("insertItems", items)
      }

    }

我假设在上面的示例中,如果有人调用了此方法

public addItems(List<Item> items){

  for(Item item : items)
  {
       myDao.insertItem(item);
  }  

}

与调用相比,性能会降低

 public addItemsBulk(List<String> items){

     myDao.insertItems(items)

 }

...由于 for循环的每次迭代,将发生以下情况:

  
      
  1. 会话模板使用会话工厂
  2.   
  3. 会话工厂创建会话,打开连接。
  4.   
  5. 会话工厂创建事务
  6.   
  7. 会话工厂执行插入
  8.   
  9. 会话工厂提交事务
  10.   
  11. 会话工厂关闭会话
  12.   

^因此,在此示例中,我假设:对于包含for循环的方法,将有多个会话,每个插入一个,每个会话有一个事务。


现在,如果在MyService类的顶部添加了 @Transactional 注释,会发生什么情况?

我假设两种情况下的性能相同,并且都是事件发生的顺序:

  
      
  1. 会话模板使用会话工厂
  2.   
  3. 会话工厂创建会话,打开连接。
  4.   
  5. 会话工厂创建事务
  6.   
  7. 会话工厂执行所有插入语句
  8.   
  9. 会话工厂提交事务
  10.   
  11. 会话工厂关闭会话
  12.   

^因此,在此示例中,我假设:对于包含for循环的方法,将有一个会话和一个事务。

我的推理是否正确?还是有缺陷?

1 个答案:

答案 0 :(得分:1)

您的问题与@Transactional无关,但与Mybatis的Executor.BATCH的用法(等效于prepareStatement.executeBatch())

比较原始解决方案和以下设置之间的区别:

将ExecutorType.BATCH添加到SqlSessionTemplate:

@Configuration
@ConfigurationProperties
public class MyMybatisConfiguration{

     ...

     @Bean
     public SqlSessionTemplate sessionTemplate(){
         return new SqlSessionTemplate(sessionFactory(), ExecutorType.BATCH);
     }

 }

声明方法flushStatements:

@Repository
public class MyDao {
      ....
      public flush(){
         sst.flushStatements();
      }
}

将冲洗添加到addItems

public addItems(List<Item> items){

  for(Item item : items)
  {
       myDao.insertItem(item);
       myDao.flush();
  }  

}