MyBatis批量插入数据到数据库

一、SQL层面
先复习一下单条/批量插入数据的sql语句怎么写:
1. 单条插入数据的写法:
INSERT INTO [表名]
([列名],[列名]) 
 VALUES
([列值],[列值]))

2.一次性批量插入数据的sql语句的写法:
INSERT INTO [表名]
([列名],[列名]) 
 VALUES
([列值],[列值])),
([列值],[列值])),
([列值],[列值]));
批量的好处:可以避免程序和数据库建立多次连接,从而增加服务器负荷。

二、MyBatis层面如何完成批量插入
MyBatis批量插入数据到数据库有两种方式:xml文件,注解,笔者使用的数据库是MySQL。

方法一:xml配置
最基础的是用mapping.xml配置的方式,包括以下两种具体方式:
1. mapping.xml中insert语句可以写成单条插入,在调用方循环1000次
<!-- 在外部for循环调用1000次 -->
<insert id="insert" parameterType="sdc.mybatis.test.Student">
    insert into student (id, name, sex,
    address, telephone, t_id
    )
    values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR},
    #{sex,jdbcType=VARCHAR},
    #{address,jdbcType=VARCHAR}, #{telephone,jdbcType=VARCHAR}, #{tId,jdbcType=INTEGER}
    )
</insert>

2. mapping.xml中insert语句写成一次性插入一个1000的list

mapping.xml

 
  
< insert id ="insertBatch" >
insert into student ( < include refid ="Base_Column_List" /> )
values
< foreach collection ="list" item ="item" index ="index" separator =",">
(null,#{item.name},#{item.sex},#{item.address},#{item.telephone},#{item.tId})
</ foreach >
</ insert >
参数解释:
collection:指定要遍历的集合;
表示传入过来的参数的数据类型。该参数为必选。要做 foreach 的对象,作为入参时,List 对象默认用 list 代替作为键,数组对象有 array 代替作为键,Map 对象没有默认的键
item:将当前遍历出的元素赋值给指定的变量,然后用#{变量名},就能取出变量的值,也就是当前遍历出的元素
separator:每个元素之间的分隔符, select * from Emp where id in(1,2,3)相当于1,2,3之间的","
Index:索引,遍历list的时候index就是索引,遍历map的时候index表示的就是mapkey,item就是map的值.
mapper接口中的使用:
public interface EmpMapper {
    public List<Emp> getEmpsByConditionLike(@Param("list")List<Integer> ids);
}

方法二:注解
注解说明:
MyBatis提供用于插入数据的注解有两个: @insert,@InsertProvider,类似还有: ,@DeleteProvider@UpdateProvider,和@SelectProvider,
作用:
用来在实体类的Mapper类里注解保存方法的SQL语句
区别:
@Insert是直接配置SQL语句,而@InsertProvider则是通过SQL工厂类及对应的方法生产SQL语句,这种方法的好处在于,我们可以根据不同的需求生产出不同的SQL,适用性更好。
使用:
@Insert
@Insert("insert into blog(blogId,title,author) values(#blogId,#title,#author)")
public boolean saveBlog(Blog blog);

@InsertProvider

在mapper接口中的方法上使用@InsertProvider注解:

参数解释:
type为工厂类的类对象,
method为对应的工厂类中的方法,方法中的@Param(“list”)是因为批量插入传入的是一个list,但是Mybatis会将其包装成一个map
    其中map的key为“list”,value为传入的list
工类类ActivationProvider中的方法


首先要map.get方法得到对应的list;
然后拼接insert语句,要生成的正确的sql语句的格式为:
    INSERT INTO User (id, name) VALUES (null, #{list[0].name}), (null, #{list[1].name})[,(null, #{list[i].name})] 
    其中list[0]代表list中第0个元素
特别注意:
一定注意:注意Mapper到Provider参数类型的变化(List --> Map),Mapper中传入的List会被包裹在一个Map中传给Provider,而key就是在Mapper的@Param注解中指定的名称(默认为list)。在Provider方法中使用List<T> list = (List<T>) map.get(key);即可拿到我们传入的List。

否则会报错:

Caused by: org.apache.ibatis.binding.BindingException: Parameter 'arg0' not found. Available parameters are [1, 0, param1, param2]

三、xml、注解方式区别:

1.foreach相当语句逐条INSERT语句执行,将出现如下问题:
1. mapper接口的isnert方法返回值将是最一条INSERT语句的操作成功的记录数目(就是0或1),而不是所有INSERT语句的操作成功的总记录数目
2. 当其中一条不成功时,不会进行整体回滚。

2.注解方式:当有一条插入不成功时,会整体回滚



猜你喜欢

转载自blog.csdn.net/nnnora/article/details/80662419