Mybatis Oracle数据库批量插入数据及新增一条数据返回其主键ID

近期在项目中用到了这些批量操作,记录一下自己对这些代码的理解。

第一种、批量插入数据表中没有主键(包括Mapper映射文件和映射接口)

1.1  Mapper.xml 映射文件 (此处示例使用的是oracle)
    <mapper namespace="com.mxx.demo.mapper.DmDsVestRlatMapper">
    	<!-- 通用查询映射结果 -->
    	<resultMap id="BaseResultMap" type="com.mxx.demo.entity.DmDsVestRlatEntity">
    		<result column="DM_DS_ID" property="dmDsId" />
    		<result column="VEST_TYPE_CODE" property="vestTypeCode" />
    	</resultMap>
    	<!-- 增加数据集合和归属类型的关系(union all: 是把多个归属类型结果当作临时表并起来插入到数据库中) -->
    	<insert id="addDmDsVestRlatInfo" parameterType="list">
    		insert into DM_DS_VEST_RLAT (DM_DS_ID, VEST_TYPE_CODE)
    		<!--dmDsId和vestTypeCode都是DmDsVestRlatEntity实体中的属性值 -->
    		<foreach collection="list" item="item" index="index" separator="union all">
    			( select #{item.dmDsId}, #{item.vestTypeCode} from dual)
    		</foreach>
    	</insert>
    </mapper>
    
1.2   Mapper接口如下:
public interface DmDsVestRlatMapper {
    // @Param注解的值要和foreach中的collection属性值一致(也就是都要是此处写的list)
    int addDmDsVestRlatInfo(@Param("list") List<DmDsVestRlatEntity> list); 
}

foreach属性值简单解释(只是本人的理解,如有错误之处请指正):

  1. collection属性值要和接口方法中的@Param注解值一致;
  2. item:表示循环体中的具体对象(例:有个List<User`>,那么item就可以看作代表User对象,item.age就类似User.age );具体说明:在 list 和数组中item代表其中的对象,在 map 中是 value,该参数为必选。(它是每一个元素进行迭代时的别名)
  3. index:在 list 和数组中,index 是元素的序号;在 map 中,index 是元素的 key。
  4. separator:表示foreach中sql语句以什么作为分隔符;
  5. open:表示该语句以什么开始;open:表示该语句以什么开始;
  6. close:表示该语句以什么结束

第二种、批量插入数据不需要返回主键

1.1 Mapper.xml映射文件代码

<insert id="addDwDsDetail" parameterType="list">
insert into DW_DS_DETAIL (
    ID,DW_DS_ID, DATA_ELE_ID, DATA_ELE_ORDER_FLAG)
    select SEQ_DW_DS_DETAIL.NEXTVAL, cd.* from(
  <foreach collection="list" item="item" index="index" separator="union all">
		select 
		    #{item.dwDsId}, 
		    #{item.dataEleId}, 
		    #{item.dataEleOrderFlag}
		from dual
  </foreach>
  ) cd
</insert>

1.2 Mapper映射接口方法
int addDwDsDetail(@Param("list") List<DwDsDetailEntity> list);

第三种、 一次新增一条数据,返回新插入的数据主键ID:

 1.1 Mapper.xml映射文件代码(这种情况适合返回新插入的数据主键ID):
    <!--Oracle数据库必须要使用 useGeneratedKeys、 keyProperty、selectKey 这3个属性,
          Mysql数据库使用useGeneratedKeys、 keyProperty即可-->
    <insert id="addDmDsInfo" parameterType="com.mxx.demo.entity.DmDsMgrEntity" 
    useGeneratedKeys="true" keyProperty="id">
    	   <!--  获取序列值,并赋值到对象的id字段,此处是用oracle进行的操作 -->
    	<selectKey keyProperty="id" order="BEFORE"  resultType="Long" keyColumn="id">
    		 SELECT SEQ_DM_DS_MGR.nextval from dual
    	</selectKey>
    	 insert into DM_DS_MGR  
    	 <trim prefix="(" suffix=")" suffixOverrides="," >
    		 <if test="id != null and id != '' ">ID,</if>
    		 <if test="dsEnglishName != null and dsEnglishName != '' ">DS_ENGLISH_NAME,</if>
    		 <if test="dsChineseName != null and dsChineseName != '' ">DS_CHINESE_NAME,</if>
    		 <if test="dsChineseNamePym != null and dsChineseNamePym != '' ">DS_CHINESE_NAME_PYM,</if>
    		 <if test="createDate != null">CREATE_DATE,</if>
    		 <if test="createUserId != null and createUserId != '' ">CREATE_USER_ID</if>
    	 </trim> 
    	 <trim prefix="values (" suffix=")" suffixOverrides="," >
    	     <if test="id != null and id != '' ">#{id},</if>
    		 <if test="dsEnglishName != null and dsEnglishName != '' ">#{dsEnglishName},</if>
    		 <if test="dsChineseName != null and dsChineseName != '' ">#{dsChineseName},</if>
    		 <if test="dsChineseNamePym != null and dsChineseNamePym != '' ">#{dsChineseNamePym},</if>
    		 <if test="createDate != null ">SYSDATE,</if>
    		 <if test="createUserId != null and createUserId != '' ">#{createUserId}</if>
    	 </trim>
    </insert> 
    	
   1.2 Mapper映射接口方法 : 
    public interface DmDsMgrMapper { 
         int addDmDsInfo(DmDsMgrEntity  entity);  
    }
     
   1.3 service层调用mapper层方法后如何获取主键ID值
   // 假设已经将Mapper接口dmDsMgrMapper注入到service层了
   public ResultMessage addDmDsInfo(DmDsMgrEntity entity) {
      // 主键ID在配置文件中指定了为INPUT模式,此处不用关注ID的值
     /**
      *主键类型  AUTO:"数据库ID自增",
      *  INPUT:"用户输入ID",
      *  ID_WORKER:"全局唯一ID (数字类型唯一ID)",
      *  UUID:"全局唯一ID *UUID";
      *  -- mybatis-plus.global-config.db-config.id-type=INPUT
      *  -- mybatis-plus.global-config.db-config.db-type=ORACLE
      */
       int addDmDsNum = dmDsMgrMapper.addDmDsInfo(entity);
       // 当mapper层方法执行成功后我们直接用entity.getId()就可以取到新增数据的主键ID了
       System.out.println("返回的主键 :"+ entity.getId() );
   }

第四种、 批量插入数据后批量返回主键

注:批量插入数据后利用mybatis返回主键这个操作对数据库有两点要求:
(1)数据库主键值为自增类型;
(2)数据库提供的jdbc驱动要支持返回批量插入的主键值;
到目前为止能完美支持以上2点要求的仅有mysql数据库,mysql中支持主键自增,oracle通过序列来维护主键 不符合上述的第一点要求,所以mysql数据库支持使用mybatis批量插入数据后批量返回主键,而oracle等其他数据库需要其他方法才能实现。

一. mysql支持批量插入数据批量返回主键:
 1.1 Mapper接口类: (mysql返回主键示例)
 num addUser(@Param("list") List<User> list);
 
 1.2 Mapper.xml文件
 <!-- sql中不用写id -->
 <insert id="addUser" useGeneratedKeys="true" keyProperty="id"> 
 	insert into 表名 (user_name, user_password, user_email) values
 	<foreach collection="list" item="item" separator=",">
 	  (#{item.userName}, #{item.userPassword},#{item.userEmail})
 	</foreach >
 </insert>
 
 1.3 service层调用此方法后获取新增的主键
 public void addUser() {
     List<User> list = new ArrayList<User>();
     for(int i = 0; i < 2; i++) {
      		User user = new User();
      		user.setUserName("test"+i);
      		user.setUserPassword(i);
      		user.setUserEmail("XXXX");
      		list.add(user);
     }
     int num = userMapper.addUser(list);
     for(User user : list) {
            // 会循环打印出返回的主键
			System.out.println(user.getId());
      }     
 }
二. oracle通过mybatis无法批量返回主键需要通过其他方法返回

方法一:先单独调用序列获取主键,把主键值塞到相应的实体类中,再进行批量insert操作;
方法二:通过for循环在程序中遍历插入,这样每次可以单独获取主键(适合小批量数据);

附 :
mysql批量新增数据sql:
insert into 表名(name, password, email) 
values ('AA', '123', '0000'),('BB', '456', '1111'),...

Oracle批量新增数据sql:
未涉及表主键:
insert into 表名(name, password, email) 
select 'AA', '123', '0000' from dual union all 
select 'BB', '456', '1111' from dual
或
涉及表主键:
insert into 表名(id,name, password)
selecy seq_user.nextval,a.* from 
(select 'AA', '123' from dual union all 
select 'BB', '456' from dual) a 

若有错误和不足请指正~~~

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值