Gráfico de entidade JPA

Gráfico de entidade JPA

1. Visão geral

O JPA 2.1 introduziu o recurso Entity Graph como um método mais sofisticado de lidar com o carregamento de desempenho.

Ele permite definir um modelo agrupando os campos de persistência relacionados que queremos recuperar e permite escolher o tipo de gráfico em tempo de execução.

Neste tutorial, explicaremos com mais detalhes como criar e usar esse recurso.

2. O que o gráfico de entidades tenta resolver

Até o JPA 2.0, para carregar uma associação de entidade, geralmente usamos FetchType.LAZY e FetchType.EAGER com estratégias de busca. Isso instrui o provedor de JPA a buscar adicionalmente a associação relacionada ou não. Infelizmente, essa meta-configuração é estática e não permite alternar entre essas duas estratégias em tempo de execução.

*O principal objetivo do JPA Entity Graph é, então, melhorar o desempenho do tempo de execução ao carregar as associações e os campos básicos relacionados à entidade.*

Resumidamente, o provedor JPA carrega todo o gráfico em uma consulta de seleção e evita buscar associação com mais consultas SELECT. Essa é uma boa abordagem para melhorar o desempenho do aplicativo.

3. Definindo o modelo

Antes de começarmos a explorar o gráfico de entidades, precisamos definir as entidades de modelo com as quais estamos trabalhando. Digamos que queremos criar um site de blog onde os usuários possam comentar e compartilhar postagens.

Então, primeiro teremos uma entidade User:

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;

   //...
}

O usuário pode compartilhar várias postagens, então também precisamos de uma entidade Post:

@Entity
public class Post {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String subject;
    @OneToMany(mappedBy = "post")
    private List<Comment> comments = new ArrayList<>();

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn
    private User user;

   //...
}

O usuário também pode comentar sobre as postagens compartilhadas, então, finalmente, adicionaremos uma entidade Comment:

@Entity
public class Comment {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String reply;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn
    private Post post;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn
    private User user;

   //...
}

Como podemos ver, a entidade Post tem uma associação com as entidades Comment e User. A entidade Comment tem uma associação com as entidades Post e User.

O objetivo é carregar o seguinte gráfico usando várias maneiras:

Post  ->  user:User
      ->  comments:List<Comment>
            comments[0]:Comment -> user:User
            comments[1]:Comment -> user:User

O método FetchType define duas estratégias para buscar dados do banco de dados:

  • FetchType.EAGER _: O provedor de persistência deve carregar o campo ou a propriedade anotada relacionada. Esse é o comportamento padrão dos campos _ @ Basic, @ManyToOne