Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "EclipseLink/Development/JPA 2.0/entity type expressions"

(Work Required)
 
(8 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
= Entity Type Expression =
 
= Entity Type Expression =
[[EclipseLink/Development/JPA_2.0 | JPA 2.0 Root]] |
+
[[EclipseLink/Development/JPA_2.0 | JPA 2.0 Root]] | {{bug|252009}}
[http://bugs.eclipse.org/252009 Enhancement Request]
+
 
==Issue Summary==
 
==Issue Summary==
 
JPA 2.0 introduces JPQL expressions that allow  a query to restrict results based on class types.  This feature will require functionality to be added to EclipseLink.
 
JPA 2.0 introduces JPQL expressions that allow  a query to restrict results based on class types.  This feature will require functionality to be added to EclipseLink.
Line 9: Line 8:
 
==General Solution==
 
==General Solution==
 
Expression Support will be required that can provide a comparison with an extracted discriminator value.
 
Expression Support will be required that can provide a comparison with an extracted discriminator value.
 +
 +
==Native Expression Support==
 +
through EclipseLink [http://bugs.eclipse.org/277509 Enhancement 277509]
 +
1)ReportQuery will need return Class objects that the Type expression correlates to
 +
2) Type expressions need to be supported that take parameters and constants representing Java Classes that will evaluate to String/Int values used in these class's inheritance policy fields
 +
3) Type expresions also need to operate on expressions representing relationships and entities, allowing them all to be compared
 +
===Public API===
 +
* <source lang="java">public Expression type()</source>
 +
returns a Type expression operating on the base expression.  The base expression must be an ObjectExpression.  Examples:
 +
  <source lang="java">expressionBuilder.get("project").type().equals(LargeProject.class) </source> 
 +
 +
Type chosen as it mirrors the proposed Criteria API in the JPA 2.0 spec.  Calling type() is only valid on relationship query keys and other object type expressions.  These object expressions must correlate to descriptors that have inheritance that use a discriminator field, or an invalidTypeExpression will be thrown.  For intance:
 +
  <source lang="java">expressionBuilder.get("firstName").get("project").type().equals(LargeProject.class) </source>
 +
Where firstName is a string attribute would result in QueryException:"Invalid Type Expression on [{0}].  The class does not have a descriptor, or a descriptor that does not use inheritance or uses a ClassExctractor for inheritance"
 +
 
 +
==Generated SQL==
 +
Queries on the root of an inheritance tree currently require EclipseLink to issue an SQL to first pull out the subclasses that will be returned and then issue an SQL for each subclass.  ie JPQL "Select p from Project" might result in SQL:
 +
"SELECT DISTINCT type FROM PROJECT"
 +
"SELECT t0.*, t1.* from PROJECT t0, SMALLPROJECT t1 where ((t0.id = t1.id) AND (t0.TYPE = 'S'))"
 +
"SELECT t0.*, t1.* from PROJECT t0, LARGEPROJECT t1 where ((t0.id = t1.id) AND (t0.TYPE = 'L'))"
 +
Using joining for inheritance (shouldOuterJoinSubclasses) allows all the tables from all possible subclasses to be done in one query.  ie:
 +
  "SELECT t0.*, t1.* from PROJECT t0, LARGEPROJECT t1, SMALLPROJECT t2 where ((t0.id = t1.id) AND (t0.id = t2.id))"
 +
 +
Expressions to filter data will be used on all the queries.  Using type expressions will not change the behavior mentioned above - Using say JPQL "Select p from Project where Type(p)= LargeProject" would still result in 2 SQL queries:
 +
  "SELECT DISTINCT type FROM PROJECT Where type = 'L'"
 +
  "SELECT t0.*, t1.* from PROJECT t0, LARGEPROJECT t1 where ((t0.TYPE = 'L') AND (t0.id = t1.id) AND (t0.TYPE = 'L'))"
 +
or if shouldOuterJoinSubclasses is true one query with the SQL:
 +
  "SELECT t0.*, t1.* from PROJECT t0, LARGEPROJECT t1, SMALLPROJECT t2 where ((t0.TYPE = 'L') AND (t0.id = t1.id) AND (t0.id = t2.id))"
 +
This is because the TYPE expression is added before the inheritance calculation.  Users may find this behavior a problem because it is obvious that only the 1 query/table ect is required.  Unfortunately, this is not the case with more complex queries such as "Select p from Project where (type(p) in (somesubset_of_Subclasses)) OR some_other_Conditions".  EclipseLink currently is not able to evaluate the expressions and factor the type expressions into what is required for inheritance queries, and so does not attempt to.  Such functionality should be handled as a seperate feature if requested
 +
  
 
