[hibernate-issues] [Hibernate-JIRA] Commented: (HHH-7258) NaturalIdCacheKey equals method doesn't work for primitive array types

Steve Ash (JIRA) noreply at atlassian.com
Wed Apr 18 15:48:48 EDT 2012


    [ https://hibernate.onjira.com/browse/HHH-7258?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=46347#comment-46347 ] 

Steve Ash commented on HHH-7258:
--------------------------------

Just in case anyone else stumbles upon this -- the most obvious and best solution is just to use the UUID class for a PK id type.  With a @Column(length=16) this maps to a binary[16] in the database and hibernate's native UUIDBinaryType works just fine.  Then we avoid all this primitive array nonsense entire.  

I just modified our custom generator to return UUID instances constructed with two longs.  Much better.

> NaturalIdCacheKey equals method doesn't work for primitive array types
> ----------------------------------------------------------------------
>
>                 Key: HHH-7258
>                 URL: https://hibernate.onjira.com/browse/HHH-7258
>             Project: Hibernate ORM
>          Issue Type: Bug
>          Components: core
>    Affects Versions: 4.1.2
>         Environment: Hibernate 4.1.2
> SQL 2008
>            Reporter: Steve Ash
>
> I have entities like (shorthand):
> {code}
> @Entity
> @Cache
> public class Parent {
>   @Id
>   private byte[] id;
> }
> @Entity
> @Cache
> @NaturalIdCache
> public class Child {
>   @Id
>   private byte[] id;
>   @ManyToOne
>   @NaturalId
>   private Parent parent;
>   @NaturalId
>   private String name;
> }
> {code}
> So the naturalId is a compound key made up of a FK reference to the parent + the name of the child (i.e. for a single parent, all of the childrens names are unique).
> I always get a cache miss in the 2nd level cache when I try to load this by natural key using something like:
> {code}
> Parent p = ... // attached parent instance
> return sf.getCurrentSession()
>   .byNaturalId(Child.class)
>   .using("parent", p)
>   .using("name", childName)
>   .load();
> {code}
> I stepped through the code and found that eventually an instance of {{NaturalIdCacheKey}} is built with a field {{naturalIdValues}}.  In the Child instance above this naturalIdValues would be an array of size 2.  The [0] element is a byte[] reference, and the [1] element is the child name string.
> While I can see in the debugger that my Child instance is present in the natural Id cache, the equals method on NaturalIdCacheKey just uses Array.equals on naturalIdValues.  Thus, it does a reference equals on my primitive byte[] for the parent's PK value.  While the values in the byte array are the same, they are different instances of course, and thus the reference equals returns false, and I never retrieve this from the natural id cache.
> Thinking I would be clever, I replaced this with an @Embeddable component that wrapped the byte[] and implemented my own equals, but Hibernate core _disassembles_ the component to build the naturalIdCacheKey which defeats my component and so we end up with the same problem.
> I have run in to a similar problem in HHH-7180 so clearly theres not too many of us that are using binary storage for GUIDs.  Is everyone else just storing as 32byte strings?  Or 22 byte case-sensitive coalation strings?  Or an @embedded with two longs?
> I'll build a test case that replicates this at some point soon.

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira

        


More information about the hibernate-issues mailing list