Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.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
Jpa JPQL统计OneToMany关系中多个子匹配上的父对象数_Jpa_Eclipselink_Jpql - Fatal编程技术网

Jpa JPQL统计OneToMany关系中多个子匹配上的父对象数

Jpa JPQL统计OneToMany关系中多个子匹配上的父对象数,jpa,eclipselink,jpql,Jpa,Eclipselink,Jpql,在JavaEE JPA web应用程序中,特征实体与患者实体具有双向多通关系。我想写一个查询来统计拥有一个或多个匹配条件功能的患者数量。我使用EclipseLink作为持久性提供者 例如,我想统计具有“variableName”为“Sex”和“variableData”为“Femal”的功能以及具有“variableName”为“smoking”和“variableData”为“yes”的功能的患者数量 如何编写JPQL查询以获取患者数量 在第一次回答之后,我尝试了这个查询,但没有给出预期的结果

在JavaEE JPA web应用程序中,特征实体与患者实体具有双向多通关系。我想写一个查询来统计拥有一个或多个匹配条件功能的患者数量。我使用EclipseLink作为持久性提供者

例如,我想统计具有“variableName”为“Sex”和“variableData”为“Femal”的功能以及具有“variableName”为“smoking”和“variableData”为“yes”的功能的患者数量

如何编写JPQL查询以获取患者数量

在第一次回答之后,我尝试了这个查询,但没有给出预期的结果

public void querySmokingFemales(){
    String j = "select count(f.patient) from Feature f "
            + "where ((f.variableName=:name1 and f.variableData=:data1)"
            + " and "
            + " (f.variableName=:name2 and f.variableData=:data2))";
    Map m = new HashMap();
    m.put("name1", "sex");
    m.put("data1", "female");
    m.put("name2", "smoking");
    m.put("data2", "yes");
    count = getFacade().countByJpql(j, m);
}
患者实体如下所示

@Entity
public class Patient implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;
    @OneToMany(mappedBy = "patient")
    private List<Feature> features;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }



    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Patient)) {
            return false;
        }
        Patient other = (Patient) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "entity.Patient[ id=" + id + " ]";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<Feature> getFeatures() {
        return features;
    }

    public void setFeatures(List<Feature> features) {
        this.features = features;
    }

}

对于单个特征计数您可以使用

select count(f.patient) from Feature f where f.variableName=:name and f.variableData:=data
两个功能计数

select count(distinct p) from Patient p, Feature f1, Feature f2 
where 
  p.id=f1.patient.id and p.id=f2.patient.id and 
  f1.variableName=:name1 and f1.variableData:=data1 and 
  f2.variableName=:name2 and f2.variableData:=data2
多功能计数解决方案有点棘手<可以使用code>org.springframework.data.jpa.domain.Specification

    public class PatientSpecifications {
      public static Specification<Patient> hasVariable(String name, String data) {
        return (root, query, builder) ->  {
                    Subquery<Fearure> subquery = query.subquery(Fearure.class);
                    Root<Fearure> feature = subquery.from(Fearure.class);

                    Predicate predicate1 = builder.equal(feature.get("patient").get("id"), root.get("id"));

                    Predicate predicate2 = builder.equal(feature.get("variableName"), name);
                    Predicate predicate3 = builder.equal(feature.get("variableData"), data);

                    subquery.select(operation).where(predicate1, predicate2, predicate3);

                    return builder.exists(subquery);
        }
      }
    }
