flea-frame-db使用之基於FleaJPAQuery實現JPA分表查詢

基於FleaJPAQuery實現JPA分表查詢

本文采用 EclipseLink的JPA實現,相關FleaJPAQuery的接入使用請移步個人另外幾篇博文html

首先討論一下,爲了實現JPA分表查詢,咱們須要作哪些事情:java

  • 分表規則定義(即從主表到分表的轉換實現)
  • 分表查詢實現(即JPA標準化查詢組件根據分表規則查詢具體分表)

1. JPA標準化查詢

在JPA中,實體對應的表由以下的註解定義:git

@Entity
@Table(name = "flea_login_log")

如上可見,實體類實際上只會對應一個表名,單純從這裏是沒法實現分表查詢。
那麼既然這樣沒法分表,咱們選擇退而求其次,看看錶名是何時,被那個對象使用,由於咱們能夠確認查詢最後的表名,必定是使用的註解定義的表名。
下面是調試過程的發現:
com.huazie.frame.db.jpa.common.FleaJPAQuerygithub

/**
     * <p> Flea JPA查詢對象池獲取以後,必定要調用該方法進行初始化 </p>
     *
     * @param entityManager JPA中用於增刪改查的接口
     * @param sourceClazz   實體類類對象
     * @param resultClazz   操做結果類類對象
     * @since 1.0.0
     */
    public void init(EntityManager entityManager, Class sourceClazz, Class resultClazz) {

        this.entityManager = entityManager;
        this.sourceClazz = sourceClazz;
        this.resultClazz = resultClazz;
        // 從持久化接口中獲取標準化生成器
        criteriaBuilder = entityManager.getCriteriaBuilder();
        // 經過標準化生成器 獲取 標準化查詢對象
        if (ObjectUtils.isEmpty(resultClazz)) {
            // 行記錄查詢結果
            criteriaQuery = criteriaBuilder.createQuery(sourceClazz);
        } else {
            // 單個查詢結果
            criteriaQuery = criteriaBuilder.createQuery(resultClazz);
        }
        // 經過標準化查詢對象,獲取根SQL表達式對象
        root = criteriaQuery.from(sourceClazz);
    }

以下兩張圖是根SQL表達式對象 Root 的Debug視圖,發現存儲實際表名的是 DatabaseTable 對象。
flea-frame-db使用之基於FleaJPAQuery實現JPA分表查詢
flea-frame-db使用之基於FleaJPAQuery實現JPA分表查詢
那麼既然找到了表名實際相關的地方,下面的重點就是如何在使用的JPA標準化查詢的過程當中,動態改變查詢的表名。下面給出上述咱們須要作的事情的解決方案:ide

2. 分表規則定義

實體類中定義的表名,咱們能夠理解爲主表名;分表名的命名規則首先須要肯定一下,定義以下配置:ui

<?xml version="1.0" encoding="UTF-8"?>
<tables>

    <!-- 定義分表配置
        name : 分表對應的主表名
        exp  : 分表名錶達式 (FLEA_TABLE_NAME)_(列名大寫)_(列名大寫)
    -->
    <table name="flea_login_log" exp="(FLEA_TABLE_NAME)_(CREATE_DATE)" desc="Flea登陸日誌表分表規則">
        <splits>
            <!-- 定義分表後綴
                key : 分表類型關鍵字 (可查看 com.huazie.frame.db.common.table.split.TableSplitEnum )
                column : 分表屬性列字段名
                implClass : 分表後綴轉換實現類
            -->
            <split key="yyyymm" column="create_date" implClass="com.huazie.frame.db.common.table.split.impl.YYYYMMTableSplitImpl"/>
        </splits>
    </table>

</tables>

分表規則相關實現代碼,能夠移步 GitHub 查看 TableSplitHelperthis

3. 分表查詢實現

在上述分表規則定義中, 咱們能夠看到分表名錶達式exp是由 主表名 和 分表字段 組成,分表字段的轉換實現規則由split定義。調試

@Override
    public void handle(CriteriaQuery criteriaQuery, Object entity) throws Exception {

        if (ObjectUtils.isEmpty(criteriaQuery) || ObjectUtils.isEmpty(entity)) {
            return;
        }

        // 獲取分表信息(包括主表名 和 分表名 【若是存在分表返回】)
        SplitTable splitTable = EntityUtils.getSplitTable(entity);

        // 存在分表,須要查詢指定分表
        if (StringUtils.isNotBlank(splitTable.getSplitTableName())) {
            Set<Root<?>> roots = criteriaQuery.getRoots();
            if (CollectionUtils.isNotEmpty(roots)) {
                // 從新設置 查詢的分表表名
                ((EntityTypeImpl<?>) roots.toArray(new Root<?>[0])[0].getModel()).getDescriptor().setTableName(splitTable.getSplitTableName());
            }
        }
    }

JPA分表查詢相關代碼能夠 移步 GitHub 查看 FleaJPAQueryEclipseLinkTableSplitHandler日誌

4. 自測

自測類能夠查看 AuthTest
flea-frame-db使用之基於FleaJPAQuery實現JPA分表查詢code

相關文章
相關標籤/搜索