jsr338-experts@jpa-spec.java.net

[jsr338-experts] Re: Entity Graphs

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

On 1/29/2013 2:42 PM, Steve Ebersole wrote:
> Also related... Do EntityGraph.getAttributeNodes / Subgraph.getAttributeNodes return Subgraphs in the AttributeNode list?
>

Yes

> On Tue 29 Jan 2013 04:14:13 PM CST, 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?
>>
>> 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[]
>>
>>
>> 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.
>>>
>>>
>>>