公共类患者规范{
公共静态规范hasVariable(字符串名称、字符串数据){
返回(根、查询、生成器)->{
Subquery Subquery=query.Subquery(Fearure.class);
根特征=子查询.from(Fearure.class);
谓词谓词谓词1=builder.equal(feature.get(“patient”).get(“id”)、root.get(“id”);
谓词predicate2=builder.equal(feature.get(“variableName”),name);
谓词谓词3=builder.equal(feature.get(“variableData”)、data);
选择(操作).where(谓词1、谓词2、谓词3);
返回生成器.exists(子查询);
}
}
}
然后您的PatientPosition必须扩展
org.springframework.data.jpa.repository.JpaSpecificationExecutor

@存储库
公共接口存储
扩展JpaRepository、JpaSpecificationExecutor{
}
您的服务方式:

@Service
public class PatientService {    

   @Autowired
   PatientRepository patientRepository;

   //The larger map is, the more subqueries query would involve. Try to avoid large map
   public long countPatiens(Map<String, String> nameDataMap) {
         Specification<Patient> spec = null;

         for(Map.Entry<String, String> entry : nameDataMap.entrySet()) {
            Specification<Patient> tempSpec = PatientSpecifications.hasVariable(entry.getKey(), entry.getValue());
            if(spec != null)
              spec = Specifications.where(spec).and(tempSpec);
            else spec = tempSpec;

         }

         Objects.requireNonNull(spec);

         return patientRepository.count(spec);        
    }
}
@服务
公共类PatientService{
@自动连线
病人肯定的病人肯定的;
//地图越大,查询涉及的子查询越多。请尽量避免使用大地图
公共长CountPatients(地图名称DataMap){
规格规格=空;
对于(Map.Entry:nameDataMap.entrySet()){
Specification tempSpec=patientsspecifications.hasVariable(entry.getKey(),entry.getValue());
如果(规格!=null)
规范=规范,其中(规范)和(临时规范);
else spec=临时spec;
}
对象。要求完整(规范);
返回patientRepository.count(规格);
}
}

对于单个功能计数您可以使用此

select count(f.patient) from Feature f where f.variableName=:name and f.variableData:=data
两个功能计数

select count(distinct p) from Patient p, Feature f1, Feature f2 
where 
  p.id=f1.patient.id and p.id=f2.patient.id and 
  f1.variableName=:name1 and f1.variableData:=data1 and 
  f2.variableName=:name2 and f2.variableData:=data2
多功能计数解决方案有点棘手<可以使用code>org.springframework.data.jpa.domain.Specification

    public class PatientSpecifications {
      public static Specification<Patient> hasVariable(String name, String data) {
        return (root, query, builder) ->  {
                    Subquery<Fearure> subquery = query.subquery(Fearure.class);
                    Root<Fearure> feature = subquery.from(Fearure.class);

                    Predicate predicate1 = builder.equal(feature.get("patient").get("id"), root.get("id"));

                    Predicate predicate2 = builder.equal(feature.get("variableName"), name);
                    Predicate predicate3 = builder.equal(feature.get("variableData"), data);

                    subquery.select(operation).where(predicate1, predicate2, predicate3);

                    return builder.exists(subquery);
        }
      }
    }
公共类患者规范{
公共静态规范hasVariable(字符串名称、字符串数据){
返回(根、查询、生成器)->{
Subquery Subquery=query.Subquery(Fearure.class);
根特征=子查询.from(Fearure.class);
谓词谓词谓词1=builder.equal(feature.get(“patient”).get(“id”)、root.get(“id”);
谓词predicate2=builder.equal(feature.get(“variableName”),name);
谓词谓词3=builder.equal(feature.get(“variableData”)、data);
选择(操作).where(谓词1、谓词2、谓词3);
返回生成器.exists(子查询);
}
}
}
然后您的PatientPosition必须扩展
org.springframework.data.jpa.repository.JpaSpecificationExecutor

@存储库
公共接口存储
扩展JpaRepository、JpaSpecificationExecutor{
}
您的服务方式:

@Service
public class PatientService {    

   @Autowired
   PatientRepository patientRepository;

   //The larger map is, the more subqueries query would involve. Try to avoid large map
   public long countPatiens(Map<String, String> nameDataMap) {
         Specification<Patient> spec = null;

         for(Map.Entry<String, String> entry : nameDataMap.entrySet()) {
            Specification<Patient> tempSpec = PatientSpecifications.hasVariable(entry.getKey(), entry.getValue());
            if(spec != null)
              spec = Specifications.where(spec).and(tempSpec);
            else spec = tempSpec;

         }

         Objects.requireNonNull(spec);

         return patientRepository.count(spec);        
    }
}
@服务
公共类PatientService{
@自动连线
病人肯定的病人肯定的;
//地图越大,查询涉及的子查询越多。请尽量避免使用大地图
公共长CountPatients(地图名称DataMap){
规格规格=空;
对于(Map.Entry:nameDataMap.entrySet()){
Specification tempSpec=patientsspecifications.hasVariable(entry.getKey(),entry.getValue());
如果(规格!=null)
规范=规范,其中(规范)和(临时规范);
else spec=临时spec;
}
对象。要求完整(规范);
返回patientRepository.count(规格);
}
}

我们还为两个特性处理了相同的情况,在提取ID之后,我们在和计数公共计数的数量之后使用了嵌套循环。这是一个资源密集型的问题,答案中的这两个功能查询帮助很大

对于两个特征,我们也处理了相同的情况,在提取ID之后,我们使用了一个嵌套循环,然后计算公共计数的数量。这是一个资源密集型的问题,答案中的这两个功能查询帮助很大

可能需要重新设计类结构以便于查询。

可能需要重新设计类结构以便于查询。

它给出了此错误。编译[从功能f中选择计数(f.patient),其中f.variableName=:名称和f.variableData:=数据]时出现问题。[72,87]无法将状态字段路径“f.variableData:”解析为有效类型。[90,94]FROM子句中未定义标识变量“data”。很抱歉,它是一种类型。现在查询不计算记录。这又是我的打字错误。它很好用。谢谢。它有一个功能。但是我需要搜索两个特性。如问题中所述,“性别”=“男性”为一,而“吸烟”=“是”。您只需要两个特征患者计数还是多个特征患者计数?它会给出此错误。