前面介绍了无主键的表的批量插入,文章地址:http://blog.csdn.net/zhouxiaoyun0228/article/details/9980181

但是在开发中往往许多的表是需要主键的,因而现在介绍一下有主键的表的批量插入,该主键是数据类型的数字类型。

最开始我是这么想的:主键让他自动添加,因而我们可以在insert中添加一个自增序列号就可以了,如下

<selectKey resultType="long" keyProperty="ID" order="BEFORE">
     SELECT IBATIS_SEQUENCE.NEXTVAL AS ID FROM dual
    </selectKey>

然后在listStr中添加一个#{obj.ID,jdbsType=DOUBLE}即可,但是发现没用,生成的Id不会自动添加进入List中。

后面有想了一下,其实思路还是没有错的。。我们只需要转化一下,将生成的主键Id值放入自动添加到List集合中即可,代码如下

for(DataRecord d:list){
   Serializable id = this.generateId();
   d.put(keyName, id);
   back.add(d);
  }

上面红色的标记是是与无主键部分唯一的区别,keyName是传入进来的主键名称,this.generateId();是提供自增长id的方法。

public Serializable generateId() {
  return this.getDao().queryForLong("com.mip.biz.syn.data.batch.demo.getKeyValue", null);
 }

mapper中的代码如下

<select id="getKeyValue" parameterType="map" resultType="LONG">
     SELECT IBATIS_SEQUENCE.NEXTVAL AS ID FROM dual
   </select>

这样一来也就解决了表有主键的问题。其他的代码没有变化,就是接口变化了一下:

/**
    * 有主键的表批量插入
    * @param list
    * @param tableName
    * @param keyName  主键名称
    */

public void batchInsertWithKey(List<DataRecord> list,String tableName,String keyName);

通过观察,发现代码好多冗余的,因而我们可以重构下代码,重构后的java代码如下,mapper中的代码不变,只添加了上面提到过的getKeyValue

接口方法:

/**
     * 无主键的表批量插入
     * @param list
     * @param tableName
     */
 public void batchInsertWithOutKey(List<DataRecord> list,String tableName);
   /**
    * 有主键的表批量插入
    * @param list
    * @param tableName
    * @param keyName  主键名称
    */
 public void batchInsertWithKey(List<DataRecord> list,String tableName,String keyName);

以下是实现方法  this.getDao().这里是内部封装的dao层,可以自己改动一下去实现与mapper交互
 @Override
 public void batchInsertWithKey(List<DataRecord> list,String tableName,String keyName) {
  this.batchInsert(list, tableName, keyName);
 }
 @Override
 public void batchInsertWithOutKey(List<DataRecord> list,String tableName) {
  this.batchInsert(list, tableName, null);
 }
 //查询表所包含的列名,以及该列对应的类型
 private List<DataRecord> getTableColumns(String tableName){
  Map<String,Object> m=new HashMap<String,Object>();
  m.put("tableName", tableName);
  //去数据库中查询
  List<DataRecord> list=this.getDao().queryForDataSet("com.mip.biz.syn.data.batch.demo.getTableColumn", m).getResults();
  return list;
 }
 //改变列名对应的类型
 private String changeColumnType(String dataType){
  if("NUMBER".equals(dataType)){
   return "DOUBLE";
  }else if("VARCHAR2".equals(dataType)){
   return "VARCHAR";
  }else if(dataType.startsWith("TIMESTAMP")){
   return "TIMESTAMP"; 
  }else{
   return dataType;
  }
 }

//根据是否有主键名改变集合的数据,DataRecord是Map的一个自定义的子类
 private List<Map> changgeList(List<DataRecord> list,String keyName ){
  List<Map> back=new ArrayList<Map>();
  if(keyName==null){
   for(DataRecord d:list){
    back.add(d);
   }
  }else{
   for(DataRecord d:list){
    Serializable id = this.generateId();
    d.put(keyName, id);
    back.add(d);
   }
  }
  return back;
 }
 //批量插入数据
 private void batchInsert(List<DataRecord> list,String tableName,String keyName){
  //如果无数据,不需要执行插入了
  if(list.size()<=0){
   return ;
  }
  //获取表的列名以及类型
  List<DataRecord> columns=this.getTableColumns(tableName);
  if(columns.size()==0){
   return;
  }
  Map<String,String> columnMap=new HashMap<String,String>();
  for(DataRecord dr:columns){
   columnMap.put(dr.getString("COLUMN_NAME"), changeColumnType(dr.getString("DATA_TYPE")));
  }
  List<Map> back=this.changgeList(list, keyName);
  Map dm=back.get(0);
  Set<String> objectKeys = dm.keySet();
  StringBuffer insertSql=new StringBuffer();
  insertSql.append("insert into "+tableName+" (");
  StringBuffer listSql=new StringBuffer();
  listSql.append(" select ");
  for(String col:objectKeys){
   insertSql.append(""+col+",");
   listSql.append("#{obj."+col+",jdbcType="+columnMap.get(col)+"}"+",");
  }
  // 删除最后的半角逗号
  if (insertSql.length() > 0) {
   insertSql.deleteCharAt(insertSql.length() - 1);
  }
  if (listSql.length() > 0) {
   listSql.deleteCharAt(listSql.length() - 1);
  }
  insertSql.append(")");
  listSql.append(" from dual");
  Map<String,Object> batchMap=new HashMap<String,Object>();
  batchMap.put("insertSql", insertSql.toString());
  batchMap.put("listSql", listSql.toString());
  batchMap.put("list", back);
  this.getDao().insertByStatement("com.mip.biz.syn.data.batch.demo.batchDemo", batchMap);
 }
 //获取主键序列号
 public Serializable generateId() {
  return this.getDao().queryForLong("com.mip.biz.syn.data.batch.demo.getKeyValue", null);
 }
 public void test(){
  //test_batch
  List<DataRecord> list=new ArrayList<DataRecord>();
  for(int i=0;i<10;i++){
   DataRecord dr=new DataRecord();
   dr.put("USERNAME","NAME_"+i);
   list.add(dr);
  }
  batchInsertWithKey(list,"TEST_BATCH","ID");
 }
}

