tk.mybatis擴(kuò)展通用接口使用詳解
一.tk.mybatis已經(jīng)為我們封裝好了許多拆箱即用的通用mapper,但在實(shí)際的項(xiàng)目開發(fā)中想必不少小伙伴在數(shù)據(jù)庫(kù)設(shè)計(jì)中都會(huì)采用邏輯刪除這種方案,再去使用通用的mapper接口就不行了。
這時(shí)候就需要我們封裝一些擴(kuò)展的通用Mapper接口。
二.項(xiàng)目中提供了大量現(xiàn)成的方法,這些方法可以作為擴(kuò)展時(shí)的參考。
例如 selectAll 方法。
首先定義接口:
@RegisterMapper
public interface SelectAllMapper<T> {
/**
* 查詢?nèi)拷Y(jié)果
*
* @return
*/
@SelectProvider(type = MySelectProvider.class, method = "dynamicSQL")
List<T> selectAll();
}
其中 MySelectProvider 是你要實(shí)現(xiàn)的一個(gè)類,該類需要繼承 MapperTemplate。@RegisterMapper 注解可以避免 mappers 參數(shù)配置,通用 Mapper 檢測(cè)到該接口被繼承時(shí),會(huì)自動(dòng)注冊(cè)。
import org.apache.ibatis.mapping.MappedStatement;
import tk.mybatis.mapper.mapperhelper.MapperHelper;
import tk.mybatis.mapper.mapperhelper.MapperTemplate;
import tk.mybatis.mapper.mapperhelper.SqlHelper;
public class MySelectProvider extends MapperTemplate {
public BaseSelectProvider(Class<?> mapperClass, MapperHelper mapperHelper) {
super(mapperClass, mapperHelper);
}
/**
* 查詢?nèi)拷Y(jié)果
*
* @param ms
* @return
*/
public String selectAll(MappedStatement ms) {
final Class<?> entityClass = getEntityClass(ms);
//修改返回值類型為實(shí)體類型
setResultType(ms, entityClass);
StringBuilder sql = new StringBuilder();
sql.append(SqlHelper.selectAllColumns(entityClass));
sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass)));
sql.append(SqlHelper.orderByDefault(entityClass));
return sql.toString();
}
}
其中 selectAll 方法名要和接口中定義的方法名一致。其次就是該方法的參數(shù)為 MappedStatement類型。
在 selectAll 方法中,首先是獲取了當(dāng)前接口的實(shí)體類型:
final Class<?> entityClass = getEntityClass(ms);
因?yàn)榻涌诜祷刂殿愋蜑?List<T>,MyBatis 會(huì)認(rèn)為返回值類型為 List<Object>,這和我們想要的實(shí)體類型不一樣,所以下一行代碼就是設(shè)置返回值類型:
setResultType(ms, entityClass);
注意,只有返回 T 或者 List 時(shí)需要設(shè)置,返回 int 類型時(shí)不需要設(shè)置。
接下來就是純粹的拼接 XML 形式的 SQL 了。
/select col1,col2... sql.append(SqlHelper.selectAllColumns(entityClass)); //from tablename - 支持動(dòng)態(tài)表名 sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass))); //order by xxx sql.append(SqlHelper.orderByDefault(entityClass));
當(dāng)你想要實(shí)現(xiàn)某種方法時(shí),可以從已有的例子中找一個(gè)最接近的方法,在此基礎(chǔ)上進(jìn)行修改
三.例:根據(jù)主鍵查詢單個(gè)實(shí)體對(duì)象(過濾掉邏輯刪除的實(shí)體,注:我的數(shù)據(jù)表邏輯刪除字段定義為enabled_status)
首先定義mapper
@RegisterMapper
public interface SelectByKeyAndNotDeletedMapper<T> {
/**
* 根據(jù)主鍵查詢沒有被邏輯刪除的實(shí)體
*
* @return
*/
@SelectProvider(type = SelectByKeyNotDeletedProvider.class, method = "dynamicSQL")
T selectByKeyNotDeleted(Object key);
}
其次定義SelectByKeyNotDeletedProvider
public class SelectByKeyNotDeletedProvider extends MapperTemplate {
public SelectByKeyNotDeletedProvider(Class<?> mapperClass, MapperHelper mapperHelper) {
super(mapperClass, mapperHelper);
}
public String selectByKeyNotDeleted(MappedStatement ms) {
final Class<?> entityClass = getEntityClass(ms);
//將返回值修改為實(shí)體類型
setResultType(ms, entityClass);
StringBuilder sql = new StringBuilder();
sql.append(SqlHelper.selectAllColumns(entityClass));
sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass)));
sql.append(wherePKColumns(entityClass, false));
return sql.toString();
}
private String wherePKColumns(Class<?> entityClass, boolean useVersion) {
StringBuilder sql = new StringBuilder();
sql.append("<where>");
//獲取全部列
Set<EntityColumn> columnSet = EntityHelper.getPKColumns(entityClass);
//當(dāng)某個(gè)列有主鍵策略時(shí),不需要考慮他的屬性是否為空,因?yàn)槿绻麨榭?,一定?huì)根據(jù)主鍵策略給他生成一個(gè)值
for (EntityColumn column : columnSet) {
sql.append(" AND " + column.getColumnEqualsHolder());
}
if (useVersion) {
sql.append(whereVersion(entityClass));
}
//過濾被邏輯刪除的數(shù)據(jù)
sql.append(" AND enabled_status = 1 ");
sql.append("</where>");
return sql.toString();
}
}
然后定義BasicMapper,讓其繼承通用Mapper接口以及上面自定義的SelectByKeyAndNotDeletedMapper接口。
@tk.mybatis.mapper.annotation.RegisterMapper public interface BasicMapper<T> extends Mapper<T>, SelectByKeyAndNotDeletedMapper<T> { }
最后在通用service中引入,
@Autowired private BasicMapper<T> mapper;
自定義*.Mapper都去繼承BasicMapper<T>即可
public interface UserPOMapper extends BasicMapper<UserPO> {}
注意:最新版本的tk已經(jīng)支持根據(jù)注解@LogicDelete實(shí)現(xiàn)邏輯刪除
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java利用trueLicense實(shí)現(xiàn)項(xiàng)目離線證書授權(quán)操作步驟
文章介紹了如何使用trueLicense實(shí)現(xiàn)離線授權(quán)控制,包括生成公私鑰、創(chuàng)建證書校驗(yàn)?zāi)K、生成證書模塊和測(cè)試模塊,通過這種方式,可以控制用戶使用的項(xiàng)目模塊、授權(quán)周期、使用的設(shè)備和服務(wù)器,感興趣的朋友跟隨小編一起看看吧2024-11-11
java.lang.NoClassDefFoundError錯(cuò)誤的原因及解決方法
這篇文章主要給大家介紹了關(guān)于java.lang.NoClassDefFoundError錯(cuò)誤的原因及解決的相關(guān)資料,java.lang.NoClassDefFoundError是Java虛擬機(jī)在運(yùn)行時(shí)無法找到特定類的錯(cuò)誤,需要的朋友可以參考下2023-10-10
SpringBoot定時(shí)調(diào)度之Timer與Quartz詳解
Java?中常用的定時(shí)調(diào)度框架有以下幾種:Timer、ScheduledExecutorService、Spring?Task和Quartz,本文主要來和大家講講他們的具體使用,需要的可以參考一下2023-06-06
Java?將list集合數(shù)據(jù)按照時(shí)間字段排序的方法
這篇文章主要介紹了Java?將list集合數(shù)據(jù)按照時(shí)間字段排序,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03
Spring如何基于xml實(shí)現(xiàn)聲明式事務(wù)控制
這篇文章主要介紹了Spring如何基于xml實(shí)現(xiàn)聲明式事務(wù)控制,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10
Maven pom.xml文件中build,plugin標(biāo)簽的使用小結(jié)
本文主要介紹了Maven pom.xml文件中build,plugin標(biāo)簽的使用小結(jié),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-03-03

