[hibernate-dev] Cache key containing composite ID with a many-to-one

Steve Ebersole steve at hibernate.org
Thu Dec 5 12:33:26 EST 2019


>
> > JPA does not allow mixing of @IdClass and @EmbeddedId.  But I think
> that's a valid option.  In fact in our original work on 6 where we
> completely replaced the mapping model (persisters) i had added support for
> this.  We could add an improvement to pull this feature to 6 proper?
>
> There would be some rough edges (what would
> org.hibernate.Session#getIdentifier return, the embedded id or the idclass?
> What would Session.load accept? What would be the declared type of the ID
> in JPA Criteria?). But that could be a valuable feature for people who
> really want composite IDs. And it could solve the caching problem.
> However, if we need to solve the caching problem in ORM 5 and are not in a
> position to declare that caching isn't supported for such identifiers...
> then we'll have to work on some hack in ORM 5. So maybe it's not a priority
> in ORM 6.
>

`Session#getIdentifier` would return the embedded-id, imo.  The embedded-id
is the "real" id.  The id-class is just a simplified "syntactic sugar" used
only for an alternative form of loading.  In fact for an entity with an
id-class you can load using either approach, though the legacy form of
loading an entity with a non-aggregated composite id is truly painful.

Just spit-balling, one option would be to expose a even more simplified
loading for these entities using `Session#byId` (or a new similar method)
allowing specifying the simplified, basic "maps-id" values for the load.
Just for illustration, something like:

session.byCompositeId( EntityWithCompositeId.class )
    .using( "idAttribute1", "idAttribute1-value" )
    .using( "keyManyToOne", "keyManyToOne-basic-id-value" )
    ...
    .load();

That's geared toward non-aggregated composite id cases, though really it
could be available in aggregated composite id cases as well.

We could also allow a form in normal load-by-id using a Map maybe?  I only
mention this as even though its still a "new feature", it does not require
any API changes or new APIs.

final Map idValues = new HashMap();
idValues.put( "idAttribute1", "idAttribute1-value" );
idValues.put( "keyManyToOne", "keyManyToOne-basic-id-value" );
...
session.get( EntityWithCompositeId.class, idValues );

Or even an "array Map" option to avoid the Map instantiation:

final Object[] idValues = new Object[] {
    "idAttribute1", "idAttribute1-value",
    "keyManyToOne", "keyManyToOne-basic-id-value",
    ...
};
assert idValues.length %2 == 0;
session.get( EntityWithCompositeId.class, idValues );

Of course, if the embedded-id could also have an id-class you'd use that.

I'd like to see all of these as options btw, not one-or-the-other.  Though
I'm fine if no-one else likes the `Session#byCompositeId` idea.  It was
just a spur-of-the-moment idea.


More information about the hibernate-dev mailing list