[hibernate-dev] Extended KEY expression support

Christian Beikov christian.beikov at gmail.com
Fri Jan 27 14:25:12 EST 2017


I have a little proposal for supporting the use of a KEY expression in 
the FROM clause and I'd like to hear your opinions on that.
Unfortunately the JPA spec does not support that, but since a key of a 
java.util.Map mapping may be an entity type, we need to specify how one 
can "join" that key explicitly.

Right now(pre HHH-10537), when joining a java.util.Map mapping, an inner 
join is generated for the map key entity type. In my fix for HHH-10537 I 
changed the behavior to respect/inherit the join type of the collection 
join.
The problem is, that one can't further join any attributes on that key, 
because there is no syntax in the HQL or the JPA spec that allows to do 
that.

We need to decide (1) whether we always want to join the entity key or 
require the user to do that specifically via e.g. something like "JOIN 
alias.map m JOIN KEY(m) k"
and also (2) how the syntax for joining further attributes should look 
like. If we decide to not allow the "JOIN KEY(m)" syntax for (1) we have 
to support something like "JOIN KEY(m).association", otherwise we can 
just use the alias like for normal joins "JOIN k.association".
Either way, we have to change the grammar but I'd rather like to 
support/implement the map key joining syntax like "JOIN KEY(m) k" for 
(1). A further change to that would be to not generate the implicit key 
table join anymore but require the user to do the join explicitly. Since 
that would break backwards compatibility, I'd like to make that behavior 
configurable and of course, by default it will generate the implicit key 
join to maintain backwards compatibility. I also propose to switch the 
default in 6.0 so that the join is not generate anymore.
The usage in the JPA Criteria API will unfortunately require a cast 
since the return type of javax.persistence.metamodel.MapAttribute#key() 
is javax.persistence.metamodel.Path instead of 
javax.persistence.metamodel.SingularAttribute but essentially the same 
functionality is available to a user out of the box.
Specifying a custom join for a key would look like this in the Criteria API

MapAttribute<Entity, MapKeyEntity, MapValueEntity> mapAttribute = ...
Join<Entity, MapKeyEntity> keyEntity = 
mapAttribute.join((SingularAttribute<? super Entity, ? extends 
MapKeyEntity>) mapAttribute.key(), JoinType.LEFT);
keyEntity.join(...)

So the questions again.
  1. Do you all agree that this is important and should be done?
  2. Agree to not generate implicit joins for keys in future versions?
  3. Allow joining the key in a separate join?
  4. Allow further joins on a key?
  5. Happy with how it can be done in JPA Criteria?

In addition to that, it would be nice if anyone could make someone from 
the JPA EG aware of this.
 From a JPQL BNF point of view, I'd propose the following changes

from

join_single_valued_path_expression::=
identification_variable.{single_valued_embeddable_object_field.}*single_valued_object_field

to

join_single_valued_path_expression::=
identification_variable.{single_valued_embeddable_object_field.}*single_valued_object_field 
|
     map_field_identification_variable

Regards,
Christian


More information about the hibernate-dev mailing list