[ https://issues.apache.org/jira/browse/OPENJPA-2726?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16350704#comment-16350704 ]
Will Dazey edited comment on OPENJPA-2726 at 2/2/18 5:35 PM: ------------------------------------------------------------- Patch looks good to me. Thanks Joe! was (Author: dazeydev): Patch looks good to me > Under certain conditions an Embeddable can be directly admitted into the > Datacache map > -------------------------------------------------------------------------------------- > > Key: OPENJPA-2726 > URL: https://issues.apache.org/jira/browse/OPENJPA-2726 > Project: OpenJPA > Issue Type: Bug > Components: kernel > Affects Versions: 2.2.2 > Reporter: Jody Grassel > Assignee: Jody Grassel > Priority: Major > Fix For: 2.2.3 > > Attachments: OPENJPA-2726_2.2.x.patch > > > A certain sequence of events can result in an Embeddable object instance, > with a null identity, being admitted to the DataCache. This has a number of > consequences, ranging from errors by third party datacache implementations > which cannot accept a null key value (which the native OpenJPA datacache impl > can), to possible data integrity issues since a null key can refer to any > kind of object type (since the regular key includes both > identity and identity type in its information.) > Consider the following entities: > @Entity > public class LeftHand { > @Id private long id; > private String strData; > @OneToMany private Collection<RightHand> rhList; > ... > @Entity > public class RightHand { > @Id private long id; > @Basic private String strData; > @Embedded private EmbeddableData emb; > ... > > @Embeddable > public class EmbeddableData { > @Basic private String embeddedString; > @Basic(fetch=FetchType.LAZY) private String lazyEmbeddedString; > After committing the above entities with filled data, the contents of the L2 > datacache is as follows: > this TestDataCache (id=42) > cm ConcurrentDataCache$1 (id=43) > [0] ConcurrentHashMap$Entry (id=68) > key LongId (id=73) > value DataCachePCDataImpl (id=74) > _cache "default" (id=85) > _data Object[4] (id=88) > [0] Long (id=102) > [1] AbstractPCData$ProxyDataList (id=104) > [2] "left hand" (id=110) > [3] Long (id=111) > _exp -1 > _fieldImpl null > _impl null > _loaded BitSet (id=91) > _oid LongId (id=73) > _type Class<T> > (org.apache.openjpa.persistence.cache.jpa.model.LeftHand) (id=94) > _version Integer (id=99) > [1] ConcurrentHashMap$Entry (id=69) > key LongId (id=116) > value DataCachePCDataImpl (id=117) > _cache "default" (id=85) > _data Object[3] (id=120) > [0] DataCachePCDataImpl (id=125) > _cache "default" (id=85) > _data Object[2] (id=128) > [0] "Embedded String" > (id=130) > [1] "Lazy String" (id=131) > _exp -1 > _fieldImpl null > _impl null > _loaded BitSet (id=129) > _oid BrokerImpl$StateManagerId > (id=3611) > _type Class<T> > (org.apache.openjpa.persistence.cache.jpa.model.EmbeddableData) (id=2336) > > _version null > [1] Long (id=126) > [2] "right hand" (id=127) > _exp -1 > _fieldImpl null > _impl null > _loaded BitSet (id=121) > _oid LongId (id=116) > _type Class<T> > (org.apache.openjpa.persistence.cache.jpa.model.RightHand) (id=122) > _version null > Here we see that the datacache contains two entries, one for LeftHand, one > for RightHand. Completely expected, and at this point Life is Good. > After purging the persistence context and L2 cache, a query "SELECT lh from > LeftHand lh" is executed, and iterating through its result list yields the > following L2 datacache state: > this TestDataCache (id=42) > cm ConcurrentDataCache$1 (id=43) > [0] ConcurrentHashMap$Entry (id=3657) > key LongId (id=3660) > value DataCachePCDataImpl (id=3661) > _cache "default" (id=85) > _data Object[4] (id=3662) > [0] Long (id=3665) > [1] null > [2] "left hand" (id=3666) > [3] Long (id=111) > _exp -1 > _fieldImpl null > _impl null > _loaded BitSet (id=3667) > _oid LongId (id=3660) > _type Class<T> > (org.apache.openjpa.persistence.cache.jpa.model.LeftHand) (id=94) > _version Long (id=111) > [1] ConcurrentHashMap$Entry (id=3658) > key null > value DataCachePCDataImpl (id=3670) > _cache "default" (id=85) > _data Object[2] (id=3671) > [0] "Embedded String" (id=3673) > [1] "Lazy String" (id=3674) > _exp -1 > _fieldImpl null > _impl null > _loaded BitSet (id=3675) > _oid null > _type Class<T> > (org.apache.openjpa.persistence.cache.jpa.model.EmbeddableData) (id=2336) > > _version null > [2] ConcurrentHashMap$Entry (id=3659) > key LongId (id=3682) > value DataCachePCDataImpl (id=3683) > _cache "default" (id=85) > _data Object[3] (id=3686) > [0] DataCachePCDataImpl (id=3688) > _cache "default" (id=85) > _data Object[2] (id=3691) > [0] "Embedded String" > (id=3673) > [1] "Lazy String" (id=3674) > _exp -1 > _fieldImpl null > _impl null > _loaded BitSet (id=3694) > _oid BrokerImpl$StateManagerId > (id=3695) > _type Class<T> > (org.apache.openjpa.persistence.cache.jpa.model.EmbeddableData) (id=2336) > > _version null > [1] Long (id=3689) > [2] "right hand" (id=3690) > _exp -1 > _fieldImpl null > _impl null > _loaded BitSet (id=3687) > _oid LongId (id=3682) > _type Class<T> > (org.apache.openjpa.persistence.cache.jpa.model.RightHand) (id=122) > _version null > A specific sequence of events, requiring the embeddable to contain a lazy > loaded field (which forces a ROPStoreManager.load() in the > AbstractPCData.toEmbeddedData() path results in the > DataCacheStoreManager.load() operation attempting to admit the embeddable > into the Datacache as if it was an entity type (object > ConcurrentHashMap$Entry(id=3658) at index [1].) The embeddable has no > identity of its own, so is inserted into the cache with a null key value. > The OpenJPA datacache impl replaces the null value with an object that > represents the null value -- while other datacache implementations attempt to > add the key to a regular map instance which results in a NullPointerException. > The attached patch looks for the attempt to insert a new (embeddable) item > into the datacache at updateDataCache() - admission into the datacache is > rejected if this condition is met. I've further modified cacheStateManager() > to reject any attempt to admit an entry into the datacache that has a null > entity to guard against other unidentified paths which could lead to a > similar issue, as a null key identity in a datacache is meaningless. A unit > test has been added to verify that the fix corrects the issue. -- This message was sent by Atlassian JIRA (v7.6.3#76005)