Spring数据jpa - 如何通过方法名称组合多个And和Or

Pre*_*jam 27 java spring-data spring-data-jpa

我正在尝试迁移该应用程序.我正在从Hibernate工作到Spring Data Jpa.

虽然spring数据jpa提供了简单的查询构建方法,但我仍然坚持创建使用And和的查询方法Or operator.

MethodName - findByPlan_PlanTypeInAndSetupStepIsNullOrStepupStepIs(...)

当它转换为查询时,前两个表达式被组合并执行为[(exp1 and exp2) or (exp3)].

而要求是](exp1) and (exp2 or exp3)].

任何人都可以告诉我,如果这是可以实现的 Spring data jpa?

小智 24

与Oliver就长而不可读的方法名称达成一致,但是为了论证,你可以通过使用等价来达到预期的结果

A /\ (B \/ C) <=> (A /\ B) \/ (A /\ C)
A and (B or C) <=> (A and B) or (A and C)
Run Code Online (Sandbox Code Playgroud)

所以在你的情况下它应该看起来像这样:

findByPlan_PlanTypeInAndSetupStepIsNullOrPlan_PlanTypeInAndStepupStepIs(...)
Run Code Online (Sandbox Code Playgroud)

  • 这基本上是有效的-但是:如何避免用method重复变量?(如果可能的话..) (2认同)

fat*_*ddy 10

选项1:您可以使用命名查询(请参阅使用JPA命名查询):

@Entity
@NamedQuery(name = "User.findByEmailAddress",
  query = "select u from User u where u.emailAddress = ?1")
public class User {

}

public interface UserRepository extends JpaRepository<User, Long> {

   User findByEmailAddress(String emailAddress);
}
Run Code Online (Sandbox Code Playgroud)

Option2:用于@Query编写您的自定义查询(请参阅使用@Query

public interface UserRepository extends JpaRepository<User, Long> {

   @Query("select u from User u where u.emailAddress = ?1")
   User findByEmailAddress(String emailAddress);
}
Run Code Online (Sandbox Code Playgroud)

  • 但是话又说回来,您的方法名称会不会开始看起来很混乱并且变得难以阅读?从方法名称派生的查询对于简单查询很方便 - 在某些时候你应该切换到 `@Query` 或类似的。 (2认同)

Oli*_*ohm 9

它目前是不可能的,也不会在未来.我认为,即使有可能,使用更复杂的查询,您也不希望人为地将所有查询复杂性压缩到方法名称中.不仅因为它很难消化查询中实际发生的事情,而且从客户端代码的角度来看:你想要使用富有表现力的方法名称 - 在简单的情况下findByUsername(…)- 查询派生允许你创建.

对于更复杂的东西,你只是将查询复杂性提升到调用代码中,建议转而使用一个可读的方法名称,该名称在语义上表达查询的作用,并在使用@Query,命名查询等手动声明的查询中保持查询复杂性..


小智 8

使用类似

findByFirstElementAndCriteriaOrSecondElementAndCriteria
Run Code Online (Sandbox Code Playgroud)

就像(第一&条件)或(第二&条件)->条件&(第一或第二)

  • 它将起作用,但是最大的缺点是您必须在查询中使用相同的条件作为参数传递相同的次数。在这种情况下,您将必须传递两个包含相同内容的变量`Criteria`:`findByFirstElementAndCriteriaOrSecondElementAndCriteria(Element element1,Criteriacriteria1,Element element2,Criteriacriteria2)//criteria1.equals(criteria2)-&gt; true` (2认同)