|
After upgrade Hibernate ORM from 5.0.2 to 5.0.3 I can't make to work JPQL query which uses Enum value with AttributeConverter as part of WHERE clause.
Given this classes:
package point.data.jpa.entities;
public class DeskTransaction {
public enum Type {
TYPE1(1), TYPE2(2);
private int code;
private static Map<Integer, Type> typesByCode = new HashMap<>();
static {
for (Type type : Type.values()) {
typesByCode.put(type.code, type);
}
}
public Type(int code) {
this.code = code;
}
public int code getCode() {
return this.code;
}
public static Type fromCode(int code) {
return typesByCode.get(code);
}
}
@Converter(autoApply = true)
public static class TypeConverter implements AttributeConverter<Type, Integer> {
@Override
public Integer convertToDatabaseColumn(Type attribute) {
return attribute == null ? null : attribute.getCode();
}
@Override
public Type convertToEntityAttribute(Integer dbData) {
return dbData == null ? null : Type.fromCode(dbData);
}
}
@Column(nullable = false)
private Type type;
@ManyToOne(optional = true)
@JoinColumn(name = "worker_id")
private Employee employee;
@Column(name = "money", nullable = false)
private BigDecimal sum;
}
Before 5.0.3 (up to 5.0.2 inclusive) this JPQL query works (in 4.x it also worked fine): SELECT dt.employee, -SUM(dt.sum) FROM point.data.jpa.entities.DeskTransaction dt WHERE dt.type = 1 GROUP BY dt.employee
After upgrading to 5.0.3 it don't work anymore and raises exception at application launch:
I think that before 5.0.3 AttributeConverters were not applied for this JPQL WHERE clause so literal "1" worked because in DB this is INTEGER field. So I tried to replace literal "1" to Enum in this query.
I tried this: SELECT dt.employee, -SUM(dt.sum) FROM point.data.jpa.entities.DeskTransaction dt WHERE dt.type = TYPE1 GROUP BY dt.employee In this case application starts fine but when this query executes it raises the exception:
(take no note of additional fields as my real DeskTransaction and Employee classes are little bigger)
The real problem here is desktransa0_.type=EMPLOYEE_RESPONSIBILITY. Of course this is not correct SQL.
Then I tried to wrote full qualified class name for enum: SELECT dt.employee, -SUM(dt.sum) FROM point.data.jpa.entities.DeskTransaction dt WHERE dt.type = point.data.jpa.entities.DeskTransaction.Type.TYPE1 GROUP BY dt.employee
This causes exception:
Then I changed nested class divider from dot to "$" sign: SELECT dt.employee, -SUM(dt.sum) FROM point.data.jpa.entities.DeskTransaction dt WHERE dt.type = point.data.jpa.entities.DeskTransaction$Type.TYPE1 GROUP BY dt.employee
And finally it works fine!
I find this last solution while wroting this report and now not sure if it is bug at all. Maybe wroting nested classes in class-loader format with "$" as divider is right solution?
But even if this is true then when this has been changed? I check all changes between 5.0.2 and 5.0.3 and found only
HHH-9074
. But it is for boolean and not enums.
Maybe it should be documented somewhere as many JPQL queries became broken after upgrading to 5.0.3. I think it is bug that type = 1 worked before (skipping AttributeConverters) but it worked quite a while...
And maybe it is possible to make type = TYPE1 (without FQCN) also works? If class of type is known at runtime then we can deduce enum class for TYPE1.
|