quinta-feira, 6 de março de 2008

Mapeamentos do Hibernate

Atualmente, mesmo usando o GRAILS, tenho preferido utilizar classes de domínio escritas em JAVA e JPA annotations para definição de como será realizada a persistencia.

Sempre que tenho que fazer alguma coisa nova, ou mesmo alguma coisa que já tenho feito acabo tendo dúvidas e isso me faz ir para o site do hibernate e ficar procurando lá as coisas.

Vou fazer um resumo aqui das tags que tenho usado e as referencias para o site do hibernate. Provavelmente eu serei o usuário que mais consultará este post.. rs.

Lembre-se: No caso de dúvidas, sempre consulte o site do hibernate.

Vamos lá...

Definição de uma entidade... [hibernate]
@Entity
@Table(name="USUARIOS")
class User { ...

Definição da chave primária (PK)... [hibernate]
@Id
@GeneratedValue
@Column(name = "ID_USUARIO")
Long id;

Definição de campo String... (para campo numérico deve remover o atributo length) [hibernate]
@Column(name="NOME_USUARIO", nullable=false, length=50)

String name;

Definição de campo que não será mapeado para o banco (transiente) [hibernate]
@Transient
int

RELACIONAMENTOS - Aqui acho um pouco mais complicado...

UM-PARA-UM
[hibernate]

A -> B - Relacionamento unidirecional

Existem 3 soluções resolver o mapeamento físico (veja link hibernate)... mas escolhi um aqui.
Escolhi a classe A para possuir a FK para a classe B.

Na classe A colocamos

class ClassA {
...
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="FK_B", nullable=false)
private ClasseB classeB; // referencia para a classe B
...
}

A <-> B - Relacionamento bidirecional

class ClassA {
...
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="FK_B", nullable=false)
private ClasseB classeB;
...
}


class ClassB {
...
@OneToOne(mappedBy="classB") // classB é o atributo na classe A
private ClassA classA;
...
}

MUITOS-PARA-UM - [hibernate]

*A -> B - Relacionamento unidirecional
Um objeto da classe B pode pertencer referenciado por mais de um objeto da classe A

class ClassA {
...
@ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE} )
@JoinColumn(name="FK_B", nullable=false)
private ClassB classB;
...
}

UM-PARA-MUITOS - [hibernate]

A -> * B - Relacionamento unidirecional

Neste exemplo a ClassA é a "proprietária" do relacionamento

class ClassA {
...
@OneToMany
List classBList = new ArrayList();
...
}

A <-> * B - Relacionamento bidirecional

Estou aqui escolhendo que a ClassB é a responsável pelo relacionamento

class ClassA {
...
@OneToMany(mappedBy="classA",cascade = CascadeType.ALL) // classA é o atributo na classe B
List classBList = new ArrayList();
...
}

class ClassB {
....
@ManyToOne
@JoinColumn(name="PK_A")
private ClassA classA;
...
}

O mesmo exemplo agora tendo a ClassA como "proprietária" do relacionamento.

class ClassA {
...
@OneToMany
@JoinColumn(name="PK_A") //we need to duplicate the physical information
List classBList = new ArrayList();
...
}

class ClassB {
....
@ManyToOne
@JoinColumn(name="PK_A", insertable=false, updatable=false)
private ClassA classA;
...
}

Exemplos acima corrigidos de acordo com comentários do Felipe Nascimento (valeu Felipe)


MUITOS-PARA-MUITOS [hibernate] - veja seção 2.2.5.3.3.

Neste exemplo de referencia foi escolhida a ClassA como a "proprietária" do relacionamento.

class ClassA {
...
@ManyToMany(
targetEntity=packageA.ClassB.class,
cascade={CascadeType.PERSIST, CascadeType.MERGE}
)
@JoinTable(
name="TabelaA_TabelaB",
joinColumns={@JoinColumn(name="FK_A")},
inverseJoinColumns={@JoinColumn(name="FK_B")}
)
private List classAList = new ArrayList();
...
}

class ClassB {
...
@ManyToMany(
cascade={CascadeType.PERSIST, CascadeType.MERGE},
mappedBy="classAList"
targetEntity=ClassA.class
)
private List classBList = new ArrayList();
...
}

3 comentários:

Gilber Albino de Souza disse...

muito bom Gilvan!
Parabéns pelo artigo. Será de grande utilidade para consultas futuras

abs,

Felipe Nascimento disse...

Legal Gilvan, parabéns!

Fiquei na dúvida no exemplo 'O mesmo exemplo agora tendo a ClassA como "proprietária" do relacionamento.'

Na ClassA, vc colocou
@OneToMany
@JoinColumn(name="PK_B")

Só que no primeiro exemplo de OneToMany bidirecional, vc tinha usado PK_A. Neste segundo exemplo, nao seria PK_A também, ao invés de PK_B? Esta não é a chave estrangeira usada na entidade B?

Abcs
Felipe

Gilvan Albino de Souza disse...

Oi Felipe,

Eu dei bobeira, o certo é PK_A mesmo.
Obrigado pela revisão.