You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@openjpa.apache.org by "Will Dazey (JIRA)" <ji...@apache.org> on 2018/02/02 17:36:00 UTC
[jira] [Comment Edited] (OPENJPA-2726) Under certain conditions an
Embeddable can be directly admitted into the Datacache map
[ 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)