基于Oracle的Mybatis 批量插入
项目中会遇到这样的情况,一次性要插入多条数据到数据库中,有两种插入方法:
方法一:
Mybatis本身只支持逐条插入,比较笨的方法,就是遍历一个List,循环中逐条插入,比如下面这段代码
1 2 3 | for (Data d : ListData) { dataMapper.insertSelective(d); } |
这样做的后果就是效率严重低下,因为每次循环都要向数据库提交一次,数据少的时候看不出来,但是如果上千条,花费的时间就相当多了
方法二:
Mybatis本身是很灵活的,因为可以自己在XML文件中编写sql进行操作,那就可以一次性将插入到数据库中,这样只用向数据库提交一次,性能也可以提高不少。下面来看一个例子:
首先,在DataMapper.java 接口类中加入接口:
int batchInsert(List<Data> datas);
然后,在DataMapper.xml 中编写对应的实现sql,我使用的是oracle,如果是mysql或sqlserver,可能sql语句会略有区别吧:
1 2 3 4 5 6 7 8 9 10 | <insert id= "batchInsert" parameterType= "java.util.List" > insert into DATA (ID, TEXT, STAUTS) <foreach close= ")" collection= "list" item= "item" index= "index" open= "(" separator= "union" > select #{item.id,jdbcType=VARCHAR}, #{item.text,jdbcType=VARCHAR}, #{item.stauts,jdbcType=VARCHAR} from dual </foreach> </insert> |
最后,在需要批量插入Data数据的地方调用接口:
1 | dataMapper.batchInsert(ListData); |
说明一下xml文件的实现,使用foreach标签,是用来拼接内部的字符串,item就相当于一个指针,用来遍历list中的对象,将每一个item的属性值复制给内部sql之后,用union拼接起来,一次性执行一个长的sql语句。 如果我们从后台打印sql执行语句的话,会看到这样的sql语句
1 2 3 4 5 6 | insert into DATA (ID, TEXT, STAUTS) ( select ?, ?, ? from dual union select ?, ?, ? from dual union select ?, ?, ? from dual ) |
相对于第一个方法,第二个方法的代码量要多出很多,但是从性能方面考虑,不管插入多少条数据,都只用向数据库提交一次,这样效率就会大幅提升。
如果id 是使用 seq 自增长的呢?
1 2 3 4 5 6 7 8 | <insert id= "insertRoleMenu" > insert into ROLE_MENU_RELA (RM_ID, ROLE_ID, MENU_ID) select ROLE_MENU_RELA_SEQ.nextval,a.* from ( <foreach collection= "list" item= "rela" index= "index" separator= "union" open= "(" close= ")" > select #{rela.roleId,jdbcType=DECIMAL}, #{rela.menuId,jdbcType=DECIMAL} from dual </foreach> ) a </insert> |
这里传入的参数为 List<ROLE_MENU_RELA> list
然而,如果我传入的对象role如下:
1 2 3 4 5 | class role { int roleId; List<menu> list; } |
那么要插入 role与menu 的关系表数据的方法:
1 2 3 4 5 6 7 8 | <insert id= "insertRoleMenu" parameterType= "com.xxx.modules.sys.entity.Role" > begin <foreach collection= "menuList" item= "menu" index= "index" > insert into ROLE_MENU_RELA (RM_ID, ROLE_ID, MENU_ID) values (BPMP_SYS_ROLE_MENU_RELA_SEQ.nextval, #{roleId,jdbcType=DECIMAL}, #{menu.menuId,jdbcType=DECIMAL}); </foreach> end; </insert> |
将所有的sql 语句放入一个块中处理
作者:panie
出处:http://www.cnblogs.com/panie2015/
如果您希望与我交流互动,欢迎加我微信
本文内容为作者辛苦整理书写,欢迎转载,但请保留文章出处
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?