I have an enum as an attribute of an Entity. When I try to use the enum in a JPQL query, it gives an error. What is the correct method to use except passing it as a parameter?
Enum is
package com.divudi.data;
public enum Sex {
Male,
Female,
Unknown,
Other,
}
Entity is
package com.divudi.entity.lab;
import com.divudi.data.Sex;
import com.divudi.entity.Item;
import com.divudi.entity.WebUser;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.Temporal;
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class InvestigationItemValueFlag extends InvestigationItemValue implements Serializable {
private static final long serialVersionUID = 1L;
@Enumerated(EnumType.STRING)
Sex sex;
@ManyToOne
InvestigationItem investigationItemOfLabelType;
@ManyToOne
private InvestigationItem investigationItemOfValueType;
@ManyToOne
InvestigationItem investigationItemOfFlagType;
@ManyToOne
Item item;
long fromAge;
long toAge;
@Lob
private String flagMessage;
@Lob
String highMessage;
@Lob
String lowMessage;
@Lob
String normalMessage;
boolean displayFlagMessage;
boolean displayHighMessage;
boolean displayLowMessage;
boolean displayNormalMessage;
public InvestigationItem getInvestigationItemOfLabelType() {
return investigationItemOfLabelType;
}
public void setInvestigationItemOfLabelType(InvestigationItem investigationItemOfLabelType) {
this.investigationItemOfLabelType = investigationItemOfLabelType;
}
public String getHighMessage() {
return highMessage;
}
public void setHighMessage(String highMessage) {
this.highMessage = highMessage;
}
public String getLowMessage() {
return lowMessage;
}
public void setLowMessage(String lowMessage) {
this.lowMessage = lowMessage;
}
public String getNormalMessage() {
return normalMessage;
}
public void setNormalMessage(String normalMessage) {
this.normalMessage = normalMessage;
}
public boolean isDisplayFlagMessage() {
return displayFlagMessage;
}
public void setDisplayFlagMessage(boolean displayFlagMessage) {
this.displayFlagMessage = displayFlagMessage;
}
public boolean isDisplayHighMessage() {
return displayHighMessage;
}
public void setDisplayHighMessage(boolean displayHighMessage) {
this.displayHighMessage = displayHighMessage;
}
public boolean isDisplayLowMessage() {
return displayLowMessage;
}
public void setDisplayLowMessage(boolean displayLowMessage) {
this.displayLowMessage = displayLowMessage;
}
public boolean isDisplayNormalMessage() {
return displayNormalMessage;
}
public void setDisplayNormalMessage(boolean displayNormalMessage) {
this.displayNormalMessage = displayNormalMessage;
}
public Item getItem() {
return item;
}
public void setItem(Item item) {
this.item = item;
}
public InvestigationItemValueFlag() {
}
public Sex getSex() {
return sex;
}
public void setSex(Sex sex) {
this.sex = sex;
}
public long getFromAge() {
return fromAge;
}
public void setFromAge(long fromAge) {
this.fromAge = fromAge;
}
public long getToAge() {
return toAge;
}
public void setToAge(long toAge) {
this.toAge = toAge;
}
public String getFlagMessage() {
return flagMessage;
}
public void setFlagMessage(String flagMessage) {
this.flagMessage = flagMessage;
}
public InvestigationItem getInvestigationItemOfValueType() {
return investigationItemOfValueType;
}
public void setInvestigationItemOfValueType(InvestigationItem investigationItemOfValueType) {
this.investigationItemOfValueType = investigationItemOfValueType;
}
public InvestigationItem getInvestigationItemOfFlagType() {
return investigationItemOfFlagType;
}
public void setInvestigationItemOfFlagType(InvestigationItem investigationItemOfFlagType) {
this.investigationItemOfFlagType = investigationItemOfFlagType;
}
}
JSF Managed bean is as follows (Relevant code only)
public String getPatientDynamicLabel(InvestigationItem ii, Patient p) {
String dl;
String sql;
dl = ii.getName();
long ageInDays = commonFunctions.calculateAgeInDays(p.getPerson().getDob(), Calendar.getInstance().getTime());
sql = "select f from InvestigationItemValueFlag f where f.fromAge < " + ageInDays + " and f.toAge > " + ageInDays + " and f.investigationItemOfLabelType.id = " + ii.getId();
List<InvestigationItemValueFlag> fs = getIivfFacade().findBySQL(sql);
for (InvestigationItemValueFlag f : fs) {
if (f.getSex() == p.getPerson().getSex()) {
dl = f.getFlagMessage();
}
}
return dl;
}
Error is
java.lang.IllegalArgumentException: An exception occurred while creating a query in EntityManager:
Exception Description: Error compiling the query [select f from InvestigationItemValueFlag f where f.sex = com.divudi.data.Male and f.fromAge < 12419 and f.toAge > 12419 and f.investigationItemOfLabelType.id = 2678], line 1, column 57: unknown identification variable [com]. The FROM clause of the query does not declare an identification variable [com].
You shouldn't use string concatenation to pass parameters to a query. You should use parameters (named, preferrably):
String jpql =
"select f from InvestigationItemValueFlag f"
+ " where f.sex = :sex"
+ " and ...";
Query query = em.createQuery(jpql);
query.setParameter("sex", Sex.Male);
That will take care of proper escaping, correct SQL generation (the enum could be mapped as a string or as an ordinal), and avoid JPQL injection attacks.
Also please don't name something sql
or findBySQL
whan it's actually JPQL.