Anda di halaman 1dari 27

JPA Com Hibernate Aula 2

Paulo Ricardo Lisboa de Almeida

1
Universidade Positivo
Modelo Necessrio

Modelo Necessrio

2
Universidade Positivo
Dados Transientes

Quando criamos determinada propriedade em uma classe,


mas essa propriedade no deve ser salva no banco de
dados.
Utilizar a notao
@Transient
Exemplo
@Entity
class Pessoa {
@Id
@GeneratedValue
private Long id ;
private Calendar nascimento ;
@Transient
private int idade ;//idade no precisa ser salva no banco,
pois ela pode ser deduzida pela aplicao atravs da data de nascimento
}

3
Universidade Positivo
Mapeando Relacionamentos

Feitos a partir de anotaes

4
Universidade Positivo
One to One Um para Um

Anotao @OneToOne
Ex.: um estado tem um governador e um governador
governa somente um estado

5
Universidade Positivo
One to One Um para Um
@Entity
public class Governador { A anotao @JoinColumn

@Id especifica como feito o join entre


private Long cpf; governador e estado.
No exemplo, o atributo name
private String nomeGovernador; especifica o nome da coluna
} que faz esse join na tabela
@Entity estado (Chave estrangeira)
public class Estado {
@Id
private String UF;
private String nomeEstado;
@OneToOne
@JoinColumn (name = "governador_cpf")
private Governador governador ;
}

6
Universidade Positivo
Many To One Muitos Para Um

Anotao @ManyToOne
Ex.: Muitos animais pertencem a uma pessoa, e uma
pessoa pode ter muitos animais

7
Universidade Positivo
Many To One Muitos Para Um

@Entity
@Table(name="ANIMAL")
public class Animal {
...

@ManyToOne
@JoinColumn(name = "pessoa_id")
private Pessoa dono;
...
}

8
Universidade Positivo
One To Many Um Para Muitos

Anotao @OneToMany
Ex.: Uma pessoa possui vrios animais e um animal possui
somente um dono.

