亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

自己手寫Mybatis通用batchInsert問題

 更新時(shí)間:2022年11月17日 11:24:25   作者:OK_boom  
這篇文章主要介紹了自己手寫Mybatis通用batchInsert問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

自己手寫Mybatis通用batchInsert

寫完才在群里有人告知本來tk mybatis就提供了批量insert的功能,那就放上來做個(gè)紀(jì)念吧.

先寫個(gè)數(shù)據(jù)字典(其實(shí)tk mybatis自身也有相應(yīng)的功能)。

/**
?* Mybatis 帶緩沖功能的數(shù)據(jù)字典
?* Created by rocklee on 2019/8/10 23:27
?*/
public class MybatisDictionary {
? private static ConcurrentHashMap<Class<?>, String> entityClass2TableName=new ConcurrentHashMap<>();
? private static ConcurrentHashMap<Class<?>, String> entityClass2Columns=new ConcurrentHashMap<>();
? private static ConcurrentHashMap<Class<?>, List<String>> entityClass2FieldsList=new ConcurrentHashMap<>();
? private static ConcurrentHashMap<Class<?>, Hashtable<Field,String>> 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標(biāo)識(shí)");
? ? }
? ? 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<String> 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<String> getFieldsList(Class<?> pvEntityClass){
? ? List<String> 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 Hashtable<Field,String>getFields(Class<?> pvEntityClass){
? ? Hashtable<Field,String> lvRet=entityClass2Fields.get(pvEntityClass);
? ? if (lvRet!=null)return lvRet;
? ? lvRet=new Hashtable<Field,String>();
? ? 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<trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n");
? ? sb.append(MybatisDictionary.getColumns(entityClass));
? ? sb.append("</trim> \n");
? ? sb.append("\nVALUES\n");
? ? sb.append("<foreach collection=\"list\" item=\"record\" separator=\",\">");
? ? sb.append("\n");
? ? sb.append("<trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n");
? ? String lvsValFields="#{record."+ Util.toString(MybatisDictionary.getFieldsList(entityClass),"},#{record.")
? ? ? ? ? ? +"}";
? ? sb.append(lvsValFields);
? ? sb.append("\n</trim>\n</foreach>");
? ? return sb.toString() ;
? }
?
}

Mapper: 

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

這是基于tk的MapperTemplate 寫的sqlprovider,傳入的是MappedStatement,這時(shí)候返回的SQL不是raw SQL,還能支持<if>,<foreach>這些mybatis表達(dá)式, 而如果用與mapper接口相同的參數(shù)方式返回sql,那這些表達(dá)式則不會(huì)被mybatis解釋,而直接傳到database服務(wù)器那邊, 導(dǎo)致異常。

最后要提一下, tkmybatis帶自了一個(gè)insertListMapper,我們extends它就可以實(shí)現(xiàn)批量insert了:

使用Mapper通用insert方法遇到的問題

環(huán)境

  • spingboot
  • sqlserver
  • mybatis
  • Mapper

insert拋出不能為標(biāo)識(shí)列插入顯式值的異常

原因:表的自增主鍵,通常情況下不需要直接在insert語句中指定設(shè)值。查看控制臺(tái)打印語句,發(fā)現(xiàn)是對(duì)該字段做了插入。

解決方法:該表對(duì)應(yīng)實(shí)體中,在不需要做插入的字段上增加@Column(insertable = false)。

延伸:@Column還有一些值可供設(shè)值,

  • name 被標(biāo)注字段在數(shù)據(jù)庫表中所對(duì)應(yīng)字段的名稱;
  • unique 表示該字段是否為唯一標(biāo)識(shí),默認(rèn)為false;
  • nullable表示該字段是否可以為null值,默認(rèn)為true;
  • insertable表示在使用“INSERT”腳本插入數(shù)據(jù)時(shí),是否需要插入該字段的值。
  • updatable表示在使用“UPDATE”腳本插入數(shù)據(jù)時(shí),是否需要更新該字段的值。
  • columnDefinition表示創(chuàng)建表時(shí),該字段創(chuàng)建的SQL語句,一般用于通過Entity生成表定義時(shí)使用。
  • table 定義了包含當(dāng)前字段的表名。
  • length表示字段的長(zhǎng)度,當(dāng)字段的類型為varchar時(shí),該屬性才有效,默認(rèn)為255個(gè)字符。
  • precision屬性和scale屬性表示精度,當(dāng)字段類型為double時(shí),precision表示數(shù)值的總長(zhǎng)度,scale表示小數(shù)點(diǎn)所占的位數(shù)。
  • insert不能返回自增id的問題

這個(gè)問題,用過給自增id加 @GeneratedValue(generator =’“JDBC”)等,無效;

只能先不用Mapper通用的方法,自己定義一個(gè)insert接口,在xml中設(shè)置usergeneratedkeys=true ,keyProperty=“id” 這樣會(huì)把自增得到的id值注入到實(shí)體id參數(shù)中。

(該問題待解決,有知道的朋友指點(diǎn)下,注意數(shù)據(jù)庫是SqlServer)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論