如何在Spring Boot Data JPA应用程序中使用Criteria查询

16

我有一个应用程序使用Spring Boot Data jpa。 到目前为止,我使用的存储库如下:

public interface StudentRepository extends CrudRepository<StudentEntity, Integer>{
    @Query(value = "" 
        + "SELECT s.studentname "
        + "FROM   studententity s, "
        + "       courseentity c "
        + "WHERE  s.courseid = c.courseid "
        + "       AND s.courseid IN (SELECT c.courseid "
        + "                          FROM   courseentity c "
        + "                          WHERE  c.coursename = ?1)")
    List<String> nameByCourse(String coursename);
}

如何在Spring Boot应用程序中利用Hibernate提供的Criteria Query

5个回答

34

文档中:

为了丰富存储库的自定义功能,您首先需要为自定义功能定义一个接口和实现。使用您提供的存储库接口来扩展自定义接口。

按以下方式定义一个接口:

public interface StudentRepositoryCustom {

    List<String> nameByCourse(String coursename);

}

然后像这样定义一个自定义实现该接口的实现:

@Service
class StudentRepositoryImpl implements StudentRepositoryCustom {

    @PersistenceContext
    private EntityManager em;

    public List<String> nameByCourse(String coursename) {            
        CriteriaBuilder cb = em.getCriteriaBuilder();
        //Using criteria builder you can build your criteria queries.
    }

}

现在您可以像这样在JPA存储库中扩展此自定义存储库实现。

public interface StudentRepository extends CrudRepository<StudentEntity, Integer>, StudentRepositoryCustom {

}

了解有关条件查询和条件构建器的更多信息here


谢谢。但是我们如何在Spring Boot中整合Hibernate Criteria查询呢?或者还有其他的Spring Hibernate JPA之类的东西吗? - Rahul
你能否在这里简单地举个例子来解释一下吗?非常感谢,谢谢。 - Rahul
你需要从你自定义实现中注入的 entitymanager 中获取条件构建器。使用条件构建器来构建你的查询。查看这个链接以获取关于条件查询的详细解释。 - Abdullah Khan
你能帮我了解使用Criteria和JPQL的性能比较吗? - mwKART
StudentRepositoryImpl 中的 @Service 注解是否正确?难道不应该是 @Repository 吗? - Philippe Gioseffi

9
使用Spring-boot-jpa,你几乎可以在任何地方使用entityManager。最常见的方法是为自定义方法创建一个接口。
public interface StudentCustomRepository {

    void anyCustomMethod();
    Student getStudentByName(String name);
}

然后将此接口实现到一个服务类中,您可以在其中进行自动装配并使用entityManager

@Service
public class StudentCustomRepositoryServiceImpl implements StudentCustomRepository {

     @PersistenceContext
     private EntityManager em;

     @Override
     public void anyCustomMethod(){
         //here use the entityManager
     }

     @Override
     StudentEntity getStudentByName(String name){
         Criteria crit = em.unwrap(Session.class).createCriteria(StudentEntity.class);
         crit.add(Restrictions.eq("name", name));
         List<StudentEntity> students = crit.list();
         return students.get(0);
     }
 }

你也可以决定将你的StudentRepository实现到你的新 StudentCustomRepositoryServiceImpl类中。

谢谢。但是我们如何在Spring Boot中整合Hibernate Criteria查询呢?或者有没有其他类似于Spring Hibernate Jpa的东西? - Rahul
@Rahul Hibernate是默认的持久化提供程序。 - Patrick
是的,Patrick。但是如何获取相同的条件查询呢?您能否给出一个简单的示例来说明您上面给出的答案? - Rahul
为什么在你的实现中使用 @Service 而不是 @Repository - Philippe Gioseffi

8
JPA 2引入了一个条件API,可用于以编程方式构建查询。您可以从JpaSpecificationExecutor扩展一个新接口。
public interface CustomerRepository extends 
  CrudRepository<Customer, Long>, 
  JpaSpecificationExecutor<Customer> {

  default List<Customer> findCustomers() {
    return findAll(CustomerSpecs.findCustomers());
  }

然后创建客户规格。
public final class CustomerSpecs {

    public static Specification<Customer> findCustomers() {
        return new Specification<Customer>() {
            public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query,
            CriteriaBuilder builder) {

         LocalDate date = new LocalDate().minusYears(2);
         return builder.lessThan(root.get("birthday"), date);
      }
    };
}

可以使用lambda表达式来简化上述过程,如下所示。
public interface CustomerRepository extends 
  CrudRepository<Customer, Long>, 
  JpaSpecificationExecutor<Customer> {

  default List<Customer> findCustomers() {
    return findAll(
      (root, query, cb) -> {
         LocalDate date = new LocalDate().minusYears(2);
         return cb.lessThan(root.get("birthday"), date);
      }
    );
  }

更多详细信息,请参考此处的Spring文档。

https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#specifications


我尝试了这种方法,但是当浏览到.../customers/search/findCustomers时,我会收到404错误。 - maximum
那么看起来页面不存在。你的URL正确吗? - sendon1982

2
根据Spring文档 HibernateTemplate:

注意:Hibernate访问代码也可以使用纯Hibernate样式编码。因此,对于新启动的项目,请考虑采用基于SessionFactory.getCurrentSession()的标准Hibernate样式编码数据访问对象。该HibernateTemplate主要作为迁移助手存在,以使基于Hibernate 3的数据访问代码受益于Hibernate 4.x中的缺陷修复。

而根据Hibernate文档:

新开发应重点关注JPA javax.persistence.criteria.CriteriaQuery API。最终,Hibernate特定的标准将作为扩展移植到JPA javax.persistence.criteria.CriteriaQuery中。

因此最好使用JPQL Criteria:JPA Criteria API Queries 示例:
  CriteriaBuilder cb = entityManager.getCriteriaBuilder();

  CriteriaQuery<Country> q = cb.createQuery(Country.class);
  Root<Country> c = q.from(Country.class);
  q.select(c);

entityManager应该使用@Autowired注入。详细信息请参见上面的链接。


那么我们在这里如何使用它呢?@Afridi - Rahul
我已经更新了我的回答(只是添加了一个简单的例子)。更多信息,请查看回答中给出的链接http://www.objectdb.com/java/jpa/query/criteria - Afridi
感谢您的回答。 - Rahul

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接