【问题标题】:How to use Criteria Queries in Spring Boot Data Jpa Application如何在 Spring Boot Data Jpa 应用程序中使用条件查询
【发布时间】:2017-10-31 20:42:24
【问题描述】:

我有一个使用 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);
}

我如何利用 Hibernate 在 Spring Boot 应用程序中为此类情况提供的 Criteria Query

【问题讨论】:

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


    【解决方案1】:

    来自docs

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

    这样定义接口

    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 Queries。或者还有其他 Spring Hibernate Jpa 之类的东西吗?
    • 你能不能像一个小例子一样解释一下。将不胜感激
    • 您必须从entitymanger 获取标准构建器,以便您在自定义实现中连接。使用标准构建器来构建您的查询。查看此link,了解有关条件查询的详细说明。
    • 你能帮我理解使用标准和JPQL的性能比较吗?
    【解决方案2】:

    使用Spring-boot-jpa,您几乎可以在任何地方使用entityManager。最常用的方法是为自定义方法创建自己的interface。

    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 Queries。或者还有其他 Spring Hibernate Jpa 之类的东西吗?
    • @Rahul hibernate 是默认的持久性提供程序。
    • 是的,帕特里克。但是如何获得相同的条件查询,你可以给一个小例子,例如你给出的上述答案
    【解决方案3】:

    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);
          }
        };
    }
    

    上面可以使用 lambdas 简化如下

    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 builder.lessThan(root.get("birthday"), date);
          }
        );
      }
    

    有关更多详细信息,请参阅此春季文档

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

    【讨论】:

    • 我尝试了这种方法,但在浏览到 .../customers/search/findCustomers 时出现 404 错误
    • 然后似乎找不到页面。你的网址正确吗?
    【解决方案4】:

    根据 Spring 文档HibernateTemplate:

    注意:Hibernate 访问代码也可以用纯 Hibernate 编码 风格。因此,对于新启动的项目,可以考虑采用 代替编码数据访问对象的标准 Hibernate 风格,基于 在 SessionFactory.getCurrentSession() 上。这个休眠模板 主要作为基于 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
    • 我已经更新了我的答案(只是添加了一个简单的例子)。有关更多信息,请按照答案中的给定链接objectdb.com/java/jpa/query/criteria
    • 感谢分析器
    【解决方案5】:

    你可以参考Query creation进入spring data JPA文档并查看表格,JPA从方法名称中提供多个查询创建,你可以避免使用字符串查询

    【讨论】:

      猜你喜欢
      • 2018-09-17
      • 1970-01-01
      • 2019-12-14
      • 1970-01-01
      • 2022-01-06
      • 2023-03-09
      • 1970-01-01
      • 2018-07-12
      • 1970-01-01
      相关资源
      最近更新 更多