9
Universidade Positivo
One To Many Um Para Muitos
Em @JoinColumn
- name indica o nome da coluna
@Entity da tabela animal que referencia a
@Table(name="pessoa") pessoa
- referencedColumnName indica
public class Pessoa {
o nome da coluna de id da tabela
pessoa referenciada pelo animal

@OneToMany
@JoinColumn(name="pessoa_id",referencedColumnName="pessoa
_id")
private List<Animal> animais;
...
}

10
Universidade Positivo
Many To Many Muitos para Muitos

Anotao @ManyToMany
Ex.: Um animal pode possuir vrias alergias, e uma alergia
pode estar associada a vrios animais.

11
Universidade Positivo
Many To Many Muitos para Muitos

@Entity
@Table(name="ANIMAL")
public class Animal {
...
@ManyToMany
@JoinTable(name="alergiaanimal",
joinColumns={@JoinColumn(name="animal_id",
referencedColumnName="animal_id")},
inverseJoinColumns={@JoinColumn
(name="alergia_id",referencedColumnName="alergia_id")})
private List<Alergia> alergias;

12
Universidade Positivo
Many To Many Muitos para Muitos

@JoinTable define o nome da tabela que faz a ligao (no


exemplo a tabela alergiaAnimal)
joinColumns={@JoinColumn(name="nome_fk_tab_ligacao",
referencedColumnName=" nome_chave_tab_original ")}
define quais so as colunas da tabela que fazem a ligao
entre a tabela sendo mapeada (animal) e a tabela de
ligao (alergiaanimal)
inverseJoinColumns
O mesmo que joinColumns, mas para as chaves da tabela
sendo relacionada (alergia)

13
Universidade Positivo
Relacionamentos Bidirecionais

Em muitas ocasies queremos acessar as entidades de


ambos os lados dos relacionamentos. Ex.:
Ao acessar uma pessoa, queremos ter acesso a sua lista
de animais.
Ao acessar um animal, queremos ter acesso ao seu dono
Nos relacionamentos bidirecionais, temos uma classe que a
dona do relacionamento, a possui as informaes sobre as
chaves estrangeiras no banco de dados
Geralmente o ManyToOne o dono do relacionamento
Na classe que no dona do relacionamento, deve-se utilizar
o atributo mappedBy, que deve conter o nome do atributo
que expressa o mesmo relacionamento na outra entidade.

14
Universidade Positivo
Relacionamentos Bidirecionais

- No exemplo a classe animal


public class Animal {
a dona do relacionamento com
pessoa.
@ManyToOne - A classe pessoa especifica
@JoinColumn(name = "pessoa_id") que a classe animal se
private Pessoa dono; relaciona com a classe pessoa
atravs do atributo dono, j
... mapeado no banco de dados.
}
public class Pessoa {
...
@OneToMany(mappedBy="dono")
private List<Animal> animais;
...
}

15
Universidade Positivo
Mapeando Entidades com chaves compostas com
@EmbeddedId

No caso de chaves compostas, deve-se criar uma classe


separada que deve conter somente as chaves primrias da
tabela
Ex.: Considere a tabela vacinaanimal, que possui 3
atributos chave (dos quais 2 tambm so chave
estrangeira) e um atributo que no chave.

16
Universidade Positivo
Mapeando Entidades com chaves compostas com
@EmbeddedId

Cria-se uma classe para representar o ID que deve ser


marcada como @Embeddable

@Embeddable
public class VacinaAnimalPK implements Serializable{

private static final long serialVersionUID = 1L;

@Column(name="vacina_id")
private Integer idVacina;
@Column(name="animal_id")
private Integer idAnimal;
private Date dataVacinacao;
...
}

17
Universidade Positivo
Mapeando Entidades com chaves compostas com
@EmbeddedId

A classe que representa o ID deve conter somente atributos


nativos
A especificao do JPA 2.0 diz que somente atributos
nativos devem ser colocados nas classes de primary key.
Por essa razo a classe representa idVacina e idAnimal
como inteiros e no como as classes vacina e animal

18
Universidade Positivo
Mapeando Entidades com chaves compostas com
@EmbeddedId

Cria-se ento a classe VacinaAnimal

@Entity
@Table(name="vacinaanimal")
public class VacinaAnimal {

@EmbeddedId
private VacinaAnimalPK id;
...
}

19
Universidade Positivo
Mapeando Entidades com chaves compostas com
@EmbeddedId

O bean criado normalmente


Porm o atributo que representa o id composto (classe
VacinaAnimalPK) marcado como @EmbeddedId.
Esse mtodo no ir funcionar a menos que a classe que
representa o ID implemente os mtodos hashcode e equals
de maneira correta.

20
Universidade Positivo
Mapeando Entidades com chaves compostas com
@EmbeddedId

Contornando o problema da classe que representa a PK


aceitar somente atributos nativos
Criar os relacionamentos na classe que representa a
tabela. Ex.:
@Entity
@Table(name="vacinaanimal")
public class VacinaAnimal {

@EmbeddedId
private VacinaAnimalPK id;

@ManyToOne
@JoinColumn(name = "vacina_id", insertable = false, updatable = false)
private Vacina vacina;
...
}

21
Universidade Positivo
Mapeando Entidades com chaves compostas com
@EmbeddedId

No caso do exemplo temos que marcar que:


A entidade relacionada no inservel caso ela ainda no
exista no banco
insertable = false
No possvel atualizar o relacionamento (trocar uma vacina
por outra no relacionamento)
updatable=false
Outra opo que nos levaria ao mesmo resultado seria
utilizar @MapsId(nomeAtribudoNaClasseEmbeaddable)
Quais os problemas que podem surgir com isso?

22
Universidade Positivo
Mapeando Entidades com chaves compostas com
@EmbeddedId

No caso do exemplo temos que marcar que:


A entidade relacionada no inservel caso ela ainda no exista no
banco
insertable = false
No possvel atualizar o relacionamento (trocar uma vacina por outra
no relacionamento)
updatable=false
Quais os problemas que podem surgir com isso?
Ao fazer vacinaAnimal.setVacina(...) o id.vacina_id no ser trocado
automaticamente
Modificar o set
E se relacionarmos uma vacina a um vacinaAnimal, e trocarmos o id
da vacina?
Vacina.setId(...)
Devemos atualizar o vacinaId de vacinaAnimal manualmente
23
Universidade Positivo
Eager vs. Lazy

Por padro o hibernate ir carregar as entidades mapeadas


por collections (listas, sets, ...) de forma lazy.
O atributo fech=tipo_do_fetch do relacionamento permite
modificar esse comportamento.
Carga eager pode aumentar o desempenho evitando o
problema do N+1
Deve-se avaliar se a lista sempre utilizada para valer a
pena a carga antecipada dos itens
@ManyToMany(fetch=FetchType.EAGER)
@JoinTable(name="alergiaanimal",
joinColumns={@JoinColumn(name="animal_id",
referencedColumnName="animal_id")},
inverseJoinColumns={@JoinColumn(name="alergia_id",
referencedColumnName="alergia_id")})
private List<Alergia> alergias;

24
Universidade Positivo
Eager em Mltiplas Listas

Se tivermos duas listas marcadas como eager em uma nica


classe teremos problemas
Quais?
Por que isso ocorre?

25
Universidade Positivo
Eager em Mltiplas Listas

Se tivermos duas listas marcadas como eager em uma nica


classe teremos problemas
Quais?
Os objetos podem se repetir na lista, ou o JPA pode
lanar uma exceo
org.hibernate.loader.MultipleBagFetchException: cannot simultaneously
fetch multiple bags
Por que isso ocorre?
O banco de dados gera um produto cartesiano do dados

26
Universidade Positivo
Eager em Mltiplas Listas

Possveis solues
Apenas uma das listas deve ser eager
Utilziar sets ao invs de listas
Utilizar anotaes especficas do Hibernate
Exemplo: @Fetch(value = FetchMode.SUBSELECT)

27
Universidade Positivo

Anda mungkin juga menyukai