是否曾想過在 Spring Data JPA 中重寫查詢?

工程 | Greg L. Turnquist | 2022 年 5 月 2 日 | ...

有時,無論您嘗試應用多少功能,似乎都無法讓 Spring Data JPA 在查詢傳送到 EntityManager 之前應用您想要的所有內容。

使用 3.0.0-SNAPSHOT(並針對 Spring Data 的下一個里程碑版本系列),您現在可以在查詢傳送到 EntityManager 之前立即獲取查詢,並對其進行“重寫”。 也就是說,您可以在最後一刻進行任何更改。

請在下面檢視

示例 1. 使用 @Query 宣告 QueryRewriter

public interface MyRepository extends JpaRepository<User, Long> {

    @Query(value = "select original_user_alias.* from SD_USER original_user_alias",
                    nativeQuery = true, queryRewriter = MyQueryRewriter.class) // (1)
    List<User> findByNativeQuery(String param);

    @Query(value = "select original_user_alias from User original_user_alias",
                   queryRewriter = MyQueryRewriter.class) // (2)
    List<User> findByNonNativeQuery(String param);
}
  1. 這個純 SQL 查詢(由於 nativeQuery)將在查詢被呼叫之前透過尚未定義的 MyQueryRewriter 路由。

  2. 這個 JPQL 查詢也將在交給 EntityManager 之前透過相同的 MyQueryRewriter 路由。

然後,您可以編寫自己的票據,如下所示!

示例 2. 示例 QueryRewriter

public class MyQueryRewriter implements QueryRewriter {

    @Override
    public String rewrite(String query, Sort sort) {
        return query.replaceAll("original_user_alias", "rewritten_user_alias");
    }
}

好的,這有點牽強。 我們基本上是在更改特定查詢的別名。 但您實際上可以做任何您能想到的事情。 此掛鉤讓您有機會進行少量(或大量!)更改。

只需確保在應用程式上下文中註冊一個例項 MyQueryRewriter。 無論您使用 Spring Framework 的 @Component 基於註解中的一種,還是透過 @Configuration 類中的 @Bean 方法提供它,選擇權都在您手中。

警告

您的 QueryRewriter 是在 Spring Data JPA 執行任何和所有檢查之後呼叫的。 您有責任向 EntityManager 提供有效的查詢。

但是等等……還有更多!

雖然您可以將您的 QueryRewriter 編寫為單獨的 bean,但也可以將其直接放在使用的儲存庫中!

示例 3. 提供 QueryRewriter 的儲存庫

public interface MyRepository extends JpaRepository<User, Long>,
                                   QueryRewriter { // (1)

    @Query(value = "select original_user_alias.* from SD_USER original_user_alias",
                   nativeQuery = true, queryRewriter = MyRepository.class) // (2)
    List<User> findByNativeQuery(String param);

    @Query(value = "select original_user_alias from User original_user_alias",
                   queryRewriter = MyRepository.class) // (3)
    List<User> findByNonNativeQuery(String param);

    @Override
    default String rewrite(String query, Sort sort) { // (4)
        return query.replaceAll("original_user_alias", "rewritten_user_alias");
    }
}
  1. 讓您的儲存庫介面擴充套件 QueryRewriter 介面。

  2. 將您的儲存庫名稱插入到本機查詢的 @Query.queryRewriter 條目中。

  3. 將您的儲存庫名稱插入到 JPQL 查詢的 @Query.queryRewriter 條目中。

  4. 覆蓋 rewrite(String,Sort) 方法並插入一個 default 值,然後 **POOF** 您就完成了!

公平警告:根據您所做的事情,您可能需要多個重寫器。

Spring Data JPA 不僅支援 Spring 的應用程式上下文,還支援基於 CDI 的環境。

查詢愉快!

-Greg Turnquist

獲取 Spring 新聞通訊

透過 Spring 新聞通訊保持聯絡

訂閱

領先一步

VMware 提供培訓和認證來加速您的進步。

瞭解更多

獲取支援

Tanzu Spring 在一個簡單的訂閱中提供對 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位制檔案。

瞭解更多

即將舉行的活動

檢視 Spring 社群中所有即將舉行的活動。

檢視全部