rzo1 opened a new pull request, #226: URL: https://github.com/apache/openjpa/pull/226
https://issues.apache.org/jira/browse/OPENJPA-3023 With `openjpa.DataCache=true`, an attribute with an `AttributeConverter` was cached as its Java value, and every persistence context that loaded the instance from the cache got the same objects. A change made in place in one context showed up in the others, even after a rollback. For example, em1 finds the entity, calls `getItems().get(0).setName("changed")` and rolls back; em2 then finds the entity and sees "changed". This was seen in Apache Syncope with a converted `List<PlainAttr>`. ## Cause `AbstractPCData.toData()` copied a collection but kept its element objects, and kept a single value as is unless OpenJPA could proxy it. When the instance was loaded from the cache, `toField()`/`toNestedFields()` handed those cached objects to the entity. The collection itself was copied into a new proxy, but its elements were not. A single value that OpenJPA cannot proxy, such as a final class or a class without a no-arg constructor, was shared the same way. ## Fix - An attribute converted as a whole (`FieldMetaData.isValueConverted()`) is cached in its database form (`getExternalValue`). The converter runs again when the instance is loaded from the cache (`getFieldValue`), so each persistence context gets its own value. Null goes through the converter, as it does on a database load. - A collection whose elements are converted one by one (the mapping uses `ConverterElementHandler`) caches each element in its database form and converts each one again on load. The new `FieldMetaData` methods `isElementConverted()`, `getExternalElementValue()` and `getElementFieldValue()` do this, and the converter call is now shared in one place. - Arrays and dates returned by a converter are copied on the way into and out of the cache. - If the converter throws while the cache is filled, that attribute is left out of the cache and loaded from the database. If it throws on a cache hit, the load fails with the same exception a database load gives. - The migration notes describe the change: converters now also run on cache store and on cache hits. `DataCacheStoreManager` is not changed. Fields with an `@Externalizer` and plain serialized values are cached as before. ## Tests The new `TestConvertedDataCache` covers: - a list converted as a whole and a list converted per element, where an element is changed in place and the transaction rolled back; - a single value that OpenJPA cannot proxy; - `byte[]` and `java.util.Date` values that a converter hands on without copying; - separate objects in each persistence context; - a committed change and a null value loaded from the cache; - a converter that throws when the cache is filled, and one that throws on a cache hit. 8 of the 10 tests fail without the fix. The full openjpa-persistence-jdbc suite and the openjpa-kernel tests pass on Derby and H2. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
