记录一次tk mybatis 增加批量更新接口
tk mybatis 个人理解就是对mybatis做的一层包装,实现可以对单个对象直接调用,如增删改查的过程,省略了原来mybatis一个个写这种重复sql的过程。其效果类似mybatis-plus。
所需依赖
maven 的pom.xml 增加依赖如下:
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>2.1.5</version>
</dependency>
这种其中已经包含mybatis相关依赖包了。
相关mapper文件以及提供实现类
import org.apache.ibatis.annotations.UpdateProvider;
import java.util.List;
/**
* 批量update
*
* @param <T> 不能为空
*/
@tk.mybatis.mapper.annotation.RegisterMapper
public interface UpdateBatchByPrimaryKeySelectiveMapper<T> {
/**
* 根据Example条件批量更新实体`record`包含的不是null的属性值
*
* @return
*/
@UpdateProvider(type = BatchExampleProvider.class, method = "dynamicSQL")
int updateBatchByPrimaryKeySelective(List<? extends T> recordList);
}
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.SqlHelper;
import tk.mybatis.mapper.provider.ExampleProvider;
import java.util.Set;
public class BatchExampleProvider extends ExampleProvider {
public BatchExampleProvider(Class<?> mapperClass, MapperHelper mapperHelper) {
super(mapperClass, mapperHelper);
}
/**
* 拼update sql, 使用case when方式,id为主键
*
* @param ms
* @return
*/
public String updateBatchByPrimaryKeySelective(MappedStatement ms) {
final Class<?> entityClass = getEntityClass(ms);
//开始拼sql
StringBuilder sql = new StringBuilder();
sql.append(SqlHelper.updateTable(entityClass, tableName(entityClass)));
sql.append("<trim prefix=\"set\" suffixOverrides=\",\">");
//获取全部列
Set<EntityColumn> columnList = EntityHelper.getColumns(entityClass);
for (EntityColumn column : columnList) {
if (!column.isId() && column.isUpdatable()) {
sql.append(" <trim prefix=\""+column.getColumn()+" =case\" suffix=\"end,\">");
sql.append(" <foreach collection=\"list\" item=\"i\" index=\"index\">");
sql.append(" <if test=\"i."+column.getProperty()+"!=null\">");
sql.append(" when id=#{i.id} then #{i."+column.getProperty()+"}");
sql.append(" </if>");
sql.append(" </foreach>");
sql.append(" </trim>");
}
}
sql.append("</trim>");
sql.append("WHERE");
sql.append(" id IN ");
sql.append("<trim prefix=\"(\" suffix=\")\">");
sql.append("<foreach collection=\"list\" separator=\", \" item=\"i\" index=\"index\" >");
sql.append("#{i.id}");
sql.append("</foreach>");
sql.append("</trim>");
return sql.toString();
}
}
/**
* 批量操作接口
*
* @param <T>
* @author
*/
@tk.mybatis.mapper.annotation.RegisterMapper
public interface BatchMapper<T>
extends UpdateBatchByPrimaryKeySelectiveMapper<T> {
}
其中@tk.mybatis.mapper.annotation.RegisterMapper
该注解为了注册对应mapper类,要不然无法被tk使用。
使用方式
编写对应mapper接口时,如果想使用批量更新,直接继承对应类就可以了。
// Mapper是你使用的基类,而BatchMapper是你需要批量更新功能可以增加的。
public interface UserMapper extends Mapper<User>, BatchMapper<User> {
}
// 伪代码 , list为 ArrayList<User>();
userMapper.updateBatchByPrimaryKeySelective(list);
原理简述
其实从上面可以看出,本质就是原来mybatis中的xml文件内容变成根据每个对象的实际内容动态拼接,最终通过动态代理的方式将sql传递给数据库执行并返回结果。
参考
文章代码大部分内容参考:
但是根据本人实际遇到的问题做了更改,以及更详细的阐述。
本文额外给出一篇mybatis实现批量更新文章地址,有兴趣的读者可以自行对比。