users@jpa-spec.java.net

[jpa-spec users] [jsr338-experts] Re: Entity Graphs

From: Linda DeMichiel <linda.demichiel_at_oracle.com>
Date: Tue, 29 Jan 2013 17:27:55 -0800

On 1/29/2013 2:14 PM, Steve Ebersole wrote:
> What is the proposed behavior of EntityGraph or Subgraph when addAttributeNodes is called with non-basic attribute types
> (a ManyToOne for example)? Is that considered an exception condition? And if so, what exception
> (IllegalArgumentException)? Or do providers simply interpret it as a call to addSubgraph?
>

It just adds the attibute node for the attribute, but doesn't give the opportunity to expand on it
as a subgraph.

BTW, the documentation for EntityGraph is messed up. The last paragraph of the getName method docs
should really have been applied to EntityGraph instead (i.e., at top level).

> Also, a minor edit to report in the spec, at least as of the Public Review Draft. In the definition of the
> NamedEntityGraph annotation, the type of subclassSubgraphs is defined as NamedSubGraph[] rather than NamedSubgraph[]
>

thanks!

>
> On Sun 09 Dec 2012 05:04:55 PM CST, Linda DeMichiel wrote:
>> I've spec'd out a more detailed version of the proposal. Please
>> review and comment.
>>
>> thanks,
>>
>> -Linda
>>
>> -------------------------------
>>
>> Section: Entity Graphs
>>
>> An entity graph is a template that is defined in the form of metadata
>> or an object created by the dynamic EntityGraph API and that captures
>> the path and boundaries for an operation or query.
>>
>> Entity graphs are used in the specification of "fetch plans" for
>> query or find operations and as specifications for the boundaries
>> of merge or copy operations.
>>
>>
>> Subsection: Use of Entity Graphs in find and query operations
>>
>> An entity graph can be used with the find operation or as a query
>> hint to override or augment FetchType semantics.
>>
>> The standard properties javax.persistence.fetchgraph and
>> javax.persistence.loadgraph are used to specify such graphs to queries
>> and find operations.
>>
>> The default fetch graph for an entity or embeddable is defined to
>> consist of the transitive closure of all of its attributes that are
>> specified as FetchType.EAGER (or defaulted as such).
>>
>> The persistence provider is permitted to fetch additional entity state
>> beyond that specified by a fetch graph or load graph. It is required,
>> however, that the persistence provider fetch all state specified by the
>> fetch or load graph.
>>
>> Subsectionsection: Fetch graph semantics
>>
>> When the javax.persistence.fetchgraph property is used to specify an
>> entity graph, attributes that are specified by attribute nodes of the
>> entity graph are treated as FetchType.EAGER and attributes that are
>> not specified are treated as FetchType.LAZY. The primary key and
>> version attributes of an entity are always retrieved, even if not
>> specified by the fetch graph.
>>
>> The following rules apply, depending on attribute type. The rules of
>> this section are applied recursively.
>>
>> A primary key or version attribute never needs to be specified in an
>> attribute node of a fetch graph. (This applies to composite primary
>> keys as well, including embedded id primary keys.) When an entity is
>> fetched, its primary key and version attributes are always fetched.
>> It is not incorrect, however, to specify primary key attributes or
>> version attributes.
>>
>> Attributes other than primary key and version attributes are assumed
>> not to be fetched unless the attribute is specified. The following
>> rules apply to the specification of attributes:
>>
>> If the attribute is an embedded attribute, and the attribute is
>> specified in an attribute node, but a subgraph is not specified for
>> the attribute, the default fetch graph for the embeddable is fetched.
>> If a subgraph is specified for the attribute, the attributes of the
>> embeddable are fetched according to their specification in the
>> corresponding subgraph.
>>
>> If the attribute is an element collection of basic type, and the
>> attribute is specified in an attribute node, the element collection
>> together with its basic elements is fetched.
>>
>> If the attribute is an element collection of embeddables, and the
>> attribute is specified in an attribute node, but a subgraph is not
>> specified for the attribute, the element collection together with the
>> default fetch graph of its embeddable elements is fetched. If a
>> subgraph is specified for the attribute, the attributes of the
>> embeddable elements will be fetched according to the corresponding
>> subgraph specification.
>>
>> If the attribute is a one-to-one or many-to-one relationship, and the
>> attribute is specified in an attribute node, but a subgraph is not
>> specified for the attribute, the default fetch graph of the target
>> entity is fetched. If a subgraph is specified for the attribute, the
>> attributes of the target entity will be fetched according to the
>> corresponding subgraph specification.
>>
>> If the attribute is a one-to-many or many-to-many relationship, and
>> the attribute is specified in an attribute node, but a subgraph is not
>> specified, the collection will be fetched and the default fetch graphs
>> of the referenced entities will be fetched. If a subgraph is
>> specified for the attribute, the entities in the collection will be
>> fetched according to the corresponding subgraph specification.
>>
>> If the key of a map which has been specified in an attribute node is a
>> basic type, it will always be fetched. If the key of a map which has
>> been specified in an attribute node is an embedded type the default
>> fetch graph will be fetched for the embeddable. Otherwise, if the key
>> of the map is an entity, and a map key subgraph is not specified for
>> the attribute node, the map key will be fetched according to its
>> default fetch graph. If a key subgraph is specified for the map key
>> attribute, the map key attribute will be fetched according to the map
>> key subgraph specification.
>>
>> Example:
>>
>> @NamedEntityGraph
>> @Entity
>> public class Phonenumber{
>> @Id
>> protected String number;
>>
>> protected PhoneTypeEnum type;
>> ...
>> }
>>
>> In this example, only the number attribute would be eagerly fetched.
>>
>>
>>
>> Example:
>>
>> @NamedEntityGraph(
>> attributeNodes={
>> @NamedAttributeNode("projects")
>> }
>> )
>> @Entity
>> public class Employee{
>>
>> @Id
>> @GeneratedValue
>> protected long id;
>>
>> @Basic
>> protected String name;
>>
>> @Basic
>> protected String employeeNumber;
>>
>> @OneToMany()
>> protected List<Dependants> dependants;
>>
>> @OneToMany()
>> protected List<Project> projects;
>>
>> @OneToMany()
>> protected List<PhoneNumber> phoneNumbers;
>> ...
>> }
>>
>> @Entity
>> @Inheritance
>> public class Project{
>> @Id
>> @GeneratedValue
>> protected long id;
>>
>> String name;
>>
>> @OneToOne(fetch=FetchType.EAGER)
>> protected Requirements doc;
>> ...
>> }
>>
>> @Entity
>> public class LargeProject extends Project{
>>
>> @OneToOne(fetch=FetchType.LAZY)
>> protected Employee approver;
>> ...
>> }
>>
>>
>>
>> @Entity
>> public class Requirements{
>> @Id
>> protected long id;
>>
>> @Lob
>> protected String description;
>>
>> @OneToOne(fetch=FetchType.LAZY)
>> protected Approval approval
>> ...
>> }
>>
>>
>> In the above example, the Employee entity's primary key will be
>> fetched as well as the related project instances, whose default fetch
>> graph (id, name, and doc attributes) will be fetched. The related
>> Requirements object will be fetched according to its default fetch
>> graph.
>>
>> If the approver attribute of LargeProject were FetchType.EAGER, and
>> if any of the projects were instances of LargeProject, their approver
>> attributes would also be fetched. Since the type of the approver
>> attribute is Employee, the approver's default fetch graph (id, name,
>> and employeeNumber attributes) would also be fetched.
>>
>>
>>
>>
>> Subsubsection: Load graph semantics:
>>
>> When the javax.persistence.loadgraph property is used to specify an
>> entity graph, attributes that are specified by attribute nodes of the
>> entity graph are treated as FetchType.EAGER and attributes that are
>> not specified are treated according to their specified or default
>> FetchType. The primary key and version attributes of an entity are
>> always retrieved.
>>
>> The following rules apply. The rules of this section are applied
>> recursively.
>>
>> A primary key or version attribute never needs to be specified in an
>> attribute node of a load graph. (This applies to composite primary
>> keys as well, including embedded id primary keys.) When an entity is
>> fetched, its primary key and version attributes are always fetched.
>> It is not incorrect, however, to specify primary key attributes or
>> version attributes.
>>
>> If the attribute is an embedded attribute, and the attribute is
>> specified in an attribute node, the default fetch graph for the
>> embeddable is fetched. If a subgraph is specified for the attribute,
>> attributes that are specified by the subgraph are also fetched.
>>
>> If the attribute is an element collection of basic type, and the
>> attribute is specified in an attribute node, the element collection
>> together with its basic elements is fetched.
>>
>> If the attribute is an element collection of embeddables, and the
>> attribute is specified in an attribute node, the element collection
>> together with the default fetch graph of its embeddable elements is
>> fetched. If a subgraph is specified for the attribute, attributes
>> that are specified by the subgraph are also fetched.
>>
>> If the attribute is a one-to-one or many-to-one relationship, and the
>> attribute is specified in an attribute node, the default fetch graph
>> of the target entity is fetched. If a subgraph is specified for the
>> attribute, attributes that are specified by the subgraph are also
>> fetched.
>>
>> If the attribute is a one-to-many or many-to-many relationship, and
>> the attribute is specified in an attribute node, the collection will
>> be fetched and the default fetch graphs of the referenced entities
>> will be fetched. If a subgraph is specified for the attribute,
>> attributes that are specified by the subgraph are also fetched.
>>
>> If a collection-valued attribute is a map, and the map-valued
>> attribute is specified in an attribute node, keys that are basic or
>> embeddable types will be fetched when the map is fetched; entity map
>> key attributes will be fetched according to the default fetch graph
>> and, if a key subgraph is specified, additional entity attributes are
>> fetched as specified in the subgraph.
>>
>> Example:
>>
>> @NamedEntityGraph
>> @Entity
>> public class Phonenumber{
>> @Id
>> protected String number;
>>
>> protected PhoneTypeEnum type;
>> ...
>> }
>>
>> In the above example, the number and type attributes are loaded.
>>
>>
>> Example:
>>
>> @NamedEntityGraph(
>> attributeNodes={
>> @NamedAttributeNode("projects")
>> }
>> )
>> @Entity
>> public class Employee{
>>
>> @Id
>> @GeneratedValue
>> protected long id;
>>
>> @Basic
>> protected String name;
>>
>> @Basic
>> protected String employeeNumber;
>>
>> @OneToMany()
>> protected List<Dependants> dependants;
>>
>> @OneToMany()
>> protected List<Project> projects;
>>
>> @OneToMany()
>> protected List<PhoneNumber> phoneNumbers;
>> ...
>> }
>>
>> @Entity
>> @Inheritance
>> public class Project{
>> @Id
>> @GeneratedValue
>> protected long id;
>>
>> String name;
>>
>> @OneToOne(fetch=FetchType.EAGER)
>> protected Requirements doc;
>> ...
>> }
>>
>> @Entity
>> public class LargeProject extends Project{
>>
>> @OneToOne(fetch=FetchType.LAZY)
>> protected Employee approver;
>> ...
>> }
>>
>>
>>
>> @Entity
>> public class Requirements{
>> @Id
>> protected long id;
>>
>> @Lob
>> protected String description;
>>
>> @OneToOne(fetch=FetchType.LAZY)
>> protected Approval approval
>> ...
>> }
>>
>> In the above example, the default fetch graph (id, name, and
>> employeeNumber) of Employee is loaded. The default fetch graphs of
>> the related Project instances (id, name, and doc attributes) and their
>> Requirements instances (id and description attributes) are also
>> loaded.
>>
>>
>>
>> Subsection: Merge graph semantics
>>
>> An entity graph may be used as a "merge graph" and passed as an
>> argument to the merge method.
>>
>> The following semantics apply to entity graphs that are used as merge
>> graphs.
>>
>> A merge graph attribute node specified within an entity graph or
>> subgraph specifies how an attribute is to be merged. Primary key and
>> version attributes do not need to be specified in the merge graph. If
>> other attributes are not specified, they are not merged. Note that
>> cascade=MERGE specifications are ignored.
>>
>> The persistence provider must observe the scope and boundaries of a
>> merge graph specification exactly.
>>
>> The following additional rules apply for attributes that are
>> specified in attribute nodes. These rules are applied recursively.
>>
>> If the attribute is an embedded attribute and a subgraph is not
>> specified for the attribute, the embedded attribute is merged but the
>> attributes of the embeddable are not merged. If a subgraph is
>> specified for the attribute, the attributes of the embeddable are
>> merged according to their specification in the corresponding subgraph.
>>
>> If the attribute is an element collection of basic type, the element
>> collection is merged. The values in the element collection are
>> replaced.
>>
>> If the attribute is an element collection of embeddables and a
>> subgraph is not specified for the attribute, the element collection is
>> merged. The values in the element collection are replaced and all
>> attributes of the embeddables are included. If a subgraph is
>> specified for the attribute, the values in the element collection are
>> replaced and all attributes of the embeddables are included, and the
>> attributes specified in the subgraph are processed according to the
>> subgraph specification.
>>
>> If the attribute is a one-to-one or many-to-one relationship and a
>> subgraph is not specified for the attribute, the attribute is merged,
>> but the attributes of the target entity are not merged. If a subgraph
>> is specified for the attribute, the attributes of the target entity
>> will be merged according to the corresponding subgraph specification.
>>
>> If the attribute is a one-to-many or many-to-many relationship and a
>> subgraph is not specified for the attribute, the attribute is merged,
>> but the attributes of the target entity are not merged. If a subgraph
>> is specified for the attribute, the entities in the collection will be
>> merged according to the corresponding subgraph specification.
>>
>> In both of the two relationship cases above, note that if a new
>> entity (entity in the "new" state) was added to the relationship and
>> only a subset of its attributes is specified in the subgraph, only
>> those specified attributes are copied.
>>
>> If the attribute is a map, the map key will be merged. If the map key
>> is an embeddable, all attributes of the embeddable are included. If
>> the map key is an entity, the attribute is merged, but the attributes
>> of the target entity are not merged. If a subgraph is specified for
>> the attribute, the target entity is merged according to the corresponding
>> subgraph specification.
>>
>>
>> Example:
>>
>> @NamedEntityGraph(
>> attributeNodes={
>> @NamedAttributeNode("name"),
>> @NamedAttributeNode(
>> value="projects",
>> subGraph="projects"
>> ),
>> @NamedAttributeNode("phoneNumbers"),
>> },
>> subGraphs={
>> @NamedSubGraph(
>> name="projects",
>> attributeNodes={
>> @NamedAttributeNode("doc")
>> }
>> )
>> }
>> )
>> @Entity
>> public class Employee{
>>
>> @Id
>> @GeneratedValue
>> protected long id;
>>
>> @Basic
>> protected String name;
>>
>> @Basic
>> protected String employeeNumber;
>>
>> @OneToMany()
>> protected List<Dependants> dependants;
>>
>> @OneToMany()
>> protected List<Project> projects;
>>
>> @OneToMany()
>> protected List<PhoneNumber> phoneNumbers;
>> ...
>> }
>>
>> @Entity
>> public class Phonenumber{
>> @Id
>> protected String number;
>>
>> protected PhoneTypeEnum type;
>> ...
>> }
>>
>>
>> @Entity
>> @Inheritance
>> public class Project{
>> @Id
>> @GeneratedValue
>> protected long id;
>>
>> String name;
>>
>> @OneToOne(fetch=FetchType.EAGER)
>> protected Requirements doc;
>> ...
>> }
>>
>> In the above example, the name attribute and the projects and
>> phoneNumbers
>> collections will be merged. Within projects, only the doc attribute will
>> be merged. No attributes of phoneNumbers will be merged.
>>
>>
>>
>> Subsection: Copy graph semantics
>>
>> An entity graph may be used as a "copy graph" and passed as an
>> argument to the copy method.
>>
>> The copy method is intended for use in disconnecting a graph of
>> entities from a larger graph. When using an entity graph in
>> combination with the copy operation, a copy of the entity is created
>> and the attributes of the copied entity are populated based on copies
>> of the attributes listed in the entity graph.
>>
>> The following semantics apply to entity graphs that are used as copy
>> graphs.
>>
>> The persistence provider must observe the scope and boundaries of a
>> copy graph specification exactly.
>>
>> OPEN ISSUE: If a copy graph specifies an attribute that has not
>> yet been loaded, should it be loaded?
>>
>> The following rules apply to the specification of attributes. The
>> rules of this section are applied recursively.
>>
>> Primary key and version attributes are always copied.
>> Attributes are otherwise not copied unless they are specified.
>>
>> If the attribute is an embedded attribute and an attribute node is
>> specified for the attribute but a subgraph is not specified for the
>> attribute, a new instance of the embeddable is inserted into the
>> resulting copy of the entity graph, but no state is copied. If a
>> subgraph is specified for the attribute, the attributes of the
>> embeddable are copied according to their specification in the
>> corresponding subgraph.
>>
>> If the attribute is an element collection of basic type, the element
>> collection and its contents are copied.
>>
>> If the attribute is an element collection of embeddables and an
>> attribute node is specified for the attribute but a subgraph is not
>> specified, a new collection is created and new embeddables instances
>> are inserted into it, but no state is copied. If a subgraph is
>> specified for the attribute, the embeddables are copied according to
>> their specification in the subgraph.
>>
>> If the attribute is a one-to-one or many-to-one relationship and an
>> attribute node is specified for the attribute, but a subgraph is not
>> specified, a copy of the entity is created and inserted. Only the
>> primary key and version attributes of the entity are copied. If a
>> subgraph is specified for the attribute, a copy of the entity is
>> created and inserted and the attributes of the target entity are
>> copied according to the corresponding subgraph specification along
>> with the primary key and version attributes.
>>
>> If the attribute is a one-to-many or many-to-many relationship and an
>> attribute node is specified for the attribute, but a subgraph is not
>> specified, a new collection is created and inserted, and copies of the
>> referenced entities are created and inserted into the collection.
>> Only the primary key and version attributes of these entities are
>> copied. If a subgraph is specified for the attribute, the entities in
>> the collection will be copied according to the corresponding subgraph
>> specification along with the primary key and version attributes.
>>
>> If the attribute is a map and an attribute node has been specified for
>> the attribute:
>> if the map key attribute is a basic type, it is copied;
>> if the map key attribute is an embedded attribute, a new instance
>> of the
>> embeddable is inserted but no state is copied;
>> if the map key attribute is an entity, a copy of the entity is
>> created,
>> and only the primary key and version attributes of the entity
>> are copied.
>> If a subgraph is specified for the embeddable or entity, the
>> attributes
>> of the target are copied according to the corresponding map key
>> subgraph specification.
>>
>>
>> Example:
>>
>> @NamedEntityGraph(
>> attributeNodes={
>> @NamedAttributeNode("name"),
>> @NamedAttributeNode(
>> value="projects",
>> subGraph="projects"
>> ),
>> @NamedAttributeNode("phoneNumbers"),
>> },
>> subGraphs={
>> @NamedSubGraph(
>> name="projects",
>> attributeNodes={
>> @NamedAttributeNode("doc")
>> }
>> )
>> }
>> )
>> @Entity
>> public class Employee{
>>
>> @Id
>> @GeneratedValue
>> protected long id;
>>
>> @Basic
>> protected String name;
>>
>> @Basic
>> protected String employeeNumber;
>>
>> @OneToMany()
>> protected List<Dependants> dependants;
>>
>> @OneToMany()
>> protected List<Project> projects;
>>
>> @OneToMany()
>> protected List<PhoneNumber> phoneNumbers;
>> ...
>> }
>>
>> @Entity
>> public class Phonenumber{
>> @Id
>> protected String number;
>>
>> protected PhoneTypeEnum type;
>> ...
>> }
>>
>>
>> @Entity
>> @Inheritance
>> public class Project{
>> @Id
>> @GeneratedValue
>> protected long id;
>>
>> String name;
>>
>> @OneToOne(fetch=FetchType.EAGER)
>> protected Requirements doc;
>> ...
>> }
>>
>> In the above example, a new Employee instance will be created and the
>> values of the id and name attributes copied. The projects and
>> phoneNumbers collections are recreated and populated in the copy. For
>> the entities within the new projects collection, the id attributes are
>> copied and new Requirements objects created. Only the id attribute of
>> the Requirement entity is copied. For the entities within the new
>> phoneNumbers collection, only the number attribute is copied.
>>
>>
>>