自己手写Mybatis 通用batchInsert

   写完才在群里有人告知本来tk mybatis就提供了批量insert的功能,那就放上来做个纪念吧.

   先写个数据字典(其实tk mybatis自身也有相应的功能)。


/**
 * Mybatis 带缓冲功能的数据字典
 * Created by rocklee on 2019/8/10 23:27
 */
public class MybatisDictionary {
  private static ConcurrentHashMap, String> entityClass2TableName=new ConcurrentHashMap<>();
  private static ConcurrentHashMap, String> entityClass2Columns=new ConcurrentHashMap<>();
  private static ConcurrentHashMap, List> entityClass2FieldsList=new ConcurrentHashMap<>();
  private static ConcurrentHashMap, Hashtable> entityClass2Fields=new ConcurrentHashMap<>();

  public static String getTableName(Class pvEntityClass){
    String lvsRet=entityClass2TableName.get(pvEntityClass);
    if (lvsRet!=null)return lvsRet;
    Table lvTable= pvEntityClass.getAnnotation(Table.class);
    if (lvTable==null){
      throw new RuntimeException(pvEntityClass.getName()+"不是有效的Entity类,缺少@Table标识");
    }
    lvsRet=lvTable.name();
    entityClass2TableName.put(pvEntityClass,lvsRet);
    return lvsRet;
  }
  public static String getColumns(Class pvEntityClass){
    String lvsRet=entityClass2Columns.get(pvEntityClass);
    if (lvsRet!=null)return lvsRet;
    List lvItems=new ArrayList<>();
    for (Field field:pvEntityClass.getDeclaredFields()){
      Column lvColumn=field.getAnnotation(Column.class);
      if (lvColumn==null)continue;
      lvItems.add(lvColumn.name());
    }
    lvsRet= Util.toString(lvItems,",");
    entityClass2Columns.put(pvEntityClass,lvsRet);
    return lvsRet;
  }
  public static List getFieldsList(Class pvEntityClass){
    List lvRet=entityClass2FieldsList.get(pvEntityClass);
    if (lvRet!=null)return lvRet;
    lvRet=new ArrayList<>();
    for (Field field:pvEntityClass.getDeclaredFields()){
      Column lvColumn=field.getAnnotation(Column.class);
      if (lvColumn==null)continue;
      lvRet.add(field.getName());
    }
    entityClass2FieldsList.put(pvEntityClass,lvRet);
    return lvRet;
  }
  public static HashtablegetFields(Class pvEntityClass){
    Hashtable lvRet=entityClass2Fields.get(pvEntityClass);
    if (lvRet!=null)return lvRet;
    lvRet=new Hashtable();
    for (Field field:pvEntityClass.getDeclaredFields()){
      Column lvColumn=field.getAnnotation(Column.class);
      if (lvColumn==null)continue;
      lvRet.put(field,lvColumn.name());
    }
    entityClass2Fields.put(pvEntityClass,lvRet);
    return lvRet;
  }
}

 

再写SqlProvider:

/** 批处理SQL处理器
 * Created by rocklee on 2019/8/10 23:11
 */
public class BatchSqlProvider  extends MapperTemplate {
  public BatchSqlProvider(Class mapperClass, MapperHelper mapperHelper) {
    super(mapperClass, mapperHelper);
  }
 
  public String batchInsert(MappedStatement ms) {
    final Class entityClass = getEntityClass(ms);
    StringBuilder sb=new StringBuilder();
    sb.append("INSERT INTO "+MybatisDictionary.getTableName(entityClass));
    sb.append("\n\n");
    sb.append(MybatisDictionary.getColumns(entityClass));
    sb.append(" \n");
    sb.append("\nVALUES\n");
    sb.append("");
    sb.append("\n");
    sb.append("\n");
    String lvsValFields="#{record."+ Util.toString(MybatisDictionary.getFieldsList(entityClass),"},#{record.")
            +"}";
    sb.append(lvsValFields);
    sb.append("\n\n");
    return sb.toString() ;
  }

}

Mapper:


/**
 * Created by rocklee on 2019/8/11 0:24
 */
@RegisterMapper
public interface BatchMapper {
  /***
   * 批量插入
   * @param pvToInsertList
   * @return
   */
  @InsertProvider(type = BatchSqlProvider.class,  method = "dynamicSQL")
  int batchInsert(List pvToInsertList);
}

这是基于tk的MapperTemplate 写的sqlprovider,传入的是MappedStatement,这时候返回的SQL不是raw SQL,还能支持,这些mybatis表达式, 而如果用与mapper接口相同的参数方式返回sql,那这些表达式则不会被mybatis解释,而直接传到database服务器那边, 导致异常。

==============================

最后要提一下, tkmybatis带自了一个insertListMapper,我们extends它就可以实现批量insert了:

自己手写Mybatis 通用batchInsert_第1张图片

你可能感兴趣的:(MyBatis)