# @NaturalId on table per class entity hierarchy issue

**URL:** <https://discourse.hibernate.org/t/naturalid-on-table-per-class-entity-hierarchy-issue/5605>\
**Category:** Hibernate ORM\
**Created:** [August 13, 2021, 9:43am UTC](https://discourse.hibernate.org/t/naturalid-on-table-per-class-entity-hierarchy-issue/5605 "2021-08-13T09:43:25Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![tomindk](https://avatars.discourse-cdn.com/v4/letter/t/d6d6ee/32.png) [@tomindk](https://discourse.hibernate.org/u/tomindk)\
**Post date:** [August 13, 2021, 9:43am UTC](https://discourse.hibernate.org/t/naturalid-on-table-per-class-entity-hierarchy-issue/5605/1 "2021-08-13T09:43:25Z")

</div>

With the following TABLE\_PER\_CLASS hierarchy

```auto
@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public abstract class LegalParty {
    @NaturalId(mutable=true)
    @Column(unique=true, nullable=false)
    private String id;
}

public class Person extends LegalParty {
}

public class Company extends LegalParty {
}

```

The NaturalId implementation seems to effectively require that my _id_ column is unique across all implementing classes.

The following code:

```auto
  Person person = new Person();
  person.setId("THE_SAME_AS_THE_OTHER");
  session.save(person);
  
  Company company = new Company();
  company.setId("THE_SAME_AS_THE_OTHER");
  session.save(company);
  
  SimpleNaturalIdLoadAccess<Company> companyLoadAccess = session.bySimpleNaturalId(Company.class);
  Company foundCompany = companyLoadAccess.loadOptional("THE_SAME_AS_THE_OTHER").orElseThrow(() -> new IllegalArgumentException());
  
  SimpleNaturalIdLoadAccess<Person> personLoadAccess = session.bySimpleNaturalId(Person.class);
  Person foundPerson = personLoadAccess.loadOptional("THE_SAME_AS_THE_OTHER").orElseThrow(() -> new IllegalArgumentException());  

```

The last line throws an IllegalArgumentException as nothing is returned from the _loadOptional_ method call.

Diving into the code, I see that in _StatefulPersistenceContext::locateProperPersister()_ returns:  
` session.getFactory().getMetamodel().entityPersister( persister.getRootEntityName() )`

which returns the UnionSubclassEntityPersister for _LegalParty_, which results in that the hashCode generated for the naturalId as the key value in the _naturalIdToPkMap_ is the same, so there is only one row in this Map.

However, there are two rows in the pkToNaturalIdMap as the EntityKey used by the primary key is generated using the EntityPersister for the subclass (Person or Company).  
But both of these rows have the same value for the NaturalId part.

This results in a lookup that returns the primary key for a different object type, so the primary key lookup fails to find anything, even thought both objects exists in the PersistenceContext.

Shouldn’t the UnionSubclassEntityPersister for the proper subclass be used to generate the naturalId hashcode?

---

<div class="post-metadata">

**Author:** ![beikov](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/beikov/32/258_2.png) [@beikov](https://discourse.hibernate.org/u/beikov)\
**Post date:** [August 16, 2021, 10:59am UTC](https://discourse.hibernate.org/t/naturalid-on-table-per-class-entity-hierarchy-issue/5605/2 "2021-08-16T10:59:20Z")

</div>

Keys must be unique across the hierarchy, otherwise some kind of discriminator should be part of the key. Not sure why you need a table per class inheritance here if you the key is not unique across the tables. If you just want reuse, use a `@MappedSuperclass` and query every entity type individually by natural id. Thinking about it, what would you like Hibernate to return if you query LegalParty by e.g. PK or NaturalID 1 when there are multiple objects? See the problem? That’s just not how this works. If this is the database design you have to use, you have to decide which object to try to fetch first etc.

---

<div class="post-metadata">

**Author:** ![tomindk](https://avatars.discourse-cdn.com/v4/letter/t/d6d6ee/32.png) [@tomindk](https://discourse.hibernate.org/u/tomindk)\
**Post date:** [August 16, 2021, 12:09pm UTC](https://discourse.hibernate.org/t/naturalid-on-table-per-class-entity-hierarchy-issue/5605/3 "2021-08-16T12:09:01Z")

</div>

Thank you for taking the time to answer.

Why _must_ keys be unique across the hierarchy, when the same is not a requirement for a regular @id key? I understand the issue when querying by LegalParty, but the same can be said for the same hierarchy and querying by @Id on the root entity class - is that not correct? (assuming that your primary key is generated by two different sequences, allowing for the same primary key in two different implementing classes)

I find it strange and inconsistent that the two behaviors are not the same, and that I am able to model it in this way, and then have a silent error that my persisted object does not exist, when it clearly does. I would find it more correct that I got an exception that told me what the exact problem was, which I imagine I would get if I queried by LegalParty. Or even better that this requirement was enforced when persisting the second object, but I understand the problems implementing this.

I believe that the reason that they were originally modelled with a table\_per\_class and not single\_table, is that we could not be sure, that for all our customers that there would not be a case of an id being the same across two tables. All legal parties have _natural_ id’s, but they are only guaranteed unique within a legal party type, this makes it impossible to use single\_table inheritance.

Anyway, I am probably stuck with this design, but I can’t see how a @MappedSuperclass makes a difference.

One last thing, I was unable to find this behavior documented, is this just me looking in the wrong places?

---

<div class="post-metadata">

**Author:** ![beikov](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/beikov/32/258_2.png) [@beikov](https://discourse.hibernate.org/u/beikov)\
**Post date:** [August 16, 2021, 12:54pm UTC](https://discourse.hibernate.org/t/naturalid-on-table-per-class-entity-hierarchy-issue/5605/4 "2021-08-16T12:54:47Z")

</div>

How come you think this does not also apply for primary keys? It has the same “limitations” for the same reasons. The primary key must be unique across the hierarchy, that’s just how this is. If you see that it works, please post an example. I have the feeling that if that works, this would be a bug as that might lead to some internal inconsistencies.

The `@MappedSuperclass` approach will only help you in the sense that you can keep the Java class hierarchy and reuse the common fields. Every subclass which will be a separate entity then can have its own id then.

I can only refer you to the JPA specification regarding documentation, but I didn’t search for this yet to find a reference for you.

---

<div class="post-metadata">

**Author:** ![tomindk](https://avatars.discourse-cdn.com/v4/letter/t/d6d6ee/32.png) [@tomindk](https://discourse.hibernate.org/u/tomindk)\
**Post date:** [August 17, 2021, 2:16pm UTC](https://discourse.hibernate.org/t/naturalid-on-table-per-class-entity-hierarchy-issue/5605/5 "2021-08-17T14:16:47Z")

</div>

I made an incorrect assumption, when seeing how the EntityKey was generated for an object, which seems to use the EntityPersister of the subclass. I, therefore, assumed that both objects could exist in the persistence context at the same time as they would have different keys. I had missed that the _generateHashCode()_ method in EntityKey calls _persister.getRootEntityName()_ to generate the hash code

I guess I am just surprised that it is possible to persist the entities as described without any errors, and that querying by subclass returns one of the objects, but not the other, and does so without throwing an exception, while querying by the root class will throw an exception.

Would it not be possible in _AbstractEntityPersister_’s method _loadEntityIdByNaturalId_ after the line:  
`final Object hydratedId = getIdentifierType().hydrate( rs, getIdentifierAliases(), session, null );`  
to throw an exception if _rs.next()_ returns true?  
Combined with a check that a NaturalIdResolutionCache’s two maps _pkToNaturalIdMap_ and _naturalIdToPkMap_ have the same size after being written to?

Otherwise, one is susceptible to silent errors, without checking that an object in another subclass table does not exist with that same Id.

---

<div class="post-metadata">

**Author:** ![beikov](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/beikov/32/258_2.png) [@beikov](https://discourse.hibernate.org/u/beikov)\
**Post date:** [August 17, 2021, 4:13pm UTC](https://discourse.hibernate.org/t/naturalid-on-table-per-class-entity-hierarchy-issue/5605/6 "2021-08-17T16:13:35Z")

</div>

> I guess I am just surprised that it is possible to persist the entities as described without any errors, and that querying by subclass returns one of the objects, but not the other, and does so without throwing an exception, while querying by the root class will throw an exception.

Surprised or not, Hibernate can’t check everything for you and if you have bad data, then bad things will happen 🙂

Having said that, if you think you know how to improve this, you are free to create a JIRA issue and provide a PR for this along with a test that shows the scenario.
