当前位置: 代码网 > it编程>编程语言>Java > 解读tk.mybatis的通用批量更新方式

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

2024年08月18日 Java 我要评论
背景介绍mybatis没有提供批量更新的方法,通过代码中循环调用单个更新方法太消耗资源影响性能,在xml中写批量更新sql又太繁琐并且无法复用,并且项目中需要兼容多种类型数据库,因此在tk.mybat

背景介绍

mybatis没有提供批量更新的方法,通过代码中循环调用单个更新方法太消耗资源影响性能,

在xml中写批量更新sql又太繁琐并且无法复用,并且项目中需要兼容多种类型数据库,

因此在tk.mybatis的基础上扩展一个通用批量更新provider和mapper;

实现原理

可选批量更新实现的方式:

  • on duplicate key update语法,存在则更新,不存在则插入,能同时实现插入和更新,但on duplicate key update是mysql特有语法,切换成其他类型数据库就无法使用了。
  • foreach成多条sql去执行,但mybatis映射文件中的sql语句默认是不支持以" ; " 结尾的,也就是不支持多条sql语句的执行,为了支持这种方式,不同数据库的处理方式也不同,mysql数据库需要在url上设置&allowmultiqueries=true,oracle数据库需要在语句的前后添加关键字beginend;
  • 其他的实现方式都无法在多种数据库中使用;
  • case when语法,该语法在常用的数据库(mysql、oracle、dm、ob等)中都是支持的。

最终选定通过case when语法来实现,并扩展一个通用批量更新provider和mapper;

实现代码

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);
	}
	
	/**
	* 根据主键批量更新实体所有属性值,使用case when 方式,支持联合主键
	* 
	* @param ms mappedstatement
	* @return sql
	*/
	public string updatelistbyprimarykey(mappedstatement ms) {
		return this.sglhelper(ms, false);
	}

	/**
	*根据主键批量更新实体中不是null的属性值,使用case when方式,支持联合主键
	*
	* @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> {

	/**
	 * 根据主键批量更新实体中所有属性值,支持联合主键
	 * 
	 * @param updatelist 参数
	 * @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> {

	/** 根据主键批量更新实体中不是null的属性值,支持联合主键
	 *
	 * @param updatelist 参数
	 * @return int
	 */
	@updateprovider(type = updatelistprovider.class,method = "dynamicsql")
	int updatelistbyprimarykeyselective(list<t> updatelist);
}

总结

以上,根据主键批量更新数据的方法就实现了,只需要自己的mapper继承这两个通用扩展mapper就可以调用updatelistbyprimarykeyselective()updatelistbyprimarykey()方法进行批量更新了,并且同时支持联合主键单一主键,兼容mysql、oracle、dm、ob等数据库。

这些仅为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com