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
|