【问题标题】:How to create a dynamic WHERE clause for all queries in Spring Data JPA?如何为 Spring Data JPA 中的所有查询创建动态 WHERE 子句?
【发布时间】:2020-12-23 19:32:39
【问题描述】:

我有一个要求,我需要将全局 WHERE 条件动态传递给所有查询?

我们的表格中有多个组织的数据。所以,我需要在检索数据时传递ORG_ID = ?。

我不想写像findBy..AndOrgId(... Integer orgId) 这样的查找器方法。有一个更好的方法吗?应用全局WHERE 子句或谓词?

我收到这个orgId 作为RestController 中请求属性的一部分。由于它是动态的,我不能在实体类上使用休眠注解@Where。

【问题讨论】:

  • @SternK 不应该从帖子中删除对 spring 数据的引用
  • 我没有这样做。见this。帖子标题不适合技术名称。
  • @SternK Spring Data 可能位于标题的末尾。例如,检查接受的答案假设。
  • 谢谢..我已将它添加到标题的末尾

标签: hibernate spring-data-jpa spring-data


【解决方案1】:

你可以尝试使用hibernate@Filter注解。正如documentation 中所述:

@Filter 注释是另一种使用自定义 SQL 标准过滤掉实体或集合的方法。与@Where 注解不同,@Filter 允许您在运行时参数化过滤子句。

示例 1:

import org.hibernate.annotations.Filter;
import org.hibernate.annotations.FilterDef;
import org.hibernate.annotations.ParamDef;

@Entity
@Table(name = "MY_ORDER")
@FilterDef(
   name="byId",
   parameters = @ParamDef(
      name="ordId",
      type="long"
   )
)
@Filter(
   name="byId",
   condition="ord_id = :ordId"
)
public class MyOrder
{
   @Id
   @Column(name = "ord_id")
   private Long id;

   // ...
}

及用法:

EntityManager em = emFactory.createEntityManager();
// ...
em.unwrap(Session.class).enableFilter("byId").setParameter("ordId", 2L);

List<MyOrder> orders = em.createQuery("select o from MyOrder o", MyOrder.class)
   .getResultList();

将生成以下sql:

/* select o from MyOrder o */
select
  myorder0_.ord_id as ord_id1_3_,
  myorder0_.ord_time as ord_time2_3_ 
from TEST_SCHEMA.MY_ORDER myorder0_ 
where myorder0_.ord_id = ?

编辑

上述方法也适用于 spring data jpa @Query 以及从方法名称派生的查询。

示例 2:

@Entity
@Table(name = "post")
@FilterDef(
   name="postById",
      parameters = @ParamDef(
         name="postId",
         type="long"
      )
   )
@Filter(
   name="postById",
   condition="id = :postId"
)
public class Post
{
   @Id
   private Long id;

   @Enumerated(EnumType.ORDINAL)
   private PostStatus status;

   // getters, setters
}

public enum PostStatus { OPEN, CLOSE }

public interface PostRepository extends JpaRepository<Post, Long>
{
   @Query(value = "select p from Post p where p.status = :sts")
   List<Post> test(@Param("sts") PostStatus status);

   List<Post> findByStatus(PostStatus status);
}

@RestController
public class TestRestController
{
   @Autowired
   EntityManager entityManager;

   @Autowired
   private PostRepository postRepository;

   @RequestMapping("/")
   @Transactional
   public String home()
   {
      entityManager
          .unwrap(Session.class)
          .enableFilter("postById")
          .setParameter("postId", 10L);
       // ....
       List<Post> posts1 = postRepository.test(PostStatus.OPEN);
       List<Post> posts2 = postRepository.findByStatus(PostStatus.OPEN);
   }      
}

【讨论】:

  • 我喜欢使用@Filter 的想法,有什么方法可以在存储库中使用@Query 吗?
【解决方案2】:

Spring Data(我假设您正在使用基于您的帖子标签的 Spring Data)不支持查询扩充(在撰写本文时)。对该功能的长期需求here 还描述了其他人尝试过的一些替代方案。

祝你好运!

【讨论】:

  • 谢谢.. 是的正在寻找基于 spring-data-jpa 的解决方案
猜你喜欢
  • 2014-02-24
  • 2019-05-20
  • 2015-09-20
  • 1970-01-01
  • 2016-11-26
  • 1970-01-01
  • 2020-06-19
  • 1970-01-01
  • 2015-01-27
相关资源
最近更新 更多