1

I use Hibernate and want to query for entities by their natural identifier. However, it seems not to be possible to have natural ids on subtypes. I have two classes A and B where B extends A:

class A {
  long id;
}

class B extends A {
  String naturalId;
}

A is mapped in Hibernate with its own identifier. B is mapped as joined subclass. However, it is not possible to map the natural identifier of B in Hibernate because the mapping of B is a subclass mapping.

  • Why is it not possible to have a natural identifier on the subclass B? Note that I don't want Hibernate to generate my database schema, I just want to have natural ids for fast cache hits.

  • Is there a way/a best practice to have natural ids on subtypes for fast second level cache querying?

    • Is this still possible when natural ids might get updated (change) in rare circumstances and the cache has to be maintained in a clustered Java EE environment?
Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
Felix Feisst
  • 175
  • 10

2 Answers2

1
  1. NaturalId only make sense for base classes, because you can't retrieve a sub-class without the base class info.

    Let's say you could map map both the base class and the sub-class with a natural-id:

    class A {
      long id;
      String baseId;
    }
    
    class B extends A {
      String naturalId;
    }
    
    A a = session.bySimpleNaturalId( A.class ).load( "abc" );
    

    If the entity we retrieve if of type B, it's not clear which of the natural-id variants will be used.

  2. You can't fetch a sub-class without getting the base-class info. So when you load a Sub-class from cache, the associated base-class info is retrieved as well. Therefore you could have the base class store the natural-id, or simply use the primary key for caching.

  3. You can update the natural-id, although a business key should be immutable. For mutable natural-ids you need to use the mutable attribute.

Vlad Mihalcea
  • 142,745
  • 71
  • 566
  • 911
  • Thank you for your answer. However, I don't see why Hibernate shouldn't know which natural-id to use, because we're explicitly giving the type of the entity to query. Also defining a natural-id with same signature as the natural-id of a parent class could easily be forbidden. – Felix Feisst Mar 12 '15 at 07:48
  • I think this decision was taken for simplicity sake. From an implementation point of view, it's doable to implement some work-around to override the base class natural-id from a sub-class. You can file a Hibernate issue for this situation on Hibernate JIRA. – Vlad Mihalcea Mar 12 '15 at 07:54
0

According to 13.3. Entity inheritance and second-level cache mapping:

As of Hibernate ORM 5.3, you can now override a base class @Cacheable or @Cache definition at subclass level.

so you might have a chance by resetting the caching annotations on B.
I never tried it so please confirm the solution with a comment.

Adrian
  • 3,321
  • 2
  • 29
  • 46