We are migrating from Eclipselink to Hibernate (5.6.14) and, with Hibernate, a previously green unit test in some legacy code runs into the following exception:
[ERROR] someTestWasRun(com.abc.AbcTest) Time elapsed: 0 s <<< ERROR!
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:124)
[... long stack ...]
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
... 27 more
Caused by: java.lang.IllegalStateException: @Convert placed on Map attribute [Abc.colors] 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)
The attribute in question is a Map<String, String>
:
@ElementCollection
@CollectionTable(name = "some_map")
@MapKeyColumn(name = "name")
@Column(name = "value")
@Convert(converter = SomeStringConverter.class)
private Map<String, String> colors;
The Hibernate source for the stack from the error explicitly states:
JPA says that @Convert on a Map always needs to specify attributeName of key/value (or prefixed with key./value. for embedded paths).
However, while the API for Convert lists a few conditions under which attributeName
has to be specified, a map of basic types is not among them, and the page contains an example 5 with a Map<String, String>
and no attributeName
.
Correspondingly, when we add attributeName="value"
to the @Convert
annotation, Eclipselink gives the error:
The mapping attribute [colors] from the class [Abc] is not a valid mapping type for a convert using an attribute name specification. An attribute name should only be specified to traverse an Embedded mapping type.
So the two seem to be contradicting each other directly. Is this a bug in one of them, or has the standard changed at some point, or is there something else I am missing?
EclipseLink behavior here is correct, as the JPA specification (starting in 2.1) section 11.1.10 states :
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.
Which makes this against the specification to require the attributeName on this mapping.
See HHH-15733 for details of the bug within Hibernate.