users@jpa-spec.java.net

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

From: Linda DeMichiel <linda.demichiel_at_oracle.com>
Date: Wed, 30 Jan 2013 09:35:15 -0800

Hi Gordon,

Could you propose the specific methods that you think should be added in this release?

thanks,

-Linda


On 1/30/2013 6:29 AM, Gordon Yorke wrote:
> Yes, they should although it may be easier to support more inspection in the future if AttributeNode.getSubgraps()
> AttributeNode.getKeySubgraphs() were to exist or planned to exist. The alternate pattern that will be needed of
> isKeySubgraph() is not a great pattern. I think we should add this simple methods to this release if possible.
> --Gordon
>
>
> On 29/01/2013 5:42 PM, Steve Ebersole wrote:
>> Also related... Do EntityGraph.getAttributeNodes / Subgraph.getAttributeNodes return Subgraphs in the AttributeNode list?
>>
>> 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.
>>>>
>>>>
>>>>
>