Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Hibernate中使用编程条件创建查询的最佳方法_Hibernate_Criteria_Named Parameters - Fatal编程技术网

在Hibernate中使用编程条件创建查询的最佳方法

在Hibernate中使用编程条件创建查询的最佳方法,hibernate,criteria,named-parameters,Hibernate,Criteria,Named Parameters,假设我有一个方法负责根据传递给它的参数构建查询: public Query<User> buildQuery(String name, String city) { Session session = HibernateUtil.getSessionFactory().openSession(); String queryString = "from Users where 1 = 1 "; if (name != null)

假设我有一个方法负责根据传递给它的参数构建查询:

    public Query<User> buildQuery(String name, String city) {
        Session session = HibernateUtil.getSessionFactory().openSession();

        String queryString = "from Users where 1 = 1 ";
        if (name != null) queryString += "and name = :name ";
        if (city != null) queryString += "and city = :city ";

        Query<User> query = session.createQuery(queryString, User.class);

        if (name != null) query.setParameter("name", name);
        if (city != null) query.setParameter("city", city);

        return query;
    }
公共查询buildQuery(字符串名称,字符串城市){
Session Session=HibernateUtil.getSessionFactory().openSession();
字符串queryString=“来自用户,其中1=1”;
如果(name!=null)queryString+=“和name=:name”;
如果(city!=null)queryString+=“和city=:city”;
Query=session.createQuery(queryString,User.class);
if(name!=null)query.setParameter(“name”,name);
if(city!=null)query.setParameter(“city”,city);
返回查询;
}
我不喜欢这样,因为逻辑重复了两次(用于添加条件和设置参数)

我想到的唯一解决方案是使用条件查询:

    public Query<User> buildQuery2(String name, String city) {
        Session session = HibernateUtil.getSessionFactory().openSession();

        CriteriaBuilder builder = session.getCriteriaBuilder();         
        CriteriaQuery<User> criteriaQuery = builder.createQuery(User.class);
        Root<User> root = criteriaQuery.from(User.class);
        Predicate predicate = builder.conjunction();
        if (name != null) {
            predicate = builder.and(predicate, builder.equal(root.get("name"), name));
        }
        if (city != null) {
            predicate = builder.and(predicate, builder.equal(root.get("city"), city));
        }
        criteriaQuery.select(root).where(predicate);            
        Query<User> query = session.createQuery(criteriaQuery);
        return query;
    }
公共查询buildQuery2(字符串名称,字符串城市){
Session Session=HibernateUtil.getSessionFactory().openSession();
CriteriaBuilder=session.getCriteriaBuilder();
CriteriaQuery CriteriaQuery=builder.createQuery(User.class);
Root=criteriaQuery.from(User.class);
谓词=builder.conjunction();
if(name!=null){
谓词=builder.and(谓词,builder.equal(root.get(“name”),name));
}
如果(城市!=null){
谓词=builder.and(谓词,builder.equal(root.get(“city”),city));
}
选择(根)。其中(谓词);
Query Query=session.createQuery(criteriaQuery);
返回查询;
}

有更好的解决方案吗?

JPA Criteria API方法是一种方法,但是添加新的过滤器将需要更改您的业务代码,这不是很理想。此外,在某些情况下,将所有可能的筛选值列为方法的参数是非常痛苦的

我建议你看看能提供什么

我创建了这个库,以便在JPA模型和自定义接口定义的模型之间进行轻松映射,类似于类固醇上的Spring数据投影。其思想是以您喜欢的方式定义目标结构,并通过JPQL表达式将属性(getter)映射到实体模型。由于属性名被用作默认映射,您基本上不需要显式映射,因为80%的用例都需要DTO作为实体模型的子集。最好的是,您可以为投影定义过滤器

您的模型的映射可以看起来像下面这样简单

@EntityView(User.class)
interface UserView {
  @IdMapping
  Long getId();
  @AttributeFilter(EqualFilter.class)
  String getName();
  @AttributeFilter(EqualFilter.class)
  String getCity();
}
在表示层中,您可以构建一个
EntityViewSetting
对象,您可以将其传递到服务层

EntityViewSetting<UserView, CriteriaBuilder<UserView>> setting = EntityViewSetting.create(UserView.class);
if (nameFilter != null) setting.addAttributeFilter("name", nameFilter);
if (cityFilter != null) setting.addAttributeFilter("city", cityFilter);
EntityViewSetting=EntityViewSetting.create(UserView.class);
if(nameFilter!=null)设置.addAttributeFilter(“name”,nameFilter);
if(cityFilter!=null)setting.addAttributeFilter(“city”,cityFilter);
然后,您的服务可以是纯业务逻辑的,类似这样的

<T> T findAll(EntityViewSetting<T, CriteriaBuilder<T>> setting) {
    CriteriaBuilder<User> cb = criteriaBuilderFactory.create(entityManager, User.class);
    // Your business logic
    return entityViewManager.applySetting(setting, cb);
}
T findAll(实体视图设置){
CriteriaBuilder cb=criteriaBuilderFactory.create(entityManager,User.class);
//您的业务逻辑
返回entityViewManager.applySetting(设置,cb);
}

谢谢你的回答,我肯定会调查Blaze,但目前我必须坚持纯Hibernate。你能详细介绍一下这个话题吗?你对JPA标准API的使用还可以。你有什么特别的方法不起作用吗?我的解决方案非常有效,我只是想知道其他方法是否更好。谢谢