MyBatis进行批次操作

文章目录


在项目中,遇到这样一种情况,需要批量插入一些数据。在XML中配置的基本sql如下:

<insert id="addMenuRole">
	insert into fyk_role_menu
	  (role_id, menu_id)
	values
	  (#{roleId}, #{menuId})
</insert>

很显然,只要重复调用addMenuRole方法,就可以了,但是这样会有性能问题(每执行一次,就会和数据库交互一次)。
所以最好的方式就是将这些操作打个批次 ,一次性提交到数据库。(当然,可以使用foreach元素来循环集合,但是这个会基于不同的数据库,导致这个sql不一样:比如mysql和oracle中的批量插入方式就不一样)

批次操作

核心代码如下:

@Autowired
private SqlSessionFactory sqlSessionFactory;

@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public Boolean addMenuRole(String roleId, List<String> menuIds) {
    
    
	try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH)) {
    
    
		RoleDao batchRoleDao = sqlSession.getMapper(RoleDao.class);
		for (String menuId : menuIds) {
    
    
			batchRoleDao.addMenuRole(roleId, menuId);
		}
		sqlSession.flushStatements();
	}
	return Boolean.TRUE;
}

大致的意思就是:通过openSession方法,打开session,然后依次调用addMenuRole方法,只是这里并没有把该操作提交到数据库,而是在sqlSession.flushStatements()执行,才是将这些操作,一次性提交到数据库。
这里需要提醒两点:

  • 批次是不包含事务的。例如:这个批次会执行10条语句,前5条成功执行,第6条出错,前5条并不会回滚。所以,应该用事务进行处理,这里使用了@Transactional注解;
  • SqlSession 在使用完了,一定要关闭,这里使用了带资源的try语句。当然也可以使用sqlSession.close()语句来手动关闭。

补充

以下介绍几个在Mybatis中很重要的对象:

  • SqlSessionFactoryBuilder:可以在任何时候被实例化、使用和销毁。一旦创造了SqlSessionFactory就不需要再保留它了。所以它的最好的作用域是方法体内(即一个本地方法变量)。可以重用SqlSessionFactoryBuilder创建多个SqlSessionFactory实例,但最好不要把时间、资源放在解析XML文件上,而是要从中解放出来做最重要的事情。
  • SqlSessionFactory一旦创建,将会存在于应用程序的整个运行生命周期中。很少或根本没有理由去销毁它或重建它。最佳实践是不要在一个应用中多次创建SqlSessionFactory。所以SqlSessionFactory最好的作用域范围是一个应用的生命周期范围。
  • SqlSession:是与Mybatis一起工作的基本java接口。通过这个接口,你可以执行命令、获得映射和管理事务。每个线程都有一个SqlSession实例,SqlSession实例是不被共享的,并且不是线程安全的。因此最好的作用域是request或者method。决不要用一个静态字段或者一个类的实例字段来保存SqlSession实例引用,也不要用任何一个管理作用域,来保存SqlSession的引用。注意:如果是自己打开了SqlSession,则在使用完之后要记得关闭
  • Mapper实例:Mapper是创建来绑定映射语句的接口,该Mapper实例是从SqlSession得到的。因此所有的Mapper实例的作用域跟它创建它的SqlSession一样,但是Mapper最好的作用域是method,也就是他们应该在方法内被调用,使用完即被销毁。并且Mapper实例不用显示地被关闭

猜你喜欢

转载自blog.csdn.net/fyk844645164/article/details/100992200