This entity definition results in a runtime exception:
{code:java} @Entity public class Employee {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) public int id;
@ElementCollection @Convert(converter = MyStringConverter.class) private Map<String, String> responsibilities = new HashMap<>();
void put(String key, String value) { responsibilities.put(key, value); }
String get(String key) { return responsibilities.get(key); } } {code}
The exception points to the * Convert-*annotation on the * Map*:
{noformat} Caused by: java.lang.IllegalStateException: @Convert placed on Map attribute [org.hibernate.bugs.Employee.responsibilities] must define attributeName of 'key' or 'value' at org.hibernate.cfg.CollectionPropertyHolder.applyLocalConvert(CollectionPropertyHolder.java:133) at org.hibernate.cfg.CollectionPropertyHolder.buildAttributeConversionInfoMaps(CollectionPropertyHolder.java:88) at org.hibernate.cfg.CollectionPropertyHolder.prepare(CollectionPropertyHolder.java:379) {noformat}
Indeed, the code in * CollectionPropertyHolder* explicitly enforces this, and a comment states:
{noformat} // ... JPA says // that @Convert on a Map always needs to specify attributeName of key/value (or prefixed with // key./value. for embedded paths). {noformat}
However, this does not appear to be the case: While the standard lists a few cases which require an " *attributeName"* on a * Map*, it does not require " *attributeName"* on a * Map* of basic types; without " *attributeName"*, the conversion should be applied on the values in the * Map*. See, e.g., "Example 5" on [ https://docs.jboss.org/hibernate/jpa/2.2/api/javax/persistence/Convert.html:|https://docs.jboss.org/hibernate/jpa/2.2/api/javax/persistence/Convert.html:]
{noformat} Example 5: Apply a converter to an element collection that is a map or basic values. The converter is applied to the map value.
@ElementCollection @Convert(converter=EmployeeNameConverter.class) Map<String, String> responsibilities; {noformat}
(This is identical to Example 5 in the Java TM Persistence API, Version 2.2, Chapter 11.1.10.)
One could even go a step further and say that * attributeName="value"* should be forbidden on Maps *Map*s with basic type values, since the standard specifies:
{noformat} The Convert annotation may be applied to a basic attribute or to an element collection of basic type (in which case the converter is applied to the elements of the collection). In these cases, the attributeName element must not be specified. {noformat}
(Indeed, Eclipselink will raise an exception when * attributeName="value"* is specified on a * Map* with values of a basic type.)
I have seen this behaviour when using the Entity in a minimal test (just create an Employee) both in the *hibernate-test-case-templates/orm/hibernate-orm-5* and *hibernate-test-case-templates/orm/hibernate-orm-6* |
|