0

I would like to use the EntityGraph Feature because of the known n+1 Problem. I have the following Entities structure:

@Entity
@Table(name = "customer")
public class Customer extends Person {

    @Column(name = "foo")
    public String foo;

    @Column(name = "bar")
    public String bar;
}

@Entity
@Table(name = "person")
public class Person {

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "car.id")
    public Car car;

    @Embedded
    public Key key;
}


@Entity
@Table(name = "car")
public class Car {

    @Column(name = "a")
    public String a;

    @Column(name = "b")
    public String b;
}

@Embeddable
public class Key
{
    @Column(name = "key_id")
    public Long keyId;

    @Column(name = "key_color")
    public String keyColor;
}

Now I want to use a NamedEntityGraph. As far as I understand with "@NamedEntityGraph(name = "getCustomer", includeAllAttributes=true)" it should work but it doesnt.

The NamedEntityGraph call with

em.createQuery(criteriaQuery).setHint("javax.persistence.fetchgraph", em.getEntityGraph("getCustomer")).getResultList()

returns the amount of Customers in the database but all Attributes including car and the Embedded Attribute key is always null.

Do I have to use subgraphs? I tried to declare the NamedEntityGraph on Customer class also on Person class. It makes no difference.

EDIT: After struggling a long time with this problem, i tried to break down it to the lowest level with these two entities

@Entity
@Table(name = "publication")
@NamedEntityGraph(name = "graph.Publication.articles",
        attributeNodes = @NamedAttributeNode("articles"))
public class Publication {

    @Id
    private String publicationId;

    private String name;

    private String category;

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "publicationId")
    private List<Article> articles;

@Entity
@Table(name = "article")
public class Article {

    @Id
    private String articleId;

    private String title;

    private String publicationId;
}

If i create a query i can see further more than one query in the postgres log.

EntityGraph<?> entityGraph = em.getEntityGraph("graph.Publication.articles");
List resultList = em.createQuery("SELECT x FROM Publication x").setHint("javax.persistence.fetchgraph", entityGraph).getResultList();

Different queries for all publications

SELECT ARTICLEID, publicationId, TITLE FROM article WHERE (publicationId = $1) parameters: $1 = 'publication_1'
SELECT ARTICLEID, publicationId, TITLE FROM article WHERE (publicationId = $1) parameters: $1 = 'publication_2'

But I would only have expected one query with a join here.

sylo
  • 207
  • 3
  • 16
  • Having fetch = FetchType.EAGER on Car field is verbose, cause default is Eager . – Lunatic Mar 11 '22 at 08:48
  • Key is an embedded, so should always be fetched with or without this fetch graph, so if it is null, there is something else going on. Are you sure there is data for those fields in the database? You'll want to debug and check the instance returned from running the query without and then with the FetchGroup, and also try em.refresh on the instances after that to see if the data is accessible. – Chris Mar 11 '22 at 15:27
  • Edited my Question. I think I have a fundamental problem because the edited example should work. – sylo Apr 22 '22 at 14:14

1 Answers1

0

Finally I found a solution for my problem. I refer to the edited part of my question.

I found this page which describes very well how to use batch query hints to improve performance. http://java-persistence-performance.blogspot.com/2010/08/batch-fetching-optimizing-object-graph.html?m=1

For my example I don't need the entitygraph anymore. The query should created like this

List resultList = em.createQuery("SELECT x FROM Publication x").setHint("eclipselink.batch", "x.articles").getResultList();
sylo
  • 207
  • 3
  • 16