Repository navigation
[OPENJPA-3017] Map a collection whose converter takes the collection itself - #220
Conversation
…itself A converter declared AttributeConverter<List<X>, Y> converts the attribute as a whole, so the field is basic and maps to one column. It was instead treated as having no persistence strategy, left out of the mapping, and its contents were lost without an error.
… attribute A <column> inside <basic> on a collection or map was assigned to the element mapping unless the value was serialized. A collection converted as a whole then failed to map with "this mapping cannot have columns in this context". A basic attribute is one value with one column, so its column now belongs to the attribute. The converter cannot decide this here, since an @convert annotation is not parsed yet.
|
@ilgrosso thanks for testing. The converter is fine and matches yours. The difference is in <basic name="plainAttrs">
<column column-definition="jsonb"/>
</basic>The first fix only handled annotations. When OpenJPA read a There is one more change needed on your side. The fields are declared Could you remove |
|
Thank you @rzo1 : once pulled, rebuilt and removed At present I am getting so it looks like something attempts to set |
|
@ilgrosso thanks, good to see it gets further now. The I opened OPENJPA-3018 to fix it in the dictionaries. Until then you can work around it with: |
|
Great progress, thank you @rzo1! We moved from to I will have a look at the failures and report. |
|
It looks like one reason of a few test failures is that the following test code: User rossini = userDAO.findByUsername("rossini").orElseThrow();
PlainAttr loginDate = rossini.getPlainAttr("loginDate").orElseThrow();
loginDate.getValues().getFirst().setDateValue(FormatUtils.parseDate(LOGIN_DATE_VALUE, "yyyy-MM-dd"));
entityManager.merge(rossini);does not generate any User rossini = userDAO.findByUsername("rossini").orElseThrow();
PlainAttr loginDate = rossini.getPlainAttr("loginDate").orElseThrow();
rossini.remove(loginDate);
loginDate.getValues().getFirst().setDateValue(FormatUtils.parseDate(LOGIN_DATE_VALUE, "yyyy-MM-dd"));
rossini.add(loginDate);
entityManager.merge(rossini);does. In the first snippet, the converted In the second snippet, the converted |
|
@ilgrosso thanks, that is a bug: the spec requires a change made in place to a mutable value to be written. Tracked in OPENJPA-3019. |
|
@ilgrosso regarding the Until it is merged, you can drop |
…ault A converted attribute is basic, and a basic attribute is eager unless it is declared lazy. A collection or map converted as a whole fell back to the lazy default of collections, so it was not loaded before detach.
Reported on the dev list by @ilgrosso, testing Syncope master against 4.2.0-SNAPSHOT:
@Converton aListattribute whose converter is declaredAttributeConverter<List<X>, Y>. Such a converter converts the attribute as a whole, so the attribute is basic and belongs in one column. OpenJPA instead found no persistence strategy for it, left it out of the mapping, and lost its contents without raising anything — only one warning among several hundred of the same kind in a full run.The element handler for collections was already there; the attribute never reached it. Three places decide this, and all three only ever asked the type code:
PersistenceMetaDataDefaults.getPersistenceStrategy()now treats a converter of the attribute's own type as a strategy, i.e.BASIC, as the last resort before giving up on the field.parseBasic()no longer serializes or rejects a collection in that case, since the converter maps the value.MappingRepository.defaultTypeStrategy()andFieldMetaData.isValueConverted()admit a collection or map whose converter takes the whole value, which gives itConverterValueHandlerand a single column.The discriminator is the converter's own declaration, read from
AttributeConverter<X,Y>:Xassignable from the attribute type means the value is converted as a whole,Xbeing the element type leaves the existing element-wise path untouched.FieldMetaData.resolveConverterTypeArgument()is the generalisation of the resolver that already readY.Out of scope: element-wise conversion of a collection of a non-basic type, which the specification defines for
@Converton an@ElementCollectionand which OpenJPA does not support yet — its enhancer demands metadata for the element type. Worth its own issue.Both tests fail without the production change, verified by reverting it:
the converted attribute must be mapped, andexpected:<2> but was:<0>for the round trip. Conversion, enhance, meta, simple and embed packages run 621/29/39 on Derby and on H2, against 619/29/39 on master at the same base with an identical list of failing classes, so the two new tests are the only difference. The unit tests of the three changed modules are green: kernel 145, jdbc 75, persistence 34.