Uploaded image for project: 'Hibernate ORM'
  1. HHH-9270

Allow EntityGraphs to control loading of basic entity state (not just associations)

    Details

    • Last commented by a user?:
      true

      Description

      The central discussion is this passage from the JPA spec (2.1, section 3.7.4):

      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.

      Essentially a JPA provider is free to load as much state as they want in conjunction with an EntityGraph, so long as they load what the user asked for. In other words if an EntityGraph indicates we should load a Person's name, a provider is free to also load the Person's other attributes. All the spec says is that the Person's name must be loaded.

      And in Hibernate's impl we load all non-Collection (plural attribute) state for each node in the graph.

      In conjunction with bytecode enhancement, @LazyGroup and the SQM work we should be able to more selectively apply what to load in each case.


      Original Description


      The JPA 2.1 specification gives the following example on how to implement the fetching of attributes that are not specified in the @NamedEntityGraph:

      @NamedEntityGraph
      @Entity
      public class Phonenumber{
      @Id
      protected String number;
      }
      protected PhoneTypeEnum type;
      ...
      

      In the above example, only the number attribute would be eagerly fetched."
      [Section 3.7.4]

      In my code I have a CustomerEntity with the following @NamedEntityGraph:

      @Entity
      @NamedEntityGraph(
              name = "CustomersWithOrderId",
              includeAllAttributes=false,
              attributeNodes = {
                      @NamedAttributeNode(value = "name"),
                      @NamedAttributeNode(value = "orders", subgraph = "ordersGraph")
              },
              subgraphs = {
                      @NamedSubgraph(
                              name = "ordersGraph",
                              type = OrderEntity.class,
                              attributeNodes = {
                                      @NamedAttributeNode(value = "id"),
                                      @NamedAttributeNode(value = "campaignId")
                              }
                      )
              }
      )
      public class CustomerEntity {
      
          @Id
          @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "customer_seq")
          @SequenceGenerator(name = "customer_seq", sequenceName = "CUSTOMER_SEQ_ID_SEQ", allocationSize = 1)
          private long id;
      
          @Column
          private String name;
      
          @Column
          private int numberOfPurchases;
      
          @OneToMany(mappedBy = "customer", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
          private Set<OrderEntity> orders;
      
          @OneToMany(mappedBy = "customer", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
          private Set<AddressEntity> addresses;
      

      The generated SQL is:

          select
              customeren0_.id as id1_1_0_,
              orders1_.id as id1_2_1_,
              customeren0_.name as name2_1_0_,
              customeren0_.numberOfPurchases as numberOf3_1_0_,
              orders1_.campaignId as campaign2_2_1_,
              orders1_.CUSTOMER_ID as CUSTOMER4_2_1_,
              orders1_.timestamp as timestam3_2_1_,
              orders1_.CUSTOMER_ID as CUSTOMER4_1_0__,
              orders1_.id as id1_2_0__ 
          from
              CustomerEntity customeren0_ 
          left outer join
              OrderEntity orders1_ 
                  on customeren0_.id=orders1_.CUSTOMER_ID
      

      Despite the @NamedEntityGraph the fields numberOfPurchases of CustomerEntity and timestamp of OrderEntity are loaded, which should not be the case according the example in the specification. The field addresses of the CustomerEntity is not loaded. Hence it seems that the @NamedEntityGraph only affects fields that are Collections, but fields that are not a Collection are always loaded.

        Attachments

          Activity

            People

            • Votes:
              4 Vote for this issue
              Watchers:
              9 Start watching this issue

              Dates

              • Created:
                Updated: