" />

最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

解讀tk.mybatis的通用批量更新方式

 更新時(shí)間:2024年08月17日 12:15:39   作者:Zephyr丶Syn  
這篇文章主要介紹了關(guān)于tk.mybatis的通用批量更新方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

背景介紹

mybatis沒有提供批量更新的方法,通過代碼中循環(huán)調(diào)用單個(gè)更新方法太消耗資源影響性能,

在xml中寫批量更新SQL又太繁瑣并且無法復(fù)用,并且項(xiàng)目中需要兼容多種類型數(shù)據(jù)庫,

因此在tk.mybatis的基礎(chǔ)上擴(kuò)展一個(gè)通用批量更新Provider和Mapper;

實(shí)現(xiàn)原理

可選批量更新實(shí)現(xiàn)的方式:

  • on duplicate key update語法,存在則更新,不存在則插入,能同時(shí)實(shí)現(xiàn)插入和更新,但on duplicate key update是MySQL特有語法,切換成其他類型數(shù)據(jù)庫就無法使用了。
  • foreach成多條SQL去執(zhí)行,但Mybatis映射文件中的sql語句默認(rèn)是不支持以" ; " 結(jié)尾的,也就是不支持多條sql語句的執(zhí)行,為了支持這種方式,不同數(shù)據(jù)庫的處理方式也不同,MySQL數(shù)據(jù)庫需要在URL上設(shè)置&allowMultiQueries=true,Oracle數(shù)據(jù)庫需要在語句的前后添加關(guān)鍵字BEGINEND;
  • 其他的實(shí)現(xiàn)方式都無法在多種數(shù)據(jù)庫中使用;
  • case when語法,該語法在常用的數(shù)據(jù)庫(MySQL、Oracle、DM、OB等)中都是支持的。

最終選定通過case when語法來實(shí)現(xiàn),并擴(kuò)展一個(gè)通用批量更新Provider和Mapper;

實(shí)現(xiàn)代碼

tk.mybatis的maven依賴:
<dependency>
	<groupId>tk.mybatis</groupId>
	<artifactId>mapper-spring-boot-starter</artifactId>
	<version>2.2.4.4</version>
</dependency>
UpdateListProvider類:

package com.demo.ibatis.provider;

import org.apache.ibatis.mapping.MappedStatement;
import tk.mybatis.mapper.entity.EntityColumn;
import tk.mybatis .mapper.mapperhelper.EntityHelper;
import tk.mybatis.mapper.mapperhelper.MapperHelper;
import tk.mybatis.mapper.mapperhelper.MapperTemplate;
import tk.mybatis.mapper.mapperhelper.SglHeTper;
import tk.mybatis.mapper.util.StringUtil;

import java.util.Set;

public class UpdateListProvider extends MapperTemplate {

	public UpdatelistProvider(Class<?> mapperClass, MapperHelper mapperHelper) {
		super(mapperClass, mapperHelper);
	}
	
	/**
	* 根據(jù)主鍵批量更新實(shí)體所有屬性值,使用case when 方式,支持聯(lián)合主鍵
	* 
	* @param ms MappedStatement
	* @return sql
	*/
	public String updateListByPrimaryKey(MappedStatement ms) {
		return this.sglHelper(ms, false);
	}

	/**
	*根據(jù)主鍵批量更新實(shí)體中不是null的屬性值,使用case when方式,支持聯(lián)合主鍵
	*
	* @param ms MappedStatement
	* @return sql
	*/
	public String updateListByPrimaryKeySelective(MappedStatement ms) {
		return this.sglHelper(ms, true);
	}

	private String sqlHelper(MappedStatement ms, boolean notNull) {
		final Class<?> entityclass = getEntityClass(ms);
		// 開始拼sql
		StringBuilder sgl = new StringBuilder();
		sql.append(SqlHelper.updateTable(entityclass,tableName(entityclass)));
		sql.append("<trim prefix=\"set\" suffixOverrides= \",\">");
		// 獲取全部列
		Set<EntityColumn> allColumns = EntityHelper.getColumns(entityClass);
		// 找到主鍵列
		Set<EntityColumn> pkColumns = EntityHelper.getPKColumns(entityclass);
		for (EntityColumn column : allColumns) {
			if (!column.isId() && column.isUpdatable()) {
				sql.append("  <trim prefix=\"").append(column.getColumn()).append(" = case\" suffix= \"end,\">");
				sgl.append("     <foreach collection= \"list\" item= \"i\" index= \"index\">");
				if (notNull) {
					sql.append(this.getIfNotNull("i", column, isNotEmpty()));
				}
				sql.append("         when ");
				int count = 0;
				for (EntityColumn pk  : pkColumns) {
					if (count != 0) {
						sql.append("and ");
					}
					sql.append(pk.getColumn()).append("=#{i.").append(pk.getProperty()).append("} ");
					count++;
				}
				sql.append("then ").append(column.getColumnHolder("i"));
				if (notNull) {
					sql.append("        </if>");
				}
				sql.append("        </foreach>");
				sql.append("    </trim>");
			}
		}
		sql.append("</trim>");
		sql.append("WHERE (");
		int count = 0;
		for (EntityColumn pk : pkColumns) {
			sql.append(pk.getCotumn());
			if (count < pkColumns.size() - 1) {
				sql.append(", ");
			}
			count++;
		}
		sql.append(") IN");
		sql.append("<trim prefix= \"(\" suffix= \")\">");
		sql.append("<foreach collection=\"list\" separator=\"), (\" item=\"i\" index=\"index\" open=\"(\" close=\")\" >");
		count = 0;
		for (EntityColumn pk : pkColumns) {
			sql.append("#{i.").append(pk.getProperty()).append("}");
			if (count < pkColumns.size() - 1) {
				sg.append(", ");
			}
			count++;
		}
		sql.append("</foreach>");
		sql.append("</trim>");
		return sql.toString();
	}

	private String getIfNotNull(String entityNameEntityColumn column, boolean empty) {
		StringBuilder sql = new StringBuilder();
		sql.append("   <if test=\"");
		if (StringUtil.isNotEmpty(entityName)) {
			sql.append(entityName).append(".");
		}
		sql.append(column.getProperty()).append(" != null");
		if (empty && column.getJavaType().equals(String.class)) {
			sql.append(" and ");
			if (StringUtil.isNotEmpty(entityName)) {
				sql.append(entityName).append(".");
			}
			sql.append(column.getProperty()).append(" != '' ");
		}
		sql.append("\">");
		return sql.tostring();
	}
}
UpdateListByPrimaryKeyMapper類:

package com.demo.ibatis.mapper;

import com.demo.ibatis.provider.UpdateListProvider;
import org.apache.ibatis.annotations.UpdateProvider;
import tk.mybatis .mapper.annotation.RegisterMapper;

import java.util.List;

@RegisterMapper
public interface UpdateListByPrimaryKeyMapper<T> {

	/**
	 * 根據(jù)主鍵批量更新實(shí)體中所有屬性值,支持聯(lián)合主鍵
	 * 
	 * @param updateList 參數(shù)
	 * @return int
	 */
	@UpdateProvider(type = UpdateListProvider.class,method = "dynamicSQL")
	int updateListByPrimaryKey(List<T> updateList);
}
UpdateListByPrimaryKeySelectiveMapper類:

package com.demo.ibatis.mapper;

import com.demo.ibatis.provider.UpdateListProvider;
import org.apache.ibatis.annotations.UpdateProvider;
import tk.mybatis .mapper.annotation.RegisterMapper;

import java.util.List;

@RegisterMapper
public interface UpdateListByPrimaryKeySelectiveMapper<T> {

	/** 根據(jù)主鍵批量更新實(shí)體中不是null的屬性值,支持聯(lián)合主鍵
	 *
	 * @param updateList 參數(shù)
	 * @return int
	 */
	@UpdateProvider(type = UpdateListProvider.class,method = "dynamicSQL")
	int updateListByPrimaryKeySelective(List<T> updateList);
}

總結(jié)

以上,根據(jù)主鍵批量更新數(shù)據(jù)的方法就實(shí)現(xiàn)了,只需要自己的Mapper繼承這兩個(gè)通用擴(kuò)展Mapper就可以調(diào)用updateListByPrimaryKeySelective()updateListByPrimaryKey()方法進(jìn)行批量更新了,并且同時(shí)支持聯(lián)合主鍵單一主鍵,兼容MySQL、Oracle、DM、OB等數(shù)據(jù)庫。

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

