Escolar Documentos
Profissional Documentos
Cultura Documentos
Anotaes
Por: Raphaela Galhardo Fernandes
Gleydson de A. Ferreira Lima
______________________________
raphaela@j2eebrasil.com.br,
gleydson@j2eebrasil.com.br
JavaRN - http://javarn.dev.java.net
J2EEBrasil - http://www.j2eebrasil.com.br
Sumrio
HIBERNATE COM ANOTAES .........................................................................................................1
1.
2.
3.
4.
ARQUITETURA .........................................................................................................................8
4.1
4.2
4.3
4.4
4.5
5.
CLASSES PERSISTENTES............................................................................................................10
5.1
5.2
6.
7.
8.
9.
10.
CONFIGURANDO O HIBERNATE..........................................................................................23
11.
12.
13.
ASSOCIAES ...........................................................................................................................32
15.
COLEES..................................................................................................................................56
15.1
15.2
15.3
15.4
16.
16.1
SET ..............................................................................................................................................57
LIST .............................................................................................................................................59
MAP ............................................................................................................................................61
BAG .............................................................................................................................................62
HERANA....................................................................................................................................64
TABELA POR CLASSE CONCRETA ................................................................................................66
16.2
16.3
17.
17.1
17.2
17.3
17.4
17.5
17.6
17.7
17.8
17.9
18.
18.1
18.2
19.
19.1
19.2
19.3
Na prtica, esse modelo de dados no foi utilizado em grandes aplicaes, visto que
elas tinham um volume de dados muito grande e esse modelo era ineficiente em
termos de tempo de resposta, pois ao contrrio dos bancos de dados relacionais,
eles no tinham um modelo matemtico que facilitasse as suas operaes de
persistncias.
Ento a soluo foi usar os BDR e desenvolver ferramentas para que o seu
uso seja facilitado. Uma dessas ferramentas o framework Hibernate que usa o
conceito de mapeamento objeto relacional (MOR).
As
subsees
seguintes
apresentam
os
conceitos
relacionados
ao
3. Introduo ao Hibernate
O Hibernate um framework de mapeamento objeto relacional para
aplicaes Java, ou seja, uma ferramenta para mapear classes Java em tabelas
do banco de dados e vice-versa. bastante poderoso e d suporte ao
mapeamento de associaes entre objetos, herana, polimorfismo, composio e
colees.
O Hibernate no apresenta apenas a funo de realizar o mapeamento
objeto relacional. Tambm disponibiliza um poderoso mecanismo de consulta de
dados, permitindo uma reduo considervel no tempo de desenvolvimento da
aplicao.
4. Arquitetura
A arquitetura do Hibernate formada basicamente por um conjunto de
interfaces. A Figura 4 apresenta as interfaces mais importantes nas camadas de
negcio e persistncia. A camada de negcio aparece acima da camada de
persistncia por atuar como uma cliente da camada de persistncia. Vale salientar
que algumas aplicaes podem no ter a separao clara entre as camadas de
negcio e de persistncia.
De acordo com a Figura 4, as interfaces so classificadas como:
Interfaces
que
mapeamento
permitem
do
Hibernate:
extenso
das
UserType,
funcionalidades
de
CompositeUserType,
IdentifierGenerator.
O Hibernate tambm interage com APIs j existentes do Java: JTA, JNDI e
JDBC.
do
Hibernate.
Com
ele,
define-se
diversas
configuraes
do
5. Classes Persistentes
As classes persistentes de uma aplicao so aquelas que implementam as
entidades de domnio de negcio. O Hibernate trabalha associando cada tabela do
banco de dados a um POJO (Plain Old Java Object). POJOs so objetos Java que
seguem a estrutura de JavaBeans (construtor padro sem argumentos, e mtodos
getters e setters para seus atributos). A Listagem 1 apresenta a classe Pessoa
representando uma classe POJO.
10
package br.com.jeebrasil.dominio.Pessoa;
public Pessoa(){}
11
Consideraes:
possuam
um
identificador
que
eles
sejam
12
nica;
Constante.
Uma nica tabela pode ter vrias colunas ou combinaes de colunas que
satisfazem essas propriedades. Se a tabela possui um nico atributo que a
identifique, ele por definio a sua chave primria. Se possuir vrias chaves
candidatas, uma deve ser escolhida para representar a chave primria e as demais
serem definidas como chaves nicas.
Muitas aplicaes utilizam como chaves primrias chaves naturais, ou seja,
que tm significados de negcio. Por exemplo, o atributo cpf da tabela Pessoa
(associada classe Pessoa). Essa estratgia pode no ser muito boa em longo
prazo, j que uma chave primria adequada deve ser constante, nica e no nula.
Dessa forma, se for desejado que a chave primria da tabela Pessoa seja uma
outra ao invs do cpf, podem surgir problemas j que provavelmente o cpf deve
ser referenciado em outras tabelas. Um problema que poderia acontecer seria a
remoo do cpf da tabela.
O Hibernate apresenta vrios mecanismos internos para a gerao de
chaves primrias. Veja a Tabela 1.
Descrio
Identity
Sequence
Increment
Hilo
uudi.hex
13
Objetos
Persistentes:
so objetos
que suas
instncias
esto
Objetos
detached:
so
objetos
que
tiveram
suas
instncias
finalizao
de
sesso.
So
objetos
em
um
estado
14
De acordo com a figura acima, inicialmente, o objeto pode ser criado e ter o
estado transiente ou persistente. Um objeto em estado transiente se torna
persistente se for criado ou atualizado no banco de dados. J um objeto em estado
persistente, pode retornar ao estado transiente se for apagado do banco de dados.
Tambm pode passar ao estado detached, se, por exemplo, a sesso com o banco
de dados por fechada. Um objeto no estado detached pode voltar ao estado
persistente se, por exemplo, for atualizado no banco de dados. Tanto do estado
detached quanto do estado transiente o objeto pode ser coletado para destruio.
de
sua
aplicao.
persistence.jar
tambm
Os
arquivos
devem
hibernate-annotations.jar
referenciados
no
classpath
15
e lib/ejb3da
aplicao,
16
@TesteAnotacao(Definindo valor)
public void metodoTeste{
...
}
Listagem 5 Exemplo ilustrativo para o uso de um tipo de. Anotao
No caso caso em que o tipo da anotao ser definido com mais de um
elemento, como mostrado na Listagem 6, na hora em que a anotao for usada,
para atribuir valores para seus elementos preciso pass-los tambm entre
parnteses, porm definindo o nome do elemento e o seu valor, como exemplo
ilustrado na Listagem 7.
@Override: indica que o mtodo que possui esta anotao deve ter a sua
implementao sobrescrevendo a de sua superclasse. Se o mtodo anotado
no tiver implementao, o compilador gerar um erro;
17
18
//Atributos da classe
private int id;
private int matricula;
private String nome;
private long cpf;
//Construtor padro
public Aluno(){}
19
20
do
pacote
javax.persistence.*,
como
do
pacote
org.hibernate.annotations.*.
Todas as classes persistentes mapeadas com anotaes so declaradas
usando a anotao @Entity, aplicada em nvel de classes, como mostrado na
Listagem 10. Observa-se que com o uso de anotaes, no h mais a necessidade
de se utilizar arquivos de mapeamento XML adicionais.
Quando o nome da classe diferente do nome da tabela para a qual
mapeada necessrio informar na anotao @Table qual o nome da tabela,
usando o atributo name. No caso do mapeamento da classe Aluno, no havia a
necessidade de se informar o nome da tabela, pois ela e a classe possuem o
mesmo nome. Como a tabela pertence a um esquema do banco de dados
(anotaes), no mapeamento da classe, tambm necessrio informar em que
esquema a tabela mapeada se encontra, utilizando o atributo schema da anotao
@Table.
No
caso,
linha
do
cdigo
fonte
@Table(name="aluno",
mecanismo
do
Hibernate
que
gere
automaticamente.
anotao
hora de persistir uma linha na tabela aluno, o Hibernate vai pegar como valor para
a chave primria o prximo valor disponvel por uma seqncia padro chamada
hibernate_sequence. Deve-se salientar que o programador dever criar uma
seqncia com este nome na base de dados. Ainda em relao ao identificador,
como o nome da coluna mapeada diferente do nome do atributo, necessrio
utilizar a anotao @Column informando o nome da coluna, atravs do atributo
name. Neste exemplo, o nome da coluna mapeada para o identificador
id_aluno, mapeada da seguinte forma: @Column(name="id_aluno").
Observa-se que nos demais atributos da classe no h nenhuma anotao
de mapeamento. Isso pode ser feito quando o nome do atributo igual ao nome da
coluna da tabela mapeada, de forma que no h a necessidade de mapeamento
explcito.
21
package br.com.jeebrasil.hibernate.anotacoes.dominio;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
com
anotacoes,
deve-se
22
realizar
algumas
configuraes
do
Instanciar
um
objeto
de
configurao
Dialeto.
<hibernate-configuration>
<session-factory>
23
<property name="connection.username">postgres</property>
<property name="connection.password">postgres</property>
<property name="connection.pool_size">10</property>
</session-factory>
</hibernate-configuration>
Listagem 11 - Arquivo de Configurao hibernate.cfg.xml
hibernate.connection.isolation:
define
nvel
de
isolamento.
Parmetro opcional;
24
11.
objeto Session pode ser considerado como uma sesso de comunicao com o
banco de dados atravs de uma conexo JDBC.
O cdigo fonte exibido na Listagem 12 mostra a criao e persistncia de um
objeto do tipo Aluno. Inicialmente alguns imports de objetos so feitos para se
utilizar a persistncia com o Hibernate. Em seguida, dentro do mtodo main, criase
um
objeto
que
conter
as
configuraes
definidas
do
arquivo
25
save do objeto Session. Com isso, uma linha na tabela aluno adicionada de
acordo com os valores definidos no objeto. Assim, a persistncia desejada
realizada e deve-se liberar tanto a transao quanto a sesso com o Hibernate.
package br.com.jeebrasil.hibernate.anotacoes.testes;
//Imports de elementos para o uso do Hibernate funcionar
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
//Import da classe de domnio persistida
import br.com.jeebrasil.hibernate.anotacoes.dominio.Aluno;
26
A Tabela 3 apresenta alguns dos mtodos que podem ser invocados a partir
do objeto Session.
Tabela 3 - Mtodos invocados a partir do objeto Session
save(Object)
saveOrUpdate(Object)
delete(Object)
27
//...
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
tx.commit();
session.close();
//...
Listagem 14 - Exemplo de Busca e Atualizao de um Objeto Aluno
//...
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
tx.commit();
session.close();
//...
Listagem 15 - Exemplo de Remoo de Objeto Aluno
28
29
classe
Cliente,
ilustrada
pela
Listagem
19,
possui
exemplos
de
package br.com.jeebrasil.hibernate.anotacoes.dominio;
import javax.persistence.*;
@Entity
@Table(name="cliente", schema="anotacoes")
public class Cliente {
@Transient
private int temporaria;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name="id_cliente")
private int id;
@Column(unique=true, nullable=false,
insertable=true, updatable=true)
private long cpf;
@Column(nullable=false, length=40,
insertable=true, updatable=true)
private String nome;
@Column(length=100)
private String endereco;
@Column(name="total_compras", precision=2)
private double totalCompras;
30
@Column(name="data_nascimento", nullable=false)
@Temporal(TemporalType.DATE)
private Date dataNascimento;
@Column(name="data_cadastro")
@Temporal(TemporalType.TIMESTAMP)
private Date dataCadastro;
public Cliente(){}
31
13. Associaes
O termo associao utilizado para se referir aos relacionamentos entre as
entidades. Os relacionamentos n-para-n, n-para-1 e 1-para-n so os mais comuns
entre as entidades de um banco de dados.
Nas sees seguintes, sero apresentados exemplos de mapeamentos com
anotaes para cada um dos tipos de relacionamentos citados.
32
package br.com.jeebrasil.hibernate.anotacoes.dominio;
import java.util.Collection;
import javax.persistence.*;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
@Entity @Table(schema="anotacoes")
public class Universidade {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name="id_universidade")
private int id;
private String nome;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
@Entity @Table(schema="anotacoes")
public class Centro {
33
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name="id_universidade",
insertable=true, updatable=true)
@Fetch(FetchMode.JOIN)
@Cascade(CascadeType.SAVE_UPDATE)
private Universidade universidade;
//...
}
Listagem 21 - Classe de Domnio: Centro
ON
COLUMN
anotacoes.universidade.id_universidade
IS
'Identificador da tabela';
COMMENT
ON
COLUMN
anotacoes.universidade.nome
IS
'Nome
da
universidade';
Listagem 22 Script para a Criao da Tabela universidade
34
ON
COLUMN
anotacoes.centro.id_centro
IS
'Identificador
da
tabela';
COMMENT ON COLUMN anotacoes.centro.nome IS 'Nome do centro';
COMMENT ON COLUMN anotacoes.centro.id_universidade IS 'Identificador
da universidade a que o centro pertence';
Listagem 23 Script para a Criao da Tabela centro
da
35
CascadeType.PERSIST:
os
objetos
associados
vo
ser
inseridos
atualizados
automaticamente quando
objeto "pai"
for
inserido ou
atualizado;
CascadeType.REMOVE: os objetos associados ao objeto "pai" vo ser
atributo
nome
so
associados
ao
objeto
universidade,
que
posteriormente persistido.
//...
Universidade univ = new Universidade();
univ.setNome("Universidade Federal do Rio Grande do Norte");
univ.setCentros(new HashSet<Centro>());
36
univ.getCentros().add(centro1);
univ.getCentros().add(centro2);
session.save(univ);
//...
Listagem 24 Exemplo de Persistncia OneToMany. Efeito da anotao
@Cascade(CascadeType.ALL)
Listagem
25
apresenta
resultado
da
persistncia
do
objeto
37
//...
Session session = sf.openSession();
session.close();
//...
Listagem 26 Consulta para Ilustrar o Uso do Atributo fecth
38
//...
Session session = sf.openSession();
session.close();
//...
Listagem 29 Consulta para Ilustrar o Uso do Atributo
fecth=FetchType.LAZY
39
//...
@Entity @Table(schema="anotacoes")
public class Centro {
//...
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name="id_universidade",
insertable=true, updatable=true)
@Fetch(FetchMode.JOIN)
@Cascade(CascadeType.SAVE_UPDATE)
private Universidade universidade;
//...
}
Listagem 31 - Mapeamento ManyToOne
40
adicional para
carregar
mapeamentos
colees
adicionais.
No
permitido
para
ManyToOne.
//...
Session session = sf.openSession();
41
42
43
package br.com.jeebrasil.hibernate.anotacoes.dominio;
44
import java.util.Collection;
import javax.persistence.*;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
@Entity
@Table(name="departamento", schema="anotacoes")
public class Departamento {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name="id_departamento")
private int id;
@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name="id_centro", insertable=true, updatable=true)
@Cascade(CascadeType.SAVE_UPDATE)
private Centro centro;
@ManyToMany(fetch=FetchType.LAZY)
@JoinTable(name="departamento_curso", schema="anotacoes",
joinColumns=@JoinColumn(name="id_departamento"),
inverseJoinColumns=@JoinColumn(name="id_curso"))
private Collection<Curso> cursos;
}
Listagem 38 - Classe de Domnio: Departamento
45
package br.com.jeebrasil.hibernate.anotacoes.dominio;
import java.util.Collection;
import javax.persistence.*;
@Entity
@Table(name="curso", schema="anotacoes")
public class Curso {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name="id_curso")
private int id;
@Column(unique=true, nullable=false,
insertable=true, updatable=true)
private int codigo;
@Column(nullable=false, insertable=true,
updatable=true, length=6)
private String nome;
@Column(nullable=false, insertable=true, updatable=true)
private String sigla;
@ManyToMany(fetch=FetchType.LAZY)
@JoinTable(name="departamento_curso", schema="anotacoes",
joinColumns={@JoinColumn(name="id_curso")},
inverseJoinColumns={@JoinColumn(name="id_departamento")})
private Collection<Departamento> departamentos;
//...
tx.begin();
46
//Persiste departamento
session.save(depart);
tx.commit();
//...
Listagem 40 Exemplo com Mapeamento Usado a Anotao
@ManyToMany: Persistncia de Departamento
O SQL gerado apresentado na Listagem 41. Observa-se que SELECTs na
tabela centro, na tabela curso e na seqncia hibernate_seq so realizados.
Depois, feito e um INSERT na tabela departamento e em seguida, uma incluso
de
linha
na
tabela
de
relacionamento
departamento_curso,
devido
47
ao
Imagine que seria necessrio guardar a data em que foi feita a associao
entre um determinado curso e um determinado departamento, ou seja, necessrio
ter um novo atributo na tabela departamento_curso. Dessa forma, esta tabela
no
seria
formada
apenas
pelos
identificadores
das
tabelas
curso
departamento, mas sim tambm pela data. Para essa situao, os mapeamentos
dos relacionamentos com a anotao @ManyToMany nas classes Departamento
e Curso no resolveriam o problema. Ento, deve-se criar uma nova classe
DepartamentoCurso, como mostrado no diagrama da Figura 11, formada por
uma chave primria composta por dois elementos e por um atributo que representa
a data.
48
para
Adio
da
Coluna
data
na
Tabela
package br.com.jeebrasil.hibernate.anotacoes.dominio;
import java.util.Date;
import javax.persistence.*;
@Entity
@Table(name="departamento_curso", schema="anotacoes")
public class DepartamentoCurso {
@EmbeddedId
private DepartamentoCursoPK chaveComposta;
@Column(name="data")
@Temporal(TemporalType.DATE)
private Date data;
13.4.1 Composite-id
Para mapear uma chave composta, deve-se criar uma classe que a
49
represente. Esta classe deve ser mapeada com a anotao @Embeddable, como
mostrado
na
Listagem
44
no
mapeamento
da
chave
composta
package br.com.jeebrasil.hibernate.anotacoes.dominio;
import java.io.Serializable;
import javax.persistence.*;
@Embeddable
public class DepartamentoCursoPK implements Serializable{
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name="id_departamento")
private Departamento departamento;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "id_curso")
private Curso curso;
//Mtodos getters e setters
}
Listagem 44 - Classe de Domnio: DepartamentoCursoPK
//...
tx.begin();
50
session.save(dc);
tx.commit();
//...
Listagem 45 Exemplo com Mapeamento de Chave Composta
51
package br.com.jeebrasil.hibernate.anotacoes.dominio;
import javax.persistence.*;
@Entity
@Table(schema="anotacoes")
public class Endereco {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name="id_endereco")
private int id;
52
@OneToOne
@JoinColumn(name="id_universidade")
private Universidade universidade;
53
utilizada
anotao
@Cascade
passando
como
argumento
//...
@OneToOne(mappedBy="universidade")
@Cascade(CascadeType.ALL)
private Endereco endereco;
//...
Listagem 49 Incluso de Atributo endereco na classe Universidade
54
//...
tx.begin();
Endereco endereco = new Endereco();
endereco.setRua("Av. Senador Salgado Filho");
endereco.setNumero(1034);
endereco.setBairro("Lagoa Nova");
endereco.setCidade("Natal");
endereco.setUf("RN");
endereco.setCep(59067710);
Universidade universidade = new Universidade();
universidade.setNome("Universidade Teste");
endereco.setUniversidade(universidade);
universidade.setEndereco(endereco);
session.save(universidade);
tx.commit();
//...
Listagem 50 Exemplo para Ilustrar Mapeamento 1-1
55
do
valor
do
atributo
GenerationType.SEQUENCE)
ser
atravs
nome
de
da
seqncias
mesma
(strategy
(generator
"SEQ_CLIENTE").
package br.com.jeebrasil.hibernate.anotacoes.dominio;
import javax.persistence.*;
@Entity
@Table(name="cliente", schema="anotacoes")
public class Cliente {
@Id
@SequenceGenerator(name = "SEQ_CLIENTE",
sequenceName = " anotacoes.cliente_seq")
@GeneratedValue(
strategy = GenerationType.SEQUENCE,
generator = "SEQ_CLIENTE")
@Column(name="id_cliente")
private int id;
//...
}
Listagem 52 Mapeamento de Chave Primria Usando Seqncia Prpria
15. Colees
O
mapeamento
de
colees
foi
apresentado
no
contexto
dos
56
15.1
Set
Para exemplificar o mapeamento de um Set de tipos primitivos considere o
name=aluno_telefone
schema=anotacoes.
Na
anotao
atributo
joinColumns
que
recebe
como
valor
anotao
//...
import org.hibernate.annotations.CollectionOfElements;
//...
@CollectionOfElements
@JoinTable(name = "aluno_telefone", schema = "anotacoes",
joinColumns = @JoinColumn(name = "id_aluno"))
@Column(name = "telefone")
private Set<String> telefones;
//...
Listagem 53 Atributo telefones Inserido na Classe Aluno (Set)
57
//...
tx.begin();
Aluno aluno = new Aluno();
aluno.setMatricula(12846822);
aluno.setNome("Joo Maria Costa Neto");
aluno.setTelefones(new HashSet<String>());
aluno.getTelefones().add("32222529");
aluno.getTelefones().add("32152899");
session.save(aluno);
tx.commit();
//...
Listagem 55 - Exemplo de Mapeamento de Set
58
15.2 List
//...
import org.hibernate.annotations.CollectionOfElements;
import org.hibernate.annotations.IndexColumn;
//...
@CollectionOfElements
@JoinTable(name = "aluno_telefone", schema = "anotacoes",
59
Mapeando
coleo
como
um
List,
chave
primria
da
tabela
//...
tx.begin();
aluno.setTelefones(new ArrayList<String>());
aluno.getTelefones().add("32222529");
session.save(aluno);
tx.commit();
//...
Listagem 58 - Exemplo de Mapeamento de List
60
15.3 Map
Maps associam chaves aos valores e no podem conter chaves duplicadas.
Eles diferem de Sets no fato de que contm chaves e valores, ao passo que os
Sets contm somente a chave.
O mapeamento de um Map semelhante ao de um List, onde o ndice de
posio passa a ser a chave. Veja a Figura 14. A Listagem 60 apresenta a coleo
de telefones sendo mapeada como um Map. A chave primria da tabela
aluno_telefone passa a ser as colunas id_aluno e chave, tambm permitindo a
presena de telefones duplicados na coleo. A diferena dos outros mapeamentos
que a chave mapeada atravs da anotao @MapKey(columns =
{@Column(name = "chave")}).
//...
import org.hibernate.annotations.CollectionOfElements;
import org.hibernate.annotations.MapKey;
//...
@CollectionOfElements
@JoinTable(name = "aluno_telefone", schema = "anotacoes",
joinColumns = @JoinColumn(name = "id_aluno"))
@Column(name = "telefone")
@MapKey(columns = {@Column(name = "chave")})
private Map<String, String> telefones;
//...
Listagem 60 Atributo telefones Inserido na Classe Aluno (Map)
//...
tx.begin();
61
session.save(aluno);
tx.commit();
//...
Listagem 61 - Exemplo de Mapeamento de Map
15.4 Bag
Um Bag consiste em uma coleo desordenada que permite elementos
duplicados. Em Java no h implementao de um Bag, contudo o Hibernate
fornece um mecanismo de que um List em Java simule o comportamento de um
Bag. Pela definio de um List, uma lista uma coleo ordenada, contudo o
Hibernate no preserva a ordenao quando um List persistido com a semntica
de um Bag. Para usar o Bag, a coleo de telefones deve ser definida com o tipo
List. Um exemplo de mapeamento de um Bag pode ser visto na Figura 16 e na
Listagem 63.
62
posio
do
elemento
na
tabela,
assim
ao
invs
da
anotao
exemplo,
chave
substituta
representada
pela
coluna
//...
import org.hibernate.annotations.CollectionId;
import org.hibernate.annotations.CollectionOfElements;
import org.hibernate.annotations.Type;
//...
@CollectionOfElements
@JoinTable( name = "aluno_telefone", schema = "anotacoes",
joinColumns = @JoinColumn(name = "id_aluno"))
@Column(name = "telefone")
@SequenceGenerator( name = "SEQ_HIBERNATE",
sequenceName = "hibernate_sequence")
@CollectionId(columns = @Column (name = "id_aluno_telefone"),
generator = "SEQ_HIBERNATE",
63
16. Herana
O Hibernate fornece vrios mecanismos de se realizar o mapeamento de
uma relao de herana:
64
Figura 17 Herana
65
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
@MappedSuperclass
public class Pessoa {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name="id_pessoa")
private int id;
private int matricula;
66
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import br.com.jeebrasil.hibernate.anotacoes.dominio.Curso;
@Entity
@Table(name="aluno", schema="anotacoes")
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Aluno extends Pessoa{
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "id_curso")
private Curso curso;
67
package br.com.jeebrasil.hibernate.anotacoes.heranca.dominio;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import br.com.jeebrasil.hibernate.anotacoes.dominio.Departamento;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "id_departamento")
private Departamento departamento;
Dessa
forma,
vrias
colunas
diferentes
de
tabelas
distintas
68
//...
tx.begin();
tx.commit();
//...
Listagem 68 Exemplo de Persistncia: Tabela Por Classe Concreta
69
recebendo
InheritanceType.SINGLE_TABLE,
atributo
strategy
infomando
que
as
com
trs
classes
valor
sero
import javax.persistence.*;
@Entity
@Table(name = "pessoa", schema = "anotacoes")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
name = "tipo_pessoa",
discriminatorType = DiscriminatorType.INTEGER
)
@DiscriminatorValue("0")
public class Pessoa {
70
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name="id_pessoa")
private int id;
private int matricula;
private String nome;
private long cpf;
package br.com.jeebrasil.hibernate.anotacoes.heranca.dominio;
import javax.persistence.*;
import br.com.jeebrasil.hibernate.anotacoes.dominio.Curso;
@Entity
@DiscriminatorValue("1")
public class Aluno extends Pessoa{
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "aluno_id_curso")
private Curso curso;
71
import javax.persistence.*;
import br.com.jeebrasil.hibernate.anotacoes.dominio.Departamento;
@Entity
@DiscriminatorValue("2")
public class Professor extends Pessoa{
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "professor_id_departamento")
private Departamento departamento;
72
//...
Listagem 73 Exemplo de Persistncia: Tabela Por Hierarquia
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
@Entity
@Table(name = "pessoa", schema = "anotacoes")
@Inheritance(strategy=InheritanceType.JOINED)
public class Pessoa {
73
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name="id_pessoa")
private int id;
private int matricula;
private String nome;
private long cpf;
//Mtodos getters e setters
//...
}
Listagem 75 Mapeamento da Classe Pessoa: Tabela Por SubClasse
Os mapeamentos das subclasses Aluno e Professor sao feitos como
mostrado na Listagem 76 e Listagem 77, respectivamente. Essas classes devem ser
mapeadas com anotao @Entity e com a anotao @PrimaryKeyJoinColumn
para definir qual coluna da tabela filha corresponde coluna chave primria na
tabela me, que devem ter o mesmo valor.
package br.com.jeebrasil.hibernate.anotacoes.heranca.dominio;
import javax.persistence.*;
import br.com.jeebrasil.hibernate.anotacoes.dominio.Curso;
@Entity
@Table(name="aluno", schema="anotacoes")
@PrimaryKeyJoinColumn(name = "id_aluno")
public class Aluno extends Pessoa{
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "id_curso")
private Curso curso;
//Mtodos getters e setters
//...
}
Listagem 76 Mapeamento da Classe Aluno: Tabela Por SubClasse
74
package br.com.jeebrasil.hibernate.anotacoes.heranca.dominio;
import javax.persistence.*;
import br.com.jeebrasil.hibernate.anotacoes.dominio.Departamento;
@Entity
@Table(name="professor", schema="anotacoes")
@PrimaryKeyJoinColumn(name = "id_professor")
public class Professor extends Pessoa{
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "id_departamento")
private Departamento departamento;
//Mtodos getters e setters
//...
}
Listagem 77 Mapeamento da Classe Professor: Tabela Por SubClasse
75
17. Transaes
Uma transao uma unidade de execuo indivisvel (ou atmica). Isso
significa
dizer
que
todas
as
etapas
pertencentes
uma
transao
so
76
rollback.
Quando a transao sofre commit, todas as modificaes nos dados
realizadas pelas operaes presentes na transao so salvas. Quando a transao
sofre rollback, todas as modificaes nos dados realizadas pelas operaes
presentes na transao so desfeitas.
Para que um banco de dados garanta a integridade dos seus dados deve
possuir quatro caractersticas, conhecidas como ACID:
77
nenhuma
transao
deve
influenciar
nas
outras.
78
transao
encadeada
consiste
em
um
conjunto
de
sub-transaes
Join Transaction. Esse modelo permite que duas transaes sejam unidas
em uma s, de forma que todos os recursos passam a ser compartilhados.
79
ambientes
gerenciados
so
aqueles
caracterizados
pela
gerncia
de
dados
necessitem
invocar
uma
sentena
begin
Embora alguns
transaction
80
transao
iniciada
partir
da
invocao
ao
mtodo
81
try {
tx = session.beginTransaction();
acaoExecutada();
tx.commit();
} catch (Exception e) {
if (tx != null) {
try {
tx.rollback();
} catch (HibernateException he) {
//log he and rethrow e
}
}
} finally {
try {
session.close();
} catch (HibernateException he) {
throw he;
}
}
Listagem 80 - Usando a Interface Transaction do Hibernate
17.7 Flushing
82
ou
seja,
mesmo
que
estejam
acontecendo
outras
transaes
Dirty Read (Leitura Suja): uma transao tem acesso a dados modificados
por uma outra transao ainda no finalizada que ocorre concorrentemente.
Isso pode causar problema, pois pode ocorrer um erro dentro da transao
que est modificando os dados e as suas alteraes serem desfeitas antes
de confirmadas, ento possvel que a transao que acessa os dados j
modificados esteja trabalhando se baseando em dados incorretos.
83
Dirty Read
Nonrepeatable
Phanton Read
Read Uncommited
SIM
SIM
SIM
Read Commited
NO
SIM
SIM
Repeatable Read
NO
NO
SIM
Serializable
NO
NO
NO
84
1: Read Uncommited
2: Read Commited
4: Repeatable Read
8: Serializable
18. Concorrncia
Em algumas situaes pode acontecer que duas ou mais transaes que
ocorrem paralelamente leiam e atualizem o mesmo dado. Considerando que duas
transaes leiam um mesmo dado x quase que simultaneamente. Ambas as
transaes vo manipular esse mesmo dado com operaes diferentes e atualiz-lo
85
1) Transao 1 (T1) l x = 2
2) Transao 2 (T2) l x = 2
3) T1 faz x = x + 1
4) T2 faz x = x + 3
5) T1 armazena o valor de x na base de dados
6) T2 armazena o valor de x na base de dados
Listagem 82 Exemplo de Transaes Concorrentes
86
87
package br.com.jeebrasil.hibernate.anotacoes.dominio;
import javax.persistence.*;
@Entity
@Table(name = "conta_corrente", schema = "anotacoes")
public class ContaCorrente {
//Demais atributos
@Id
88
@Column(name = "id_conta_corrente")
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private double saldo;
//Outros atributos
//...
A tabela conta_corrente tambm deve ter uma coluna para onde esse
atributo versao ser mapeado, como mostrado no script de criao da tabela na
Listagem 84. De acordo com o mapeamento feito na classe ContaCorrente, toda
vez que uma determinada linha for atualizada na base de dados, a sua coluna
versao ser incrementada de uma unidade, indicando a nova verso dos dados.
89
//...
Transaction tx = session.beginTransaction();
ContaCorrente conta = new ContaCorrente();
conta.setSaldo(1000);
tx.commit();
//...
Listagem 85 Persistindo Objeto com Atributo Version Number
90
//Atualizacao
session.saveOrUpdate(conta);
tx.commit();
//...
Listagem 86 Atualizando Objeto com Atributo Version Number
package br.com.jeebrasil.hibernate.anotacoes.dominio;
import javax.persistence.*;
import java.util.Date;
@Entity
@Table(name = "conta_corrente", schema = "anotacoes")
public class ContaCorrente {
//Demais atributos
91
@Id
@Column(name = "id_conta_corrente")
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private double saldo;
//Outros atributos
//...
public Date getData(){
return data;
}
public void setData(Date Data){
this.data = data;
}
//Outros mtodos getters e setters
//...
}
Listagem 87 - Classe de Domnio: ContaCorrente. Segunda Estratgia
Locking Otimista
da
tabela,
OptimisticLockType.ALL
deve-se
da
utilizar
anotao
atributo
optimisticLock
@org.hibernate.annotations.Entity
package br.com.jeebrasil.hibernate.anotacoes.dominio;
import javax.persistence.*;
@Entity
@Table(name = "conta_corrente", schema = "anotacoes")
@org.hibernate.annotations.Entity(
optimisticLock = OptimisticLockType.ALL , dynamicUpdate = true)
92
//Atributos da classe
@Id
@Column(name = "id_conta_corrente")
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private double saldo;
//Outros atributos
//...
Dessa maneira, quando uma linha dessa tabela fosse atualizada, o SQL
equivalente gerado para a atualizao seria como o exibido na Listagem 89. Neste
exemplo, considera-se a atualizao do saldo para
R$ 1.500,00 de uma
93
Transaction tx = session.beginTransaction();
Aluno aluno = (Aluno) session.get(Aluno.class, alunoId);
aluno.setNome("Novo Nome");
tx.commit();
Listagem 90 - Exemplo de Transao sem Lock
Transaction tx = session.beginTransaction();
Aluno aluno =
(Aluno) session.get(Aluno.class, alunoId, LockMode.UPGRADE);
aluno.setNome("Novo Nome");
tx.commit();
Listagem 91 - Exemplo de Transao com Lock Pessimista:
LockMode.UPGRADE
O mtodo get do objeto Session pode receber como terceiro argumento
para implementar o lock pessimista as seguintes constantes:
O cache
94
19. Caching
O cache uma tcnica comumente utilizada para aprimorar o desempenho
da aplicao no que diz respeito ao acesso ao banco de dados. Com o cache
possvel fazer uma cpia local dos dados, evitando acesso ao banco sempre que a
aplicao precise, por exemplo, acessar dados que nunca ou raramente so
alterados e dados no crticos. O uso do cache no indicado para manipulao de
dados crticos, de dados que mudam freqentemente ou de dados que so
compartilhados com outras aplicaes legadas. Uma m escolha das classes que
tero objetos em cache pode gerar inconsistncias na base de dados.
por
uma
outra
transao
que
executa
concorrentemente,
95
96
ser
utilizada
na
aplicao.
Essa
poltica
definida
no
arquivo
EHCache
(org.hibernate.cache.EhCacheProvider):
gerenciamento de caches
usado
para
boa
OSCache
(org.hibernate.cache.OSCacheProvider):
usado
para
SwarmCache
(org.hibernate.cache.SwarmCacheProvider):
usado
para
97
JBossCache
(org.hibernate.cache.TreeCacheProvider):
usado
para
19.2
Mapeando Cache
Quando se utiliza o segundo nvel de cache, importante utilizar uma
98
99
@Entity
@Table(schema = "anotacoes")
public class Categoria {
@Id
@SequenceGenerator(allocationSize = 1, name="SEQ")
@GeneratedValue(
strategy = GenerationType.AUTO,
generator = "SEQ")
//...
100
session1.close();
System.out.println("\nFECHOU SESSION 1\n");
session2.close();
System.out.println("\nFECHOU SESSION 2");
//...
Listagem 93 Exemplificando o Uso de Cache
ABRIU SESSION 1
101
FECHOU SESSION 1
ABRIU SESSION 2
FECHOU SESSION 2
Listagem 94 - Resultado da Execuo do Cdigo Presente na Listagem 93:
Cache em Primeiro Nvel
<property name="cache.use_second_level_cache">true</property>
<property name="cache.provider_class">
net.sf.ehcache.hibernate.EhCacheProvider
</property>
Listagem 95 Configurando o Cache no Arquivo de Configurao *.cfg.xml
exemplificar,
considera-se
mapeamento
de
cache
na
classe
102
CacheConcurrencyStrategy.NONE;
CacheConcurrencyStrategy.READ_WRITE;
CacheConcurrencyStrategy.READ_ONLY;
CacheConcurrencyStrategy.TRANSACTIONAL;
CacheConcurrencyStrategy.NONSTRICT_READ_WRITE.
@Entity
@Table(schema = "anotacoes")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Categoria {
@Id
@SequenceGenerator(allocationSize = 1, name="SEQ")
@GeneratedValue(
strategy = GenerationType.AUTO,
generator = "SEQ")
103
Hibernate
considerar
configurao
padro
definida
na
tag
<defaultCache>.
<ehcache>
<diskStore path="java.io.tmpdir"/>
<cache
name="br.com.jeebrasil.hibernate.anotacoes.dominio.Categoria"
maxElementsInMemory="500"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="false"
/>
<defaultCache
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
</ehcache>
Listagem 97 Arquivo de Configurao ehcache.xml
eternal: se configurado para true, significa que o cache nunca vai expirar;
104
seja
superior
ao
definido
pela
propriedade
Para
esse
armazenamento,
propriedade
ABRIU SESSION 1
FECHOU SESSION 1
ABRIU SESSION 2
FECHOU SESSION 2
Listagem 98 - Resultado da Execuo do Cdigo Presente na Listagem 93:
Cache em Segundo Nvel
105