Using EntityGraph with SuperClasses and Embedded Attributes

581 Views Asked by At

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.

1

There are 1 best solutions below

0
On

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();