==Work Required==
 
==Work Required==
Line 14: Line 43:
 
#: approx 1 day
 
#: approx 1 day
 
# Update Processing
 
# Update Processing
#: approx 6 days - creating expression support.
+
#: approx 6 days - creating expression support: EclipseLink [http://bugs.eclipse.org/277509 Enhancement 277509] Completed
#: approx 3 days - updating Parser
+
#: approx 3 days - updating Parser: EclipseLink [http://bugs.eclipse.org/249224 Enhancement 249224] Completed

Latest revision as of 08:50, 2 September 2009

Entity Type Expression

JPA 2.0 Root | bug 252009

Issue Summary

JPA 2.0 introduces JPQL expressions that allow a query to restrict results based on class types. This feature will require functionality to be added to EclipseLink.

See JPA 2.0 section 4.4.8 and 4.4.9 for details.

General Solution

Expression Support will be required that can provide a comparison with an extracted discriminator value.

Native Expression Support

through EclipseLink Enhancement 277509 1)ReportQuery will need return Class objects that the Type expression correlates to 2) Type expressions need to be supported that take parameters and constants representing Java Classes that will evaluate to String/Int values used in these class's inheritance policy fields 3) Type expresions also need to operate on expressions representing relationships and entities, allowing them all to be compared

Public API

*
public Expression type()

returns a Type expression operating on the base expression. The base expression must be an ObjectExpression. Examples:

expressionBuilder.get("project").type().equals(LargeProject.class)

Type chosen as it mirrors the proposed Criteria API in the JPA 2.0 spec. Calling type() is only valid on relationship query keys and other object type expressions. These object expressions must correlate to descriptors that have inheritance that use a discriminator field, or an invalidTypeExpression will be thrown. For intance:

expressionBuilder.get("firstName").get("project").type().equals(LargeProject.class)

Where firstName is a string attribute would result in QueryException:"Invalid Type Expression on [{0}]. The class does not have a descriptor, or a descriptor that does not use inheritance or uses a ClassExctractor for inheritance"

Generated SQL

Queries on the root of an inheritance tree currently require EclipseLink to issue an SQL to first pull out the subclasses that will be returned and then issue an SQL for each subclass. ie JPQL "Select p from Project" might result in SQL:

"SELECT DISTINCT type FROM PROJECT"
"SELECT t0.*, t1.* from PROJECT t0, SMALLPROJECT t1 where ((t0.id = t1.id) AND (t0.TYPE = 'S'))"
"SELECT t0.*, t1.* from PROJECT t0, LARGEPROJECT t1 where ((t0.id = t1.id) AND (t0.TYPE = 'L'))"

Using joining for inheritance (shouldOuterJoinSubclasses) allows all the tables from all possible subclasses to be done in one query. ie:

 "SELECT t0.*, t1.* from PROJECT t0, LARGEPROJECT t1, SMALLPROJECT t2 where ((t0.id = t1.id) AND (t0.id = t2.id))"

Expressions to filter data will be used on all the queries. Using type expressions will not change the behavior mentioned above - Using say JPQL "Select p from Project where Type(p)= LargeProject" would still result in 2 SQL queries:

 "SELECT DISTINCT type FROM PROJECT Where type = 'L'"
 "SELECT t0.*, t1.* from PROJECT t0, LARGEPROJECT t1 where ((t0.TYPE = 'L') AND (t0.id = t1.id) AND (t0.TYPE = 'L'))"

or if shouldOuterJoinSubclasses is true one query with the SQL:

 "SELECT t0.*, t1.* from PROJECT t0, LARGEPROJECT t1, SMALLPROJECT t2 where ((t0.TYPE = 'L') AND (t0.id = t1.id) AND (t0.id = t2.id))"

This is because the TYPE expression is added before the inheritance calculation. Users may find this behavior a problem because it is obvious that only the 1 query/table ect is required. Unfortunately, this is not the case with more complex queries such as "Select p from Project where (type(p) in (somesubset_of_Subclasses)) OR some_other_Conditions". EclipseLink currently is not able to evaluate the expressions and factor the type expressions into what is required for inheritance queries, and so does not attempt to. Such functionality should be handled as a seperate feature if requested


Work Required

  1. Develop model for testing
    approx 1 day
  2. Update Processing
    approx 6 days - creating expression support: EclipseLink Enhancement 277509 Completed
    approx 3 days - updating Parser: EclipseLink Enhancement 249224 Completed

Back to the top