6.1 Gerenciamento de dependência profunda
E algumas coisas mais úteis e interessantes sobre as anotações @OneToMany e afins. Todos eles têm 4 opções comumente usadas:
- cascata = CascadeType.ALL
- orphanRemoval = verdadeiro
- buscar = FetchType.LAZY
Agora vamos analisá-los com mais detalhes. E vamos começar com o mais interessante - CascadeType . Este parâmetro determina o que deve acontecer com as entidades dependentes se mudarmos a entidade principal.
A especificação JPA possui os seguintes valores para este parâmetro:
- TODOS
- PERSISTIR
- MERGE
- REMOVER
- ATUALIZAR
- SEPARAR
No entanto, o Hibernate expande essa especificação em mais três opções:
- REPLICAR
- SAVE_UPDATE
- TRANCAR
Existe, claro, um forte paralelo com o banco de dados e seus CONSTRANIS. No entanto, também existem diferenças. O Hibernate tenta esconder o máximo possível o trabalho real com o banco de dados, então essas cascatas do Hibernate são exatamente sobre objetos Entity.
6.2 Tipo Cascata
O parâmetro cascade descreve o que deve acontecer com os objetos dependentes se mudarmos seu pai (objeto mestre). Na maioria das vezes, esse parâmetro é usado junto com anotações que descrevem as dependências do objeto:
Exemplo:
OneToOne(cascade = CascadeType.ALL)
Ou assim:
@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
Também pode ser escrito como uma anotação separada:
@Cascade({ org.hibernate.annotations.CascadeType.ALL })
Agora vamos falar mais sobre o que essas anotações significam.
6.3 TUDO, PERSISTIR, MERGE
CascadeType.ALL
significa que todas as ações que executamos com o objeto pai devem ser repetidas para seus objetos dependentes.
CascadeType.PERSIST
significa que se salvarmos o objeto pai no banco de dados, o mesmo deve ser feito com seus objetos dependentes. Exemplo:
@Entity
@Table(name="employee")
class Employee {
@Column(name="id")
public Integer id;
@OneToOne(cascade = CascadeType.PERSIST, mappedBy="task")
private EmployeeTask task;
}
Um exemplo de trabalho com esta classe:
Employee director = new Employee();
EmployeeTask task = new EmployeeTask();
director.task = task;
session.persist(director);
session.flush();
Salvamos apenas um objeto do tipo Employee, seu objeto dependente EmployeeTask será salvo no banco de dados automaticamente.
CascadeType.MERGE
significa que se atualizarmos o objeto pai no banco de dados, o mesmo deve ser feito com seus objetos dependentes.
6.4 REMOVER, EXCLUIR, SEPARAR
CascadeType.REMOVE
significa que se excluirmos um objeto pai no banco de dados, o mesmo deve ser feito com seus objetos dependentes.
CascadeType.DELETE
significa o mesmo. Estes são sinônimos. Apenas de especificações diferentes.
CascadeType.DETACH
significa que se removermos o objeto pai da sessão, o mesmo deve ser feito com seus objetos dependentes. Exemplo:
@Entity
@Table(name="employee")
class Employee {
@Column(name="id")
public Integer id;
@OneToOne(cascade = CascadeType.DETACH, mappedBy="task")
private EmployeeTask task;
}
Um exemplo de trabalho com esta classe:
Employee director = new Employee();
EmployeeTask task = new EmployeeTask();
director.task = task;
director.task = task;
session.flush();
assertThat(session.contains(director)).isTrue();
assertThat(session.contains(task)).isTrue();
session.detach(director);
assertThat(session.contains(director)).isFalse();
assertThat(session.contains(task)).isFalse();
CascadeType.REFRESH
e CascadeType.SAVE_UPDATE
funcionam da mesma forma que esperamos - eles duplicam as ações que são executadas com o objeto pai para seu objeto dependente.
6.5 Opção de remoção órfã
Além disso, às vezes você pode encontrar o parâmetro orphan
. Isso é a abreviação de remoção de órfãos. Ele é usado para garantir que não haja entidades filhas sem entidades pai.
OneToOne(orphan = true)
Se este parâmetro for definido como verdadeiro, a entidade filha será excluída se tiver desaparecidotodos os links. Não é exatamente o mesmo que Cascade.REMOVE
.
Você pode ter uma situação em que várias entidades pai se referem a um filho. Então é benéfico que não seja excluído junto com a exclusão da entidade pai, mas apenas se todas as referências a ela forem anuladas.
Digamos que você tenha uma classe:
@Entity
@Table(name="user")
class Employee {
@Column(name="id")
public Integer id;
@OneToMany(cascade = CascadeType.ALL, orphan = true)
@JoinColumn(name = "employee_id")
private Set<EmployeeTask> tasks = new HashSet<EmployeeTask>();
}
Employee director = session.find(Employee.class, 4);
EmployeeTask task = director.tasks.get(0);
director.tasks.remove(task)
session.persist(director);
session.flush();
O objeto EmployeeTask será excluído porque não há mais referências a ele. Ao mesmo tempo, ninguém excluiu o objeto pai.
6.6 opção de busca
A opção de busca permite controlar como os objetos dependentes são carregados. Geralmente, assume um dos dois valores:
FetchType.LAZY
FetchType.EAGER
Este é um tópico muito interessante com várias armadilhas, então é melhor falar sobre isso em uma palestra separada.
GO TO FULL VERSION