有时,无论你尝试应用多少功能,似乎都不可能让Spring Data JPA在查询被发送到EntityManager 之前应用你想要的一切。
有了3.0.0-SNAPSHOT (目标是Spring Data的下一个里程碑版本),你现在有能力在查询被发送到EntityManager ,并 "重写 "它。也就是说,你可以在最后一刻做任何改动。
请看下面的例子。
例1.声明一个 QueryRewriter,使用@Query
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);
}
-
这个纯SQL查询(感谢
nativeQuery)将在查询被调用之前被路由到尚未定义的MyQueryRewriter。 -
这个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框架的一个基于@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");
}
}
-
让你的资源库接口扩展
QueryRewriter接口。 -
将你的资源库的名字插入本地查询的
@Query.queryRewriter条目中。 -
在 JPQL 查询的
@Query.queryRewriter条目中插入你的资源库的名字。 -
覆盖
rewrite(String,Sort)方法并插入一个default的值,然后POOF你就完成了。
公平的警告:根据你所做的具体工作,你可能需要一个以上的重写器。
Spring Data JPA不仅支持Spring的应用环境,还支持基于CDI的环境。
祝你查询愉快!