相關(guān)文章

  • SpringBoot啟動(dòng)失敗的排查指南

    SpringBoot啟動(dòng)失敗的排查指南

    本文詳細(xì)介紹了SpringBoot項(xiàng)目項(xiàng)目手動(dòng)部署項(xiàng)目時(shí)遇到服務(wù)啟動(dòng)失敗的排查流程,包括從環(huán)境到代碼的完整排查步驟,需要的朋友可以參考下
    2026-05-05
  • Java中的原子類AtomicInteger使用詳解

    Java中的原子類AtomicInteger使用詳解

    這篇文章主要介紹了Java中的原子類AtomicInteger使用詳解,原子操作是指不會(huì)被線程調(diào)度機(jī)制打斷的操作,這種操作一旦開始,就一直運(yùn)行到結(jié)束,中間不會(huì)有任何線程上下文切換,需要的朋友可以參考下
    2023-12-12
  • Mybatis注解方式完成輸入?yún)?shù)為list的SQL語句拼接方式

    Mybatis注解方式完成輸入?yún)?shù)為list的SQL語句拼接方式

    這篇文章主要介紹了Mybatis注解方式完成輸入?yún)?shù)為list的SQL語句拼接方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Java中集合關(guān)系圖及常見操作詳解

    Java中集合關(guān)系圖及常見操作詳解

    這篇文章主要為大家詳細(xì)介紹了Java中集合關(guān)系圖及常見操作,解析Java中的集合類型的繼承關(guān)系圖,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • 挑戰(zhàn)4道Java試題

    挑戰(zhàn)4道Java試題

    這篇文章主要為大家分享了4道Java基礎(chǔ)題,幫助大家鞏固基礎(chǔ)知識(shí),夯實(shí)java基礎(chǔ)技能,感興趣的朋友快點(diǎn)挑戰(zhàn)
    2015-12-12
  • 詳解java 中的CAS與ABA

    詳解java 中的CAS與ABA

    這篇文章主要介紹了java 中的CAS與ABA的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下
    2021-05-05
  • Java 實(shí)戰(zhàn)交易平臺(tái)項(xiàng)目之寵物在線商城系統(tǒng)

    Java 實(shí)戰(zhàn)交易平臺(tái)項(xiàng)目之寵物在線商城系統(tǒng)

    讀萬卷書不如行萬里路,只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用Java實(shí)現(xiàn)一個(gè)寵物在線商城系統(tǒng),大家可以在過程中查缺補(bǔ)漏,提升水平
    2021-11-11
  • java獲取ip地址與網(wǎng)絡(luò)接口的方法示例

    java獲取ip地址與網(wǎng)絡(luò)接口的方法示例

    這篇文章主要給大家介紹了關(guān)于利用java如何獲取ip地址與網(wǎng)絡(luò)接口的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-01-01
  • Java中Vector、ArrayList、LinkedList的關(guān)系詳細(xì)解析

    Java中Vector、ArrayList、LinkedList的關(guān)系詳細(xì)解析

    這篇文章主要介紹了Java中Vector、ArrayList、LinkedList的關(guān)系詳細(xì)解析,Vector和ArrayList底層均為Object數(shù)組,LinkedList底層是Node節(jié)點(diǎn),Vector是線程安全(底層方法均添加synchronized),ArrayList、LinkedList是線程不安全(無鎖),需要的朋友可以參考下
    2023-11-11
  • Java中的線程池ThreadPoolExecutor深入解析

    Java中的線程池ThreadPoolExecutor深入解析

    這篇文章主要介紹了Java中的線程池ThreadPoolExecutor深入解析,線程池,thread pool,是一種線程使用模式,線程池維護(hù)著多個(gè)線程,等待著監(jiān)督管理者分配可并發(fā)執(zhí)行的任務(wù),需要的朋友可以參考下
    2023-11-11

最新評(píng)論

文山县| 九台市| 资阳市| 阜阳市| 台北市| 尉氏县| 曲周县| 昭平县| 志丹县| 永春县| 盐津县| 离岛区| 康马县| 扶风县| 长武县| 册亨县| 蕉岭县| 图木舒克市| 信宜市| 运城市| 蓬安县| 常山县| 平舆县| 娄底市| 上虞市| 平远县| 五河县| 靖边县| 太和县| 广东省| 饶河县| 江门市| 牡丹江市| 将乐县| 房产| 齐齐哈尔市| 呼和浩特市| 那坡县| 溧水县| 油尖旺区| 沙雅县|