We're updating the issue view to help you get more done. 

AttributeConverter for Enum within JPQL query

Description

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:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 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; // getters and setters }

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:

1 Caused by: org.hibernate.QueryException: AttributeConverter domain-model attribute type [point.data.jpa.entities.DeskTransaction$Type] did not match query literal type [java.lang.Integer]

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:

1 2 Column "TYPE1" not found; SQL statement: select desktransa0_.worker_id as col_0_0_, -sum(desktransa0_.money) as col_1_0_, employee1_.id as id1_30_, employee1_.enable_adminka as enable_a2_30_, employee1_.enable_switch as enable_s3_30_, employee1_.enable_vpn as enable_v4_30_, employee1_.active as active5_30_, employee1_.birthday as birthday6_30_, employee1_.firstname as firstnam7_30_, employee1_.lastname as lastname8_30_, employee1_.login as login9_30_, employee1_.password as passwor10_30_, employee1_.patronymic as patrony11_30_, employee1_.position as positio12_30_, employee1_.com_config_notifications as com_con13_30_, employee1_.ip_address as ip_addr14_30_ from buhuchet desktransa0_ inner join workers employee1_ on desktransa0_.worker_id=employee1_.id where desktransa0_.type=TYPE1 and (desktransa0_.worker_id is not null) group by desktransa0_.worker_id [42122-190]

(take no note of additional fields as my real DeskTransaction and Employee classes are little bigger)

The real problem here is desktransa0_.type=TYPE1. 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:

1 Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: Invalid path: 'point.data.jpa.entities.DeskTransaction.Type.TYPE1' [SELECT dt.employee, -SUM(dt.sum) FROM point.data.jpa.entities.DeskTransaction dt WHERE dt.type = point.data.jpa.entities.DeskTransaction.Type.TYPE1 AND dt.employee IS NOT NULL GROUP BY dt.employee]

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.

Environment

Ubuntu 12.04 x64 / Spring 4.2 / Hibernate 5.0.3

Status

Assignee

Steve Ebersole

Reporter

Руслан Стельмаченко

Fix versions

Affects versions

5.0.3

Priority

Major