記錄一次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實現批量更新文章地址,有興趣的讀者可以自行對比。