[置顶] mybatis批量新增系列之有主键的表的批量新增的更多相关文章

  1. mybatis+sqlserver中返回非自增主键

    首先把实体类贴出来(这里只贴出属性,其它的就是getter和setter方法): public class Around {     private String xccd;  //对应主键      ...

  2. Mybatis在insert操作时返回主键

    今天在写项目的时候,遇到一个需求,就是在像数据库插入数据的时候,要保留插入数据的主键,以便后续进行级联时,可以将该主键作为另张表的外键. 但是在正常情况下我们使用插入语句返回的是int型,含义是影响该 ...

  3. mybatis与mysql插入时返回主键id的值

    <insert id="insertCharge" parameterType="com.bb.bean.Rechargerecord"> < ...

  4. MyBatis面对Oracle数据库如何实现主键列自增长

    因为Oracle数据库而言 不能够像SqlServer和MySql一样主键自增 而且MyBatis也没有提供直接的主键自增方法 所以我们自己使用查询语句来实现自增 实现代码: <insert i ...

  5. Mybatis批量插入返回自增主键(转)

    我们都知道Mybatis在插入单条数据的时候有两种方式返回自增主键: 1.对于支持生成自增主键的数据库:useGenerateKeys和keyProperty. 2.不支持生成自增主键的数据库:< ...

  6. mybaits实现oracle批量新增数据,回填主键

    项目有需求,百度了很久,反正他们说的方法,我都没成功,我也不知道是不是我写代码的姿势不正确,没办法只能自己想法子了 我们这个项目用到了通过Mapper,通用Mapper里通过OracleProvide ...

  7. mybatis用mysql数据库自增主键,插入一条记录返回新增记录的自增主键ID

    今天在敲代码的时候遇到一个问题,就是往数据库里插入一条记录后需要返回这个新增记录的ID(自增主键), 公司框架用的是mybatis的通用Mapper接口,里面的插入方法貌似是不能把新纪录的ID回填到对 ...

  8. mybatis注解版in查询、字符串判空模糊匹配 、批量插入、插入返回主键

    IN查询 @Select({"<script> " + " select * "+ " from business_threat bt \ ...

  9. 深入分析Mybatis 使用useGeneratedKeys获取自增主键

    摘要 我们经常使用useGenerateKeys来返回自增主键,避免多一次查询.也会经常使用on duplicate key update,来进行insertOrUpdate,来避免先query 在i ...

随机推荐

  1. 在SSIS包中使用 Checkpoint从失败处重新启动包

    使用SSIS做ETL的过程中会遇到各种各样的错误,对于一些大数据量的Job失败以后我们不希望重新运行,因为重新运行的时间开销是非常大的,我们只希望从失败的部分开始运行,这样可以省去很多的时间. SSI ...

  2. Activity 启动模式

    Activity的启动模式有四种,分别是standard.singleTop.singleTask.singleInstance.   Android是通过回退栈的模式来管理Activity实例的.栈 ...

  3. 使用Notepad++快速有效删除复制代码中的行号

    转载:http://plum.0602.blog.163.com/blog/static/1130006502011101524120757/ 试了该方法,很好用! 为什么我把用Notepad++删除 ...

  4. iOS中运用正则表达式

    iOS中运用正则表达式来匹配短信验证码,电话号码,邮箱等是比较常见的. 在iOS中运用正则表达式主要有三种方式: -:通过谓词下面是实例代码: - (BOOL)regularExpresionWith ...

  5. java 在方法中新建线程,传参和加锁详解

    在实际开发中,往往在基本两三种创建线程的方法之外,还用到一个简单的创建线程调用方法的情况,代码如下: public void deleteRedisData(RedisKey redisKey){ n ...

  6. 深入理解C/C++数组和指针

    C语言中数组和指针是一种很特别的关系,首先本质上肯定是不同的,本文从各个角度论述数组和指针. 一.数组与指针的关系数组和指针是两种不同的类型,数组具有确定数量的元素,而指针只是一个标量值.数组可以在某 ...

  7. 2045不容易系列之(3)—— LELE的RPG难题

    Problem Description人称“AC女之杀手”的超级偶像LELE最近忽然玩起了深沉,这可急坏了众多“Cole”(LELE的粉丝,即”可乐”),经过多方打探,某资深Cole终于知道了原因,原 ...

  8. PhoneGap笔记-01 基本使用

    1. 环境配置 1.1 常用框架 jQuery Backbone.js dojo bootstrap kendo UI Sencha jQuery Mobile PhoneJS AngularJS I ...

  9. jQuery validate入门

    <html> <head> <meta charset="utf8"></meta> </head> <body& ...

  10. 定时每天备份mysql

    http://blog.csdn.net/panning_hu/article/details/9210001 Spring MVC Spring中MVC框架的底层实现 http://blog.csd ...