如何重写Spring存储库方法以在布尔列上添加约束?

huangapple go评论91阅读模式
英文:

How can I override Spring repository methods to add a constraint on a boolean column?

问题

我正在阅读《Spring In Action》(第6版),以便学习Spring框架,我有一个关于如何覆盖Spring JPA默认行为的疑问,当声明存储库时。

据我迄今为止所读,我可以声明存储库方法,比如findByName(),然后让Spring神奇地实现这个方法。现在,让我们想象一下,存储库中的记录有一个名为enabled的布尔列,我希望应用程序只处理enabled = TRUE的记录。我知道我可以声明诸如findByNameAndEnabledIsTrue()之类的方法,但我想知道是否有一种方法可以使例如findByName()考虑到这个标志。

到目前为止,我尝试覆盖该方法,但似乎不起作用,因为在编译时实际上没有定义方法:

@Override
List<Customer> findByName(@Param("name") String name) {
    return findByNameAndEnabledIsTrue(name);
}

这该怎么做呢?

谢谢。

英文:

I am reading Spring In Action (6th edition) to get myself into learning the Spring framework and I have a doubt about how to override the default behavior of Spring JPA when declaring repositories.

As far as I have read so far, I can declare repository methods such as findByName() and let Spring magically implement the method. Now, let's imagine that the records in the repository have a boolean column named enabled, and I want the application to only process the records with enabled = TRUE. I know I could declare methods such as findByNameAndEnabledIsTrue() but I wonder whether there is a way to make, for example, findByName() take into account this flag.

So far I tried to override the method, but it doesn't seem to work, since there's actual no method defined at compile time:

@Override
List&lt;Customer&gt; findByName(@Param(&quot;name&quot;) String name) {
    return findByNameAndEnabledIsTrue(name);
}

How could this be done?

Thank you.

答案1

得分: 1

最简单的方法是使用@Query来明确定义查询,使用JPQL而不是依赖spring-data根据查询方法名称生成查询。通过这种方式,您可以完全控制定义您想要的查询。类似于:

public interface CustomerRepository extends JpaRepository<Customer, Long> {

  @Query("select u from Customer c where c.name = :name and c.enabled = true")
  List<Customer> findByName(@Param("name") String name);
}

这是我喜欢的方式。简单、灵活,减少了很多魔法。

如果您坚持不想编写JPQL,您可以实现一个自定义存储库(参见此处),并将CustomerRepository注入到这个自定义存储库中,以重用其方法。类似于:

interface CustomerRepository extends JpaRepository<Customer, Long>, CustomizedCustomerRepository {

    List<Customer> findByNameAndEnabledIsTrue();   
}

interface CustomizedCustomerRepository {
  void findByName(String name);
}

class CustomizedCustomerRepositoryImpl implements CustomizedCustomerRepository {

  @Autowired
  private CustomerRepository repo;

  @Override
  List<Customer> findByName(String name) {
    return repo.findByNameAndEnabledIsTrue(name);
  }
}
英文:

The simplest way is to use @Query to explicitly define the query using JPQL rather than relies on spring-data to generate the query based on the query method name. In this way, you can get back the total control to define what the query you exactly want to have . Something like :

public interface CustomerRepository extends JpaRepository&lt;Customer, Long&gt; {

  @Query(&quot;select u from Customer c where c.name = :name and c.enabled = true&quot;)
  List&lt;Customer&gt; findByName(@Param(&quot;name&quot;) String name);
}

This is the way I prefer. Simple, flexible and much less magic.

If you insist do not want to write JPQL, you can implement a custom repository (See this) , and inject the CustomerRepository into this custom repository and reuse it method. Something like :

interface CustomerRepository extends JpaRepository&lt;Customer, Long&gt; , CustomizedCustomerRepository {

    List&lt;Customer&gt; findByNameAndEnabledIsTrue();   
}

interface CustomizedCustomerRepository {
  void findByName(String name);
}


class CustomizedCustomerRepositoryImpl implements CustomizedCustomerRepository {

  @Autowired
  private CustomerRepository repo;

  @Override
  List&lt;Customer&gt; findByName(String name) {
    return repo.findByNameAndEnabledIsTrue(name);
  }
}

huangapple
  • 本文由 发表于 2023年7月24日 18:38:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/76753656.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定