在JavaEE JPA Web应用程序中,要素实体与患者实体具有双向ManyToOne关系。我想写一个查询来统计具有一个或多个匹配条件特征的患者人数。我使用EclipseLink作为Persistence Provider。
例如,我要计算具有'variableName'='Sex'和'variableData'='Female'且具有'variableName'='吸烟'和'variableData'='是。
如何编写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;
}
}
这是要素实体。
@Entity
public class Feature implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String variableName;
private String variableData;
@ManyToOne
private Patient patient;
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 Feature)) {
return false;
}
Feature other = (Feature) 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.Feature[ id=" + id + " ]";
}
public String getVariableName() {
return variableName;
}
public void setVariableName(String variableName) {
this.variableName = variableName;
}
public String getVariableData() {
return variableData;
}
public void setVariableData(String variableData) {
this.variableData = variableData;
}
public Patient getPatient() {
return patient;
}
public void setPatient(Patient patient) {
this.patient = patient;
}
}
@Query("select count(f.patient) from Feature f where f.variableName=:name and f.variableData:=data")
long countPatients(@Param("name") String variableName, @Param("data") String variableData);
对于具有多种功能的患者计数,您可以使用规范
public class Specifications {
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);
}
}
}
然后您的PatientRepository必须扩展JpaSpecificationExecutor<Feature>
您的服务方式:
public class PatientService {
@Autowired
PatientRepository patientRepository;
public long countPatiens(Map<String, String> nameDataMap) {
Specification<Patient> spec = null;
for(Map.Entry<String, String> entry : nameDataMap.entrySet()) {
Specification<Patient> tempSpec = Specifications.hasVariable(entry.getKey(), entry.getValue());
if(spec != null)
spec = Specifications.where(tempSpec);
else spec = tempSpec;
}
patientRepository.count(spec);
}
}