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

Steve Ash (JIRA) noreply at atlassian.com
Wed Apr 18 03:25:49 EDT 2012


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