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]

Reply via email to