Jpa JPQL统计OneToMany关系中多个子匹配上的父对象数
在JavaEE JPA web应用程序中,特征实体与患者实体具有双向多通关系。我想写一个查询来统计拥有一个或多个匹配条件功能的患者数量。我使用EclipseLink作为持久性提供者 例如,我想统计具有“variableName”为“Sex”和“variableData”为“Femal”的功能以及具有“variableName”为“smoking”和“variableData”为“yes”的功能的患者数量 如何编写JPQL查询以获取患者数量 在第一次回答之后,我尝试了这个查询,但没有给出预期的结果Jpa JPQL统计OneToMany关系中多个子匹配上的父对象数,jpa,eclipselink,jpql,Jpa,Eclipselink,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”。很抱歉,它是一种类型。现在查询不计算记录。这又是我的打字错误。它很好用。谢谢。它有一个功能。但是我需要搜索两个特性。如问题中所述,“性别”=“男性”为一,而“吸烟”=“是”。您只需要两个特征患者计数还是多个特征患者计数?它会给出此错误。