Hello Mauro,
Frameworks don't automatically treat the join as a left out join
because traversing a path in JPA's criteria queries or JPQL is
supposed to be treated as an inner join. Section 4.4.4 of the JPA
2.1 specification requires that
"Path _expression_ navigability is composed using “inner join”
semantics. That is, if the value of a non-terminal field in the path
_expression_ is null, the path is considered to have no value, and
does not participate in the determination of the result."
The fact that this works when the relationship is reversed is a
result of EclipseLink optimizations that take advantage of the fact
a join isn't required and not something intentionally done for null
handling. I believe I saw this behavior difference documented when
the feature was done, I just don't have a link handy.
If you want consistent, spec compliant behavior in your queries, you
are required to specify the relationship use a left join in the
query. Ie:
"Select first from First first left join first.second second where
second is null"
or its equivalent in criteria expressions.
Best Regards,
Chris
One of the problems with considering this issue is that This is why
On 08/01/2016 10:48 AM, Mauro Molinari
wrote:
Hello all,
I'm trying to implement some sort of "findByExample" feature in my
JPA application (using EclipseLink 2.6.1).
To do this, I'm inspecting the metamodel of my classes and
dynamically creating predicates to be added to a query built with
the Criteria API.
I encountered bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=485414
which is causing me a lot of headache.
To work around it, I'm trying to implement the following logic:
"if the attribute is mapping a bidirectional relationship which is
not owned by this entity, then do an outer join and apply a
condition on the corresponding relationship attribute of the
target entity".
The simple case would be:
Predicate predicate = cb.equal(from.get(attribute),
exampleValue);
which substantially is: "WHERE MyEntity.attribute =
<exampleValue>"
But if exampleValue is NULL and attribute is a
@OneToOne(mappedBy="inverseAttributeName"), so it's mapped to a
non-owned relationship, I have to do a different thing to work
around the aforementioned bug.
So, I have:
- attribute, which is a SingularAttribute
- attributeType, which is the attribute type (
attribute.getType() )
- if
attributeType.getPersistenceType() ==
PersistenceType.ENTITY (=> a relation attribute)
then I get:
DatabaseMapping mapping = ((SingularAttributeImpl)
attribute).getMapping();
The DatabaseMapping object is promising, because it has the method
getRelationshipPartnerAttributeName() (or even
getRelationshipPartner()) which, if I understand it correctly,
should give me the attribute name of the related entity, if this
is a bidirectional mapping.
However what I see while debugging is that both methods always
return null (also the protected field "mapping.mappedBy" is
null!!), even if attribute is a SingularAttributeImpl of an
attribute which is mapped like this:
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY,
mappedBy = "inverseAttributeName", optional = true,
orphanRemoval = true)
and the inverse mapping is present (so the relationship actually
*is* bidirectional):
@Id @OneToOne(fetch = FetchType.EAGER, optional = false)
Something similar seems to be the fields
mapping.targetToSourceKeyFields and
mapping.sourceToTargetKeyFields, but those are maps containing
DatabaseFields, not attributes, so I doubt I can use them to build
my query (unless, of course, I am lucky and the attribute name
matches the database column name).
On the other hand, I can't find anything else useful in
SingularAttributeImpl (not to say the plain JPA interface...) to
get the desired result.
I'm almost at it, but I already spent a lot of time on this final
detail without success :-(
Any help would be *really* appreciated.
Thanks in advance,
Mauro
_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/eclipselink-users
|