Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check if we can do something about polymorphic query problems #123

Closed
beikov opened this issue Apr 26, 2015 · 6 comments
Closed

Check if we can do something about polymorphic query problems #123

beikov opened this issue Apr 26, 2015 · 6 comments

Comments

@beikov
Copy link
Member

beikov commented Apr 26, 2015

There are some problems that we encountered when doing polymorphic property access in queries where the target property is only available in one of the possible types. This seems to only happen in hibernate when the base class is abstract.

http://stackoverflow.com/questions/18392252/access-subclass-properties-in-criteria-builder-jpa
http://stackoverflow.com/questions/6903783/jpa-criteria-api-query-property-of-subclass
http://stackoverflow.com/questions/23595594/exception-in-query-downcasting-to-subclass-with-treat-as
http://www.jroller.com/RickHigh/entry/round_2_jpa_hibernate_accessing

@beikov beikov self-assigned this Apr 26, 2015
@beikov beikov added this to the 1.0.1 milestone Apr 26, 2015
@beikov beikov modified the milestones: 1.0.2, 1.0.1 May 20, 2015
@beikov beikov modified the milestones: 1.0.3, 1.0.4 Jun 5, 2015
@beikov beikov modified the milestones: 1.0.5, 1.0.4 Jun 20, 2015
@beikov beikov modified the milestones: 1.0.6, 1.0.5 Aug 5, 2015
@beikov
Copy link
Member Author

beikov commented Aug 15, 2015

Seems we will need secondary joins a.k.a. multiple from clauses in order to make that work in a spec compliant way.

@beikov
Copy link
Member Author

beikov commented Aug 15, 2015

Let's call expressions that access properties from a subclass polymorphic expressions and joins with relations from a subclass polymorphic joins.
When having a polymorphic join the transformation to make it JPA spec compliant requires a secondary join for the concrete type from which the relation comes from. The joins have to be rewritten to use the newly created join node from the secondary join. Additionally a where clause for each type has to be created that checks for id equality between the base entity and the concrete entity.
When a polymorphic join or expression is used in a clause it first has to be rewritten to use the newly created join node. The next step is to create a case when expression which emits the expression only when the type of the base entity is the concrete entity.

Here an example:

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="OBJECT_TYPE", discriminatorType = DiscriminatorType.STRING)
public abstract class Document {

    @Id
    @GeneratedValue
    private Long id;
    private String name;
}

@Entity
@DiscriminatorValue("CONTRACT")
public class Contract extends Document {

    @ManyToOne(fetch = FetchType.LAZY)
    private Person contractOwner;
}

@Entity
@DiscriminatorValue("MEETING")
public class MeetingSheet extends Document {

    @ManyToOne(fetch = FetchType.LAZY)
    private Person writer;
}

@Entity
public class Person {

    @Id
    @GeneratedValue
    private Long id;
    private String name;
}

The query following polymorphic query will be supported.

SELECT CASE WHEN contractOwner IS NOT NULL THEN contractOwner.name ELSE writer.name END 
FROM Document d 
LEFT JOIN d.contractOwner contractOwner 
LEFT JOIN d.writer writer 
ORDER BY d.id

JPA providers that don't support that natively which is every of them except for Hibernate, will get the following transformed query.

SELECT CASE WHEN TYPE(d) = Contract THEN contractOwner.name ELSE writer.name END 
FROM Document d, Contract c, MeetingSheet m 
LEFT JOIN c.contractOwner contractOwner 
LEFT JOIN m.writer writer 
WHERE (TYPE(d) = Contract AND d.id = c.id) 
OR (TYPE(d) = MeetingSheet AND d.id = m.id) 
ORDER BY d.id

Note that in the above we support the rewriting of null equality checks of polymorphic join nodes to type checks. Type checks will be interpreted correctly and only rewritten accordingly.

@beikov beikov modified the milestones: 1.1.0, 1.0.6 Aug 17, 2015
@beikov
Copy link
Member Author

beikov commented Sep 27, 2015

Note that JPA makes it impossible to do a JOIN FETCH for the relations. I already created an issue for that. https://java.net/jira/browse/JPA_SPEC-117
JPA providers should actually either allow the original query or the treat version otherwise it would be impossible to specify these semantics.

@beikov beikov modified the milestones: 1.2.0, 1.1.0 Feb 4, 2016
@beikov
Copy link
Member Author

beikov commented Feb 4, 2016

I don't see how we can fix this for now.

@beikov beikov removed this from the 1.2.0 milestone Feb 19, 2016
@beikov beikov added this to the 1.2.0 milestone Mar 10, 2017
@beikov
Copy link
Member Author

beikov commented Mar 10, 2017

Note that what is described here is actually a nice way to emulate the TREAT operator for broken JPA providers for most cases. This will be done as part of #120

@beikov
Copy link
Member Author

beikov commented Apr 13, 2017

Superseded by #409

@beikov beikov closed this as completed Apr 13, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant