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
4. Carregando entidades relacionadas com estratégias FetchType
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