tk.mybatis擴展通用接口


 一.tk.mybatis已經為我們封裝好了許多拆箱即用的通用mapper,但在實際的項目開發中想必不少小伙伴在數據庫設計中都會采用邏輯刪除這種方案,再去使用通用的mapper接口就不行了。這時候就需要我們封裝一些擴展的通用Mapper接口。

 

 二.項目中提供了大量現成的方法,這些方法可以作為擴展時的參考。

   例如 selectAll 方法。

   首先定義接口:

@RegisterMapper
public interface SelectAllMapper<T> {

    /**
     * 查詢全部結果
     *
     * @return
     */
    @SelectProvider(type = MySelectProvider.class, method = "dynamicSQL")
    List<T> selectAll();
}

  

     其中 MySelectProvider 是你要實現的一個類,該類需要繼承 MapperTemplate。@RegisterMapper 注解可以避免 mappers 參數配置,通用 Mapper 檢測到該接口被繼承時,會自動注冊。

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);
    }
  
    /**
     * 查詢全部結果
     *
     * @param ms
     * @return
     */
    public String selectAll(MappedStatement ms) {
        final Class<?> entityClass = getEntityClass(ms);
        //修改返回值類型為實體類型
        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 方法名要和接口中定義的方法名一致。其次就是該方法的參數為 MappedStatement類型。

 在 selectAll 方法中,首先是獲取了當前接口的實體類型:

 final Class<?> entityClass = getEntityClass(ms); 

因為接口返回值類型為 List<T>,MyBatis 會認為返回值類型為 List<Object>,這和我們想要的實體類型不一樣,所以下一行代碼就是設置返回值類型:

 setResultType(ms, entityClass); 

注意,只有返回 T 或者 List 時需要設置,返回 int 類型時不需要設置。

接下來就是純粹的拼接 XML 形式的 SQL 了。

/select col1,col2...
sql.append(SqlHelper.selectAllColumns(entityClass));
//from tablename - 支持動態表名
sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass)));
//order by xxx
sql.append(SqlHelper.orderByDefault(entityClass));

當你想要實現某種方法時,可以從已有的例子中找一個最接近的方法,在此基礎上進行修改

 

三.例:根據主鍵查詢單個實體對象(過濾掉邏輯刪除的實體,注:我的數據表邏輯刪除字段定義為enabled_status)

 首先定義mapper

@RegisterMapper
public interface SelectByKeyAndNotDeletedMapper<T> {

    /**
     * 根據主鍵查詢沒有被邏輯刪除的實體
     *
     * @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);
        //將返回值修改為實體類型
        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);
        //當某個列有主鍵策略時,不需要考慮他的屬性是否為空,因為如果為空,一定會根據主鍵策略給他生成一個值
        for (EntityColumn column : columnSet) {
            sql.append(" AND " + column.getColumnEqualsHolder());
        }
        if (useVersion) {
            sql.append(whereVersion(entityClass));
        }
        //過濾被邏輯刪除的數據
        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已經支持根據注解@LogicDelete實現邏輯刪除

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM