Escolar Documentos
Profissional Documentos
Cultura Documentos
Hibernate Reference PDF
Hibernate Reference PDF
Documentao de
Referncia Hibernate
3.5.6-Final
por Gavin King, Christian Bauer, Max Rydahl Andersen, Emmanuel Bernard, e Steve Ebersole
iii
HIBERNATE - Persistncia Rela...
iv
5.3. Mapeando uma classe mais de uma vez .......................................................... 105
5.4. Identificadores quotados do SQL ..................................................................... 106
5.5. Alternativas de Metadados .............................................................................. 106
5.5.1. Usando a marcao XDoclet. ................................................................ 106
5.5.2. Usando as anotaes JDK 5.0 .............................................................. 108
5.6. Propriedades geradas ..................................................................................... 109
5.7. Coluna de expresses de gravao e leitura .................................................... 110
5.8. Objetos de Banco de Dados Auxiliares ............................................................. 110
6. Mapeamento de coleo .......................................................................................... 113
6.1. Colees persistentes ..................................................................................... 113
6.2. Mapeamento de coleo ................................................................................. 114
6.2.1. Chaves Externas de Coleo ................................................................ 116
6.2.2. Elementos de coleo .......................................................................... 116
6.2.3. Colees indexadas ............................................................................. 116
6.2.4. Colees de valores e associaes muitos-para-muitos .......................... 117
6.2.5. Associaes um-para-muitos ................................................................. 120
6.3. Mapeamentos de coleo avanados. .............................................................. 121
6.3.1. Colees escolhidas ............................................................................. 121
6.3.2. Associaes Bidirecionais ..................................................................... 122
6.3.3. Associaes bidirecionais com colees indexadas ................................ 124
6.3.4. Associaes Ternrias .......................................................................... 125
6.3.5. Using an <idbag> ................................................................................. 125
6.4. Exemplos de colees .................................................................................... 126
7. Mapeamento de associaes ................................................................................... 131
7.1. Introduo ...................................................................................................... 131
7.2. Associaes Unidirecionais .............................................................................. 131
7.2.1. Muitos-para-um .................................................................................... 131
7.2.2. Um-para-um ......................................................................................... 132
7.2.3. Um-para-muitos .................................................................................... 133
7.3. Associaes Unidirecionais com tabelas associativas ........................................ 133
7.3.1. Um-para-muitos .................................................................................... 133
7.3.2. Muitos-para-um .................................................................................... 134
7.3.3. Um-para-um ......................................................................................... 135
7.3.4. Muitos-para-muitos ............................................................................... 135
7.4. Associaes Bidirecionais ................................................................................ 136
7.4.1. Um-para-muitos/muitos-para-um ............................................................ 136
7.4.2. Um-para-um ......................................................................................... 137
7.5. Associaes Bidirecionais com tabelas associativas .......................................... 138
7.5.1. Um-para-muitos/muitos-para-um ............................................................ 138
7.5.2. Um para um ........................................................................................ 139
7.5.3. Muitos-para-muitos ............................................................................... 140
7.6. Mapeamento de associaes mais complexas .................................................. 141
8. Mapeamento de Componentes ................................................................................ 143
8.1. Objetos dependentes ...................................................................................... 143
v
HIBERNATE - Persistncia Rela...
vi
12.1.2. Longas conversaes ......................................................................... 189
12.1.3. Considerando a identidade do objeto ................................................... 190
12.1.4. Edies comuns ................................................................................. 191
12.2. Demarcao de transaes de bancos de dados ............................................ 191
12.2.1. Ambiente no gerenciado ................................................................... 192
12.2.2. Usando JTA ....................................................................................... 193
12.2.3. Tratamento de Exceo ...................................................................... 195
12.2.4. Tempo de espera de Transao .......................................................... 196
12.3. Controle de concorrncia otimista .................................................................. 197
12.3.1. Checagem de verso da aplicao ...................................................... 197
12.3.2. Sesso estendida e versionamento automtico .................................... 198
12.3.3. Objetos destacados e versionamento automtico .................................. 199
12.3.4. Versionamento automtico customizado ............................................... 199
12.4. Bloqueio Pessimista ...................................................................................... 200
12.5. Modos para liberar a conexo ........................................................................ 201
13. Interceptadores e Eventos ..................................................................................... 203
13.1. Interceptadores ............................................................................................. 203
13.2. Sistema de Eventos ...................................................................................... 205
13.3. Segurana declarativa do Hibernate ............................................................... 206
14. Batch processing ................................................................................................... 209
14.1. Insero em lotes .......................................................................................... 209
14.2. Atualizao em lotes ..................................................................................... 210
14.3. A interface de Sesso sem Estado ................................................................ 210
14.4. Operaes no estilo DML .............................................................................. 211
15. HQL: A Linguagem de Consultas do Hibernate ..................................................... 215
15.1. Diferenciao de maiscula e minscula ........................................................ 215
15.2. A clusula from ............................................................................................. 215
15.3. Associaes e unies .................................................................................... 216
15.4. Formas de sintxe de unies ......................................................................... 218
15.5. Referncia propriedade do identificador ....................................................... 218
15.6. A clusula select ........................................................................................... 219
15.7. Funes de agregao .................................................................................. 220
15.8. Pesquisas Polimrficas .................................................................................. 221
15.9. A clusula where .......................................................................................... 221
15.10. Expresses ................................................................................................. 223
15.11. A clusula ordenar por ................................................................................ 227
15.12. A clusula agrupar por ................................................................................ 228
15.13. Subconsultas ............................................................................................... 228
15.14. Exemplos de HQL ....................................................................................... 229
15.15. Atualizao e correo em lote .................................................................... 232
15.16. Dicas & Truques ......................................................................................... 232
15.17. Componentes .............................................................................................. 233
15.18. Sintxe do construtor de valores de linha ...................................................... 234
16. Consultas por critrios .......................................................................................... 235
vii
HIBERNATE - Persistncia Rela...
viii
20.2.1. Mapeamento de Cache ....................................................................... 278
20.2.2. Estratgia: somente leitura .................................................................. 278
20.2.3. Estratgia: leitura/escrita ..................................................................... 278
20.2.4. Estratgia: leitura/escrita no estrita .................................................... 279
20.2.5. Estratgia: transacional ....................................................................... 279
20.2.6. Compatibilidade de Estratgia de Concorrncia de Cache Provedor ....... 279
20.3. Gerenciando os caches ................................................................................. 280
20.4. O Cache de Consulta .................................................................................... 281
20.4.1. Ativao do cache de consulta ............................................................ 281
20.4.2. Regies de cache de consulta ............................................................ 282
20.5. Entendendo o desempenho da Coleo ......................................................... 283
20.5.1. Taxonomia ......................................................................................... 283
20.5.2. Listas, mapas, bags de id e conjuntos so colees mais eficientes para
atualizar ........................................................................................................ 284
20.5.3. As Bags e listas so as colees de inverso mais eficientes. ............... 284
20.5.4. Deletar uma vez ................................................................................. 285
20.6. Monitorando desempenho .............................................................................. 285
20.6.1. Monitorando uma SessionFactory ........................................................ 285
20.6.2. Mtricas ............................................................................................. 286
21. Guia de Toolset ...................................................................................................... 289
21.1. Gerao de esquema automtico ................................................................... 289
21.1.1. Padronizando o esquema ................................................................... 290
21.1.2. Executando a ferramenta .................................................................... 293
21.1.3. Propriedades ...................................................................................... 293
21.1.4. Usando o Ant ..................................................................................... 294
21.1.5. Atualizaes de esquema incremental ................................................. 294
21.1.6. Utilizando Ant para atualizaes de esquema incremental ..................... 295
21.1.7. Validao de esquema ....................................................................... 295
21.1.8. Utilizando Ant para validao de esquema ........................................... 296
22. Exemplo: Pai/Filho ................................................................................................. 297
22.1. Uma nota sobre as colees ......................................................................... 297
22.2. Bidirecional um-para-muitos ........................................................................... 297
22.3. Ciclo de vida em Cascata .............................................................................. 299
22.4. Cascatas e unsaved-value ............................................................................. 301
22.5. Concluso ..................................................................................................... 301
23. Exemplo: Aplicativo Weblog .................................................................................. 303
23.1. Classes Persistentes ..................................................................................... 303
23.2. Mapeamentos Hibernate ................................................................................ 304
23.3. Cdigo Hibernate .......................................................................................... 306
24. Exemplo: Vrios Mapeamentos .............................................................................. 311
24.1. Empregador/Empregado ................................................................................ 311
24.2. Autor/Trabalho .............................................................................................. 313
24.3. Cliente/Ordem/Produto .................................................................................. 315
24.4. Exemplos variados de mapeamento ............................................................... 317
ix
HIBERNATE - Persistncia Rela...
x
Prefcio
O trabalho com o software objeto relacional e banco de dados relacionais, pode ser incmodo
e desgastante atualmente num meio empresarial. Hibernate um Objeto/Relacional de
Mapeamento de ferramentas nos meios Java. O termo Objeto/Relacional de Mapeamento (ORM)
refere-se tcnica de mapeamento de dados, representada desde o objeto modelo aos dados
relacionais modelo com um esquema baseado na SQL.
Por favor siga os seguintes passos, caso voc seja inexperiente com o Hibernate, Mapeamento
Objeto/Relacional ou mesmo Java:
1. Read Captulo 1, Tutorial for a tutorial with step-by-step instructions. The source code for the
tutorial is included in the distribution in the doc/reference/tutorial/ directory.
2. Read Captulo 2, Arquitetura to understand the environments where Hibernate can be used.
4. Use this reference documentation as your primary source of information. Consider reading
[JPwH] if you need more help with application design, or if you prefer a step-by-step tutorial. Also
visit http://caveatemptor.hibernate.org and download the example application from [JPwH].
5. As respostas das perguntas mais freqentes podem ser encontradas no website Hibernate.
xi
Prefcio
xii
Tutorial
Intencionado para novos usurios, este captulo fornece uma introduo detalhada do Hibernate,
comeando com um aplicativo simples usando um banco de dados em memria. O tutorial
baseado num tutorial anterior desenvolvido por Michael Gloegl. Todo o cdigo est contido no
diretrio tutorials/web da fonte do projeto.
Importante
Este tutorial espera que o usurio tenha conhecimento de ambos Java e SQL.
Caso voc tenha um conhecimento limitado do JAVA ou SQL, recomendado que
voc inicie com uma boa introduo quela tecnologia, antes de tentar entender
o Hibernate.
Nota
Nota
Mesmo que usando qualquer banco de dados do qual voc se sinta confortvel,
ns usaremos HSQLDB [http://hsqldb.org/] (o em memria, banco de dados Java)
para evitar a descrio de instalao/configurao de quaisquer servidores do
banco de dados.
1.1.1. Configurao
1
Captulo 1. Tutorial
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/
maven-4.0.0.xsd">
<modelVersion
>4.0.0</modelVersion>
<groupId
>org.hibernate.tutorials</groupId>
<artifactId
>hibernate-tutorial</artifactId>
<version
>1.0.0-SNAPSHOT</version>
<name
>First Hibernate Tutorial</name>
<build>
<!-- we dont want the version to be part of the generated war file name -->
<finalName
>${artifactId}</finalName>
</build>
<dependencies>
<dependency>
<groupId
>org.hibernate</groupId>
<artifactId
>hibernate-core</artifactId>
</dependency>
<!-- Because this is a web app, we also have a dependency on the servlet api. -->
<dependency>
<groupId
>javax.servlet</groupId>
<artifactId
>servlet-api</artifactId>
</dependency>
<!-- Hibernate uses slf4j for logging, for our purposes here use the simple backend -->
<dependency>
<groupId
>org.slf4j</groupId>
<artifactId
>slf4j-simple</artifactId>
</dependency>
<!-- Hibernate gives you a choice of bytecode providers between cglib and javassist -->
<dependency>
<groupId
>javassist</groupId>
<artifactId
>javassist</artifactId>
2
A primeira Classe
</dependency>
</dependencies>
</project
>
Dica
It is not a requirement to use Maven. If you wish to use something else to build
this tutorial (such as Ant), the layout will remain the same. The only change is
that you will need to manually account for all the needed dependencies. If you
use something like Ivy [http://ant.apache.org/ivy/] providing transitive dependency
management you would still use the dependencies mentioned below. Otherwise,
you'd need to grab all dependencies, both explicit and transitive, and add them
to the project's classpath. If working from the Hibernate distribution bundle, this
would mean hibernate3.jar, all artifacts in the lib/required directory and all
files from either the lib/bytecode/cglib or lib/bytecode/javassist directory;
additionally you will need both the servlet-api jar and one of the slf4j logging
backends.
Agora, iremos criar uma classe que representa o evento que queremos armazenar na base de
dados. Isto uma classe JavaBean simples com algumas propriedades:
package org.hibernate.tutorial.domain;
import java.util.Date;
public Event() {}
3
Captulo 1. Tutorial
Voc pode ver que esta classe usa o padro JavaBean para o nome convencional dos mtodos
de propriedade getter e setter, como tambm a visibilidade privada dos campos. Este um
padro de projeto recomendado, mas no requerido. O Hibernate pode tambm acessar campos
diretamente, o benefcio para os mtodos de acesso a robustez para o refactoring.
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
4
O mapeamento do arquivo
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.hibernate.tutorial.domain">
[...]
</hibernate-mapping
>
Note que o Hibernate DTD muito sofisticado. Voc pode usar isso para auto-concluso no
mapeamento XML dos elementos e funes no seu editor ou IDE. Voc tambm pode abrir
o arquivo DTD no seu editor. Esta a maneira mais fcil de ter uma viso geral de todos os
elementos e funes e dos padres, como tambm alguns comentrios. Note que o Hibernate
no ir carregar o arquivo DTD da web, e sim da classpath da aplicao. O arquivo DTD est
includo no hibernate-core.jar (como tambm no hibernate3.jar, caso usando a vinculao
de distribuio.
Importante
<hibernate-mapping package="org.hibernate.tutorial.domain">
</class>
</hibernate-mapping
>
At agora, informamos o Hibernate sobre como fazer para persistir e carregar objetos da
classe Event da tabela EVENTS, cada instncia representada por uma coluna na tabela. Agora,
continuaremos com o mapeamento de uma nica propriedade identificadora para as chaves
primrias da tabela. Alm disso, como no precisamos nos preocupar em manipular este
identificador, iremos configurar uma estratgia de gerao de ids do Hibernate para uma coluna
de chave primria substituta:
<hibernate-mapping package="org.hibernate.tutorial.domain">
5
Captulo 1. Tutorial
</id>
</class>
</hibernate-mapping
>
Dica
native is no longer consider the best strategy in terms of portability. for further
discussion, see Seo 26.4, Gerao do identificador
<hibernate-mapping package="org.hibernate.tutorial.domain">
</hibernate-mapping
>
Assim como com o elemento id, a funo name do elemento property informa ao Hibernate qual
mtodo getter e setter dever usar. Assim, neste caso, o Hibernate ir procurar pelos mtodos
getDate(), setDate(), getTitle() e setTitle().
6
Configurao do Hibernate
Nota
O mapeamento do title tambm no possui a funo type. O tipo que declaramos e utilizamos
nos arquivos mapeados, no so como voc esperava, ou seja, funes de dados Java. Eles
tambm no so como os tipos de base de dados SQL. Esses tipos podem ser chamados de
Tipos de mapeamento Hibernate, que so conversores que podem traduzir tipos de dados do
Java para os tipos de dados SQL e vice-versa. Novamente, o Hibernate ir tentar determinar
a converso correta e mapear o type prprio, caso o tipo da funo no estiver presente no
mapeamento. Em alguns casos, esta deteco automtica (que usa Reflection sobre as classes
Java) poder no ter o padro que voc espera ou necessita. Este o caso com a propriedade
date. O Hibernate no sabe se a propriedade, que do java.util.Date, pode mapear para
uma coluna do tipo date do SQL, timestamp ou time. Ns preservamos as informaes sobre
datas e horas pelo mapeamento da propriedade com um conversor timestamp.
Dica
Nota
Ns utilizaremos o Maven exec plugin para lanar o servidor HSQLDB pela execuo:
mvn exec:java -Dexec.mainClass="org.hsqldb.Server" -Dexec.args="-database.0
7
Captulo 1. Tutorial
O Hibernate conectar ao banco de dados no lugar de sua aplicao, portanto ele precisar saber
como obter as conexes. Para este tutorial ns usaremos um pool de conexo autnomo (ao
invs de javax.sql.DataSource). O Hibernate vem com o suporte para dois teros dos pools
de conexo JDBC de cdigo aberto: c3p0 [https://sourceforge.net/projects/c3p0] e proxool [http://
proxool.sourceforge.net/]. No entanto, ns usaremos o pool de conexo interna do Hibernate para
este tutorial.
Cuidado
<hibernate-configuration>
<session-factory>
8
Configurao do Hibernate
<mapping resource="org/hibernate/tutorial/domain/Event.hbm.xml"/>
</session-factory>
</hibernate-configuration
>
Nota
Dica
In most cases, Hibernate is able to properly determine which dialect to use. See
Seo 26.3, Resoluo do Dialeto for more information.
9
Captulo 1. Tutorial
Criaremos uma classe de ajuda HibernateUtil, que cuida da inicializao e faz acesso a uma
org.hibernate.SessionFactory mais conveniente.
package org.hibernate.tutorial.util;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
10
Carregando e salvando objetos
Voc precisar agora configurar um sistema de logging. O Hibernate usa logging comuns e lhe
oferece a escolha entre o Log4j e o logging do JDK 1.4 . A maioria dos desenvolvedores prefere o
Log4j: copie log4j.properties da distribuio do Hibernate no diretrio etc/, para seu diretrio
src, depois v em hibernate.cfg.xml. D uma olhada no exemplo de configurao e mude as
configuraes se voc quiser ter uma sada mais detalhada. Por padro, apenas as mensagens
de inicializao do Hibernate so mostradas no stdout.
package org.hibernate.tutorial;
import org.hibernate.Session;
11
Captulo 1. Tutorial
import java.util.*;
import org.hibernate.tutorial.domain.Event;
import org.hibernate.tutorial.util.HibernateUtil;
if (args[0].equals("store")) {
mgr.createAndStoreEvent("My Event", new Date());
}
HibernateUtil.getSessionFactory().close();
}
session.getTransaction().commit();
}
Importante
O Hibernate oferece trs mtodos da sesso atual. O mtodo "thread" baseado
no possui por interesse o uso de produo; ele basicamente til para
12
Carregando e salvando objetos
prototyping e tutoriais tais como este. A sesso atual ser discutida em mais
detalhes mais tarde.
See Captulo 12, Transaes e Concorrncia for more information about transaction handling
and demarcation. The previous example also skipped any error handling and rollback.
Para rodar isto, ns faremos uso do Maven exec plugin para chamar
nossa classe com a instalao do classpath necessria: mvn exec:java -
Dexec.mainClass="org.hibernate.tutorial.EventManager" -Dexec.args="store"
Nota
Voc precisa executar o mvn compile primeiramente.
[java] Hibernate: insert into EVENTS (EVENT_DATE, title, EVENT_ID) values (?, ?, ?)
Adicionamos uma opo para o mtodo principal com o objetivo de listar os eventos arquivados:
if (args[0].equals("store")) {
mgr.createAndStoreEvent("My Event", new Date());
}
else if (args[0].equals("list")) {
List events = mgr.listEvents();
for (int i = 0; i < events.size(); i++) {
13
Captulo 1. Tutorial
Here, we are using a Hibernate Query Language (HQL) query to load all existing Event objects
from the database. Hibernate will generate the appropriate SQL, send it to the database and
populate Event objects with the data. You can create more complex queries with HQL. See
Captulo 15, HQL: A Linguagem de Consultas do Hibernate for more information.
Agora podemos chamar nossa nova funcionalidade usando, novamente, o Maven exec
plugin: mvn exec:java -Dexec.mainClass="org.hibernate.tutorial.EventManager" -
Dexec.args="list"
package org.hibernate.tutorial.domain;
public Person() {}
14
Uma associao unidirecional baseada em Configurao
<hibernate-mapping package="org.hibernate.tutorial.domain">
</hibernate-mapping
>
<mapping resource="events/Event.hbm.xml"/>
<mapping resource="events/Person.hbm.xml"/>
Crie agora uma associao entre estas duas entidades. As pessoas (Person) podem participar
de eventos, e eventos possuem participantes. As questes de design com que teremos de lidar
so: direcionalidade, multiplicidade e comportamento de coleo.
15
Captulo 1. Tutorial
Antes de mapearmos esta associao, pense no outro lado. Claramente, poderamos apenas
fazer isto de forma unidirecional. Ou poderamos criar outra coleo no Event, se quisermos
navegar de ambas direes. Isto no necessrio, de uma perspectiva funcional. Voc poder
sempre executar uma consulta explcita para recuperar os participantes de um evento em
particular. Esta uma escolha de design que cabe a voc, mas o que claro nessa discusso
a multiplicidade da associao: "muitos" vlidos em ambos os lados, ns chamamos isto de uma
associao muitos-para-muitos. Daqui pra frente, usaremos o mapeamento muitos-para-muitos
do Hibernate:
</class
>
O Hibernate suporta todo tipo de mapeamento de coleo, sendo um set mais comum. Para uma
associao muitos-para-muitos ou relacionamento de entidade n:m, necessria uma tabela de
associao. Cada linha nessa tabela representa um link entre uma pessoa e um evento. O nome
da tabela configurado com a funo table do elemento set. O nome da coluna identificadora
na associao, pelo lado da pessoa, definido com o elemento key, o nome da coluna pelo
lado dos eventos, definido com a funo column do many-to-many. Voc tambm precisa dizer
para o Hibernate a classe dos objetos na sua coleo (a classe do outro lado das colees de
referncia).
_____________ __________________
| | | | _____________
| EVENTS | | PERSON_EVENT | | |
|_____________| |__________________| | PERSON |
| | | | |_____________|
| *EVENT_ID | <--> | *EVENT_ID | | |
16
Trabalhando a associao
session.getTransaction().commit();
}
Voc pode tambm querer carregar pessoas e eventos em diferentes unidades de trabalho. Ou
voc modifica um objeto fora de um org.hibernate.Session, quando no se encontra no estado
persistente (se j esteve neste estado anteriormente, chamamos esse estado de detached). Voc
pode at mesmo modificar uma coleo quando esta se encontrar no estado detached:
17
Captulo 1. Tutorial
session.getTransaction().commit();
session2.getTransaction().commit();
}
A chamada update cria um objeto persistente novamente, pode-se dizer que ele liga o objeto a
uma nova unidade de trabalho, assim qualquer modificao que voc faa neste objeto enquanto
estiver no estado desanexado pode ser salvo no banco de dados. Isso inclui qualquer modificao
(adio/excluso) que voc faa em uma coleo da entidade deste objeto.
Bem, isso no de grande utilidade na nossa situao atual, porm, um importante conceito
que voc pode criar em seu prprio aplicativo. No momento, complete este exerccio adicionando
uma ao ao mtodo principal da classe EventManager e chame-o pela linha de comando.
Se voc precisar dos identificadores de uma pessoa ou evento - o mtodo save() retornar
estes identificadores (voc poder modificar alguns dos mtodos anteriores para retornar aquele
identificador):
else if (args[0].equals("addpersontoevent")) {
Long eventId = mgr.createAndStoreEvent("My Event", new Date());
Long personId = mgr.createAndStorePerson("Foo", "Bar");
mgr.addPersonToEvent(personId, eventId);
System.out.println("Added person " + personId + " to event " + eventId);
}
Este foi um exemplo de uma associao entre duas classes igualmente importantes: duas
entidades. Como mencionado anteriormente, h outras classes e tipos dentro de um modelo
tpico, geralmente "menos importante". Alguns voc j viu, como um int ou uma String.
Ns chamamos essas classes de tipos de valores, e suas instncias dependem de uma
entidade particular. As instncias desses tipos no possuem sua prpria identidade, nem so
compartilhados entre entidades. Duas pessoas no referenciam o mesmo objeto firstname
mesmo se elas tiverem o mesmo objeto firstname. Naturalmente, os tipos de valores no so
apenas encontrados dentro da JDK, mas voc pode tambm criar suas classes como, por
exemplo, Address ou MonetaryAmount. De fato, no aplicativo Hibernate todas as classes JDK
so consideradas tipos de valores.
Voc tambm pode criar uma coleo de tipo de valores. Isso conceitualmente muito diferente
de uma coleo de referncias para outras entidades, mas em Java parece ser quase a mesma
coisa.
18
Coleo de valores
Vamos adicionar uma coleo de endereos de e-mail entidade Person. Isto ser representado
como um java.util.Set das instncias java.lang.String:
A diferena comparada com o mapeamento anterior se encontra na parte element, que informa
ao Hibernate que a coleo no contm referncias outra entidade, mas uma coleo de
elementos do tipo String. O nome da tag em minsculo indica que se trata de um tipo/conversor
de mapeamento do Hibernate. Mais uma vez, a funo table do elemento set determina o nome
da tabela para a coleo. O elemento key define o nome da coluna de chave estrangeira na
tabela de coleo. A funo column dentro do elemento element define o nome da coluna onde
os valores da String sero armazenados.
_____________ __________________
| | | | _____________
| EVENTS | | PERSON_EVENT | | | ___________________
|_____________| |__________________| | PERSON | | |
| | | | |_____________| | PERSON_EMAIL_ADDR |
| *EVENT_ID | <--> | *EVENT_ID | | | |___________________|
| EVENT_DATE | | *PERSON_ID | <--> | *PERSON_ID | <--> | *PERSON_ID |
| TITLE | |__________________| | AGE | | *EMAIL_ADDR |
|_____________| | FIRSTNAME | |___________________|
| LASTNAME |
|_____________|
19
Captulo 1. Tutorial
Voc pode observar que a chave primria da tabela da coleo na verdade uma chave
composta, usando as duas colunas. Isso tambm implica que cada pessoa no pode ter
endereos de e-mail duplicados, o que exatamente a semntica que precisamos para um set
em Java.
Voc pode agora tentar adicionar elementos essa coleo, do mesmo modo que fizemos
anteriormente ligando pessoas e eventos. o mesmo cdigo em Java:
session.getTransaction().commit();
}
Desta vez no utilizamos uma consulta fetch (busca) para inicializar a coleo. Monitore o log
SQL e tente otimiz-lo com rdua busca.
Nota
Um banco de dados relacional mais flexvel que um linguagem de programao
da rede, de maneira que ele no precisa de uma direo de navegao; os dados
podem ser visualizados e restaurados de qualquer maneira.
20
Trabalhando com links bidirecionais
Como voc pode ver, esses so mapeamentos set normais em ambos documentos de
mapeamento. Observe que os nomes das colunas em key e many-to-many esto trocados
em ambos os documentos de mapeamento. A adio mais importante feita est na funo
inverse="true" no elemento set da coleo da classe Event.
Isso significa que o Hibernate deve pegar o outro lado, a classe Person, quando precisar
encontrar informao sobre a relao entre as duas entidades. Isso ser muito mais fcil de
entender quando voc analisar como a relao bidirecional entre as entidades criada.
Primeiro, tenha em mente que o Hibernate no afeta a semntica normal do Java. Como foi
que criamos um link entre uma Person e um Event no exemplo unidirecional? Adicionamos
uma instncia de Event, da coleo de referncias de eventos, uma instncia de Person.
Ento, obviamente, se quisermos que este link funcione bidirecionalmente, devemos fazer a
mesma coisa para o outro lado, adicionando uma referncia de Person na coleo de um Event.
Essa "configurao de link de ambos os lados" absolutamente necessria e voc nunca deve
esquecer de faz-la.
Observe que os mtodos set e get da coleo esto protegidos. Isso permite que classes e
subclasses do mesmo pacote continuem acessando os mtodos, mas evita que qualquer outra
21
Captulo 1. Tutorial
classe, que no esteja no mesmo pacote, acesse a coleo diretamente. Repita os passos para
a coleo do outro lado.
E sobre o mapeamento da funo inverse? Para voc, e para o Java, um link bidirecional
simplesmente uma questo de configurar corretamente as referncias de ambos os lados. O
Hibernate, entretanto, no possui informao necessria para ajustar corretamente as instrues
INSERT e UPDATE do SQL (para evitar violaes de restrio) e precisa de ajuda para manipular
as associaes bidirecionais de forma apropriada. Ao fazer um lado da associao com a funo
inverse, voc instrui o Hibernate para basicamente ignor-lo, considerando-o uma cpia do
outro lado. Isso o necessrio para o Hibernate compreender todas as possibilidades quando
transformar um modelo de navegao bidirecional em esquema de banco de dados do SQL. As
regras que voc precisa lembrar so diretas: todas as associaes bidirecionais necessitam que
um lado possua a funo inverse. Em uma associao de um-para-muitos, precisar ser o lado
de "muitos", j em uma associao de muitos-para-muitos voc poder selecionar qualquer lado.
package org.hibernate.tutorial.web;
// Imports
try {
// Begin unit of work
HibernateUtil.getSessionFactory().getCurrentSession().beginTransaction();
22
Processando e renderizando
if ( ServletException.class.isInstance( ex ) ) {
throw ( ServletException ) ex;
}
else {
throw new ServletException( ex );
}
}
}
O modelo que estamos aplicando neste cdigo chamado session-per-request. Quando uma
solicitao chega ao servlet, uma nova Session do Hibernate aberta atravs da primeira
chamada para getCurrentSession() em SessionFactory. Ento uma transao do banco de
dados inicializada e todo acesso a dados deve ocorrer dentro de uma transao, no importando
se o dado de leitura ou escrita. No se deve utilizar o modo auto-commit em aplicaes.
Nunca utilize uma nova Session do Hibernate para todas as operaes de banco de dados.
Utilize uma Session do Hibernate que seja de interesse todas as solicitaes. Utilize
getCurrentSession(), para que seja vinculado automaticamente thread atual de Java.
Agora, as possveis aes de uma solicitao sero processadas e uma resposta HTML ser
renderizada. J chegaremos nesta parte.
// Handle actions
if ( "store".equals(request.getParameter("action")) ) {
23
Captulo 1. Tutorial
if ( "".equals(eventTitle) || "".equals(eventDate) ) {
out.println("<b
><i
>Please enter event title and date.</i
></b
>");
}
else {
createAndStoreEvent(eventTitle, dateFormatter.parse(eventDate));
out.println("<b
><i
>Added event.</i
></b
>");
}
}
// Print page
printEventForm(out);
listEvents(out, dateFormatter);
O estilo deste cdigo misturado com o Java e HTML, no escalariam em um aplicativo mais
complexo, tenha em mente que estamos somente ilustrando os conceitos bsicos do Hibernate
neste tutorial. O cdigo imprime um cabealho e nota de rodap em HTML. Dentro desta pgina,
so impressos um formulrio para entrada de evento em HTML e uma lista de todos os evento
no banco de dados. O primeiro mtodo trivial e somente produz um HTML:
O mtodo listEvents() utiliza a Session do Hibernate, limitado ao thread atual para executar
uma consulta:
24
Processando e renderizando
HibernateUtil.getSessionFactory()
.getCurrentSession().save(theEvent);
}
25
Captulo 1. Tutorial
O servlet est completo agora. Uma solicitao ao servlet ser processada com uma nica
Session e Transaction. Quanto antes estiver no aplicativo autnomo, maior a chance do
Hibernate vincular automaticamente estes objetos thread atual de execuo. Isto lhe d a
liberdade para inserir seu cdigo e acessar a SessionFactory como desejar. Geralmente,
usaramos um diagrama mais sofisticado e moveramos o cdigo de acesso de dados para os
objetos de acesso dos dados (o modelo DAO). Veja o Hibernate Wiki para mais exemplos.
Para implementar este aplicativo em testes, ns devemos criar um Arquivo da Web (WAR).
Primeiro, ns devemos definir o descritor WAR como src/main/webapp/WEB-INF/web.xml
<servlet>
<servlet-name
>Event Manager</servlet-name>
<servlet-class
>org.hibernate.tutorial.web.EventManagerServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name
>Event Manager</servlet-name>
<url-pattern
>/eventmanager</url-pattern>
</servlet-mapping>
</web-app
>
Para construir e implementar, chame seu diretrio de projeto ant war e copie o arquivo
hibernate-tutorial.war para seu diretrio Tomcat webapp.
Nota
26
Sumrio
1.4. Sumrio
Este tutorial cobriu itens bsicos de como escrever um aplicativo Hibernate autnomo simples e
um aplicativo da web pequeno. A partir do Hibernate website [http://hibernate.org] voc poder
encontrar mais tutoriais disponveis.
27
28
Arquitetura
2.1. Viso Geral
O diagrama abaixo fornece uma viso de altssimo nvel da arquitetura do Hibernate:
Application
Persistent Objects
HIBERNATE
hibernate. XML Mapping
properties
Database
Ns no temos o escopo neste documento para mostrar uma viso mais detalhada da arquitetura
em execuo. O Hibernate muito flexvel e suporta vrias abordagens. Mostraremos os dois
extremos. No entanto, ns apresentaremos os dois extremos: arquitetura "mnima" e arquitetura
"compreensiva".
Este diagrama mostra o Hibernate usando o banco de dados e a configurao de dados para
prover persistncia de servios e persistncia de objetos para o aplicativo.
Na arquitetura "mnima", o aplicativo fornece suas prprias conexes JDBC e gerencia suas
transaes. Esta abordagem usa o mnimo de subconjuntos das APIs do Hibernate:
29
Captulo 2. Arquitetura
Persistent
Objects
Database
SessionFactory
Session Transaction
TransactionFactory ConnectionProvider
Database
30
Viso Geral
SessionFactory (org.hibernate.SessionFactory)
O threadsafe, cach imutvel composto de mapeamentos compilados para um nico banco
de dados. Uma fbrica para Session e um cliente de ConnectionProvider, SessionFactory
pode conter um cach opcional de dados (segundo nvel) reutilizveis entre transaes, no
nvel de processo ou cluster.
Session (org.hibernate.Session)
Objeto single-threaded, de vida curta, representa uma conversao entre o aplicativo
e o armazenamento persistente. Cria uma camada sobre uma conexo JDBC. uma
fabrica de Transaction. A Session possui um cach obrigatrio (primeiro nvel) de objetos
persistentes, usado para navegao nos grficos de objetos e pesquisa de objetos pelo
identificador.
Transaction (org.hibernate.Transaction)
(Opcional) Objeto de vida curta, single threaded, usado pela aplicao para especificar
unidades atmicas de trabalho. Abstrai o aplicativo das transaes JDBC, JTA ou CORBA
adjacentes. Uma Session pode, em alguns casos, iniciar vrias Transactions. Entretanto,
a demarcao da transao, mesmo utilizando API ou Transaction subjacentes, nunca
opcional.
Extension Interfaces
O Hibernate oferece vrias opes de interfaces estendidas que voc pode implementar para
customizar sua camada persistente. Veja a documentao da API para maiores detalhes.
31
Captulo 2. Arquitetura
transiente
A instncia no associada a nenhum contexto persistente. No possui uma identidade
persistente ou valor de chave primria.
persistente
A instncia est atualmente associada a um contexto persistente. Possui uma identidade
persistente (valor de chave primria) e, talvez, correspondente a uma fila no banco de dados.
Para um contexto persistente em particular, o Hibernate garante que a identidade persistente
equivalente identidade Java (na localizao em memria do objeto).
desanexado
A instncia foi associada com um contexto persistente, porm este contexto foi fechado, ou
a instncia foi serializada por outro processo. Possui uma identidade persistente, e, talvez,
corresponda a uma fila no banco de dados. Para instncias desanexadas, o Hibernate no
garante o relacionamento entre identidade persistente e identidade Java.
Session Management: O ciclo de vida de uma Session do Hibernate pode ser automaticamente
conectada a um escopo de transao JTA. Isso significa que voc no precisar mais abrir e
fechar manualmente uma Session, isso se torna uma tarefa para um interceptor EJB do JBoss.
Voc tambm no precisar mais se preocupar com demarcao de transao em seu cdigo
(caso voc prefira escrever uma camada persistente portvel, use a API opcional do Hibernate
Transaction). Voc deve chamar HibernateContext para acessar uma Session.
32
Suporte JCA
Consulte o manual do usurio do JBoss AS, para obter maiores informaes sobre essas opes.
Another feature available as a JMX service is runtime Hibernate statistics. See Seo 3.4.6,
Estatsticas do Hibernate for more information.
33
Captulo 2. Arquitetura
The first two implementations provide a "one session - one database transaction" programming
model. This is also known and used as session-per-request. The beginning and end of a Hibernate
session is defined by the duration of a database transaction. If you use programmatic transaction
demarcation in plain JSE without JTA, you are advised to use the Hibernate Transaction API
to hide the underlying transaction system from your code. If you use JTA, you can utilize the
JTA interfaces to demarcate transactions. If you execute in an EJB container that supports CMT,
transaction boundaries are defined declaratively and you do not need any transaction or session
demarcation operations in your code. Refer to Captulo 12, Transaes e Concorrncia for more
information and code examples.
34
Configuration
Devido ao fato do Hibernate ser projetado para operar em vrios ambientes diferentes, h um
grande nmero de parmetros de configurao. Felizmente, a maioria possui valores padro
considerveis e o Hibernate distribudo com um arquivo hibernate.properties de exemplo
no etc/ que mostra vrias opes. Apenas coloque o arquivo de exemplo no seu classpath e
personalize-o.
Uma alternativa especificar a classe mapeada e permitir que o Hibernate encontre o documento
de mapeamento para voc:
35
Captulo 3. Configuration
Assim que voc fizer algo que requeira o acesso ao banco de dados, uma conexo JDBC ser
obtida a partir do pool.
Para esse trabalho, precisaremos passar algumas propriedades da conexo JDBC para o
Hibernate. Todos os nomes de propriedades Hibernate e semnticas so definidas na classe
org.hibernate.cfg.Environment. Descreveremos agora as configuraes mais importantes
para a conexo JDBC.
36
Conexes JDBC
O C3P0 um pool conexo JDBC de cdigo aberto distribudo junto com Hibernate no diretrio
lib. O Hibernate usar o prprio org.hibernate.connection.C3P0ConnectionProvider para
o pool de conexo se voc configurar a propriedade hibernate.c3p0.*. Se voc gostar de
usar Proxool, consulte o pacote hibernate.properties e o web site do Hibernate para mais
informaes.
hibernate.connection.driver_class = org.postgresql.Driver
hibernate.connection.url = jdbc:postgresql://localhost/mydatabase
hibernate.connection.username = myuser
hibernate.connection.password = secret
hibernate.c3p0.min_size=5
hibernate.c3p0.max_size=20
hibernate.c3p0.timeout=1800
hibernate.c3p0.max_statements=50
hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
Para usar dentro de um servidor de aplicao, voc deve configurar o Hibernate para obter
conexes de um servidor de aplicao javax.sql.Datasource registrado no JNDI. Voc
precisar determinar pelo menos uma das seguintes propriedades:
37
Captulo 3. Configuration
hibernate.connection.datasource = java:/comp/env/jdbc/test
hibernate.transaction.factory_class = \
org.hibernate.transaction.JTATransactionFactory
hibernate.transaction.manager_lookup_class = \
org.hibernate.transaction.JBossTransactionManagerLookup
hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
Conexes JDBC obtidas de um datasource JNDI iro automaticamente participar das transaes
gerenciadas pelo recipiente no servidor de aplicao.
Voc pode definir sua prpria estratgia de plugin para obter conexes JDBC implementando
a interface org.hibernate.connection.ConnectionProvider e especificando sua
implementao customizada atravs da propriedade hibernate.connection.provider_class.
Ateno
38
Propriedades opcionais de configurao
e.g. full.classname.of.Dialect
e.g. SCHEMA_NAME
hibernate.default_catalog Qualifica no SQL gerado, os nome das tabelas
desqualificadas com catlogo dado.
e.g. CATALOG_NAME
hibernate.session_factory_name O org.hibernate.SessionFactory ir
automaticamente se ligar a este nome no JNDI
depois de ter sido criado.
e.g. jndi/composite/name
hibernate.max_fetch_depth Estabelece a "profundidade" mxima para
rvore de busca de unio externa para
associaes finais nicas (um para um, muitos
para um). Um 0 desativa por padro a busca
de unio externa.
39
Captulo 3. Configuration
40
Propriedades opcionais de configurao
exemplo classname.of.BatcherFactory
hibernate.jdbc.use_scrollable_resultset Habilita o uso dos resultados de ajustes
rolveis do JDBC2 pelo Hibernate. Essa
propriedade somente necessria quando se
usa Conexes JDBC providas pelo usurio.
Do contrrio, o Hibernate os os metadados da
conexo.
exemplo true|false
hibernate.connection.provider_class O nome da classe de um
org.hibernate.connection.ConnectionProvider,
do qual prover conexes JDBC para o
Hibernate.
exemploclassname.of.ConnectionProvider
hibernate.connection.isolation Determina o nvel de isolamento
de uma transao JDBC. Verifique
java.sql.Connection para valores
significativos mas note que a maior parte
41
Captulo 3. Configuration
exemplo 1, 2, 4, 8
hibernate.connection.autocommit Habilita o auto-commit para conexes no pool
JDBC (no recomendado).
42
Propriedades opcionais de configurao
exemplo classname.of.CacheProvider
hibernate.cache.use_minimal_puts Otimizar operao de cach de segundo nvel
para minimizar escritas, ao custo de leituras
mais freqentes. Esta configurao mais til
para cachs em cluster e, no Hibernate3,
habilitado por padro para implementaes de
cache em cluster.
exemplo true|false
hibernate.cache.use_query_cache Habilita a cache de consultas. Mesmo assim,
consultas individuais ainda tm que ser
habilitadas para o cache.
exemplo true|false
hibernate.cache.use_second_level_cache Pode ser utilizado para desabilitar
completamente o cache de segundo nvel, o
qual habilitado por padro para as classes
que especificam um mapeamento <cache>.
exemplo true|false
hibernate.cache.query_cache_factory O nome de classe de
uma interface
personalizada QueryCache, padroniza
para o StandardQueryCache criado
automaticamente.
exemplo classname.of.QueryCache
hibernate.cache.region_prefix Um prefixo para usar em nomes regionais de
cach de segundo nvel
exemplo prefix
hibernate.cache.use_structured_entries Fora o Hibernate a armazenar dados no
cach de segundo nvel em um formato mais
humanamente amigvel.
exemplo true|false
43
Captulo 3. Configuration
exemplo
classname.of.TransactionFactory
e.g. jndi/composite/name
O
hibernate.transaction.manager_lookup_class nome da classe de um
TransactionManagerLookup. Ele requerido
quando o caching a nvel JVM estiver
habilitado ou quando estivermos usando um
gerador hilo em um ambiente JTA.
exemplo
classname.of.TransactionManagerLookup
44
Propriedades opcionais de configurao
exemplo org.hibernate.hql.ast.
ASTQueryTranslatorFactory ou
org.hibernate.hql.classic.
ClassicQueryTranslatorFactory
exemplo hqlLiteral=SQL_LITERAL,
hqlFunction=SQLFUNC
45
Captulo 3. Configuration
RDBMS Dialeto
DB2 org.hibernate.dialect.DB2Dialect
PostgreSQL org.hibernate.dialect.PostgreSQLDialect
Oracle 9i org.hibernate.dialect.Oracle9iDialect
Sybase org.hibernate.dialect.SybaseDialect
SAP DB org.hibernate.dialect.SAPDBDialect
Informix org.hibernate.dialect.InformixDialect
HypersonicSQL org.hibernate.dialect.HSQLDialect
Ingres org.hibernate.dialect.IngresDialect
Progresso org.hibernate.dialect.ProgressDialect
Interbase org.hibernate.dialect.InterbaseDialect
Firebird org.hibernate.dialect.FirebirdDialect
46
Fluxos Binrios (Binary Streams)
desempenhado pelo prprio banco de dados. A busca por unio externa (outer join fetching)
permite um grfico completo de objetos conectados por associaes muitos-para-um, um-para-
muitos, muitos-para-muitos e um-para-um para serem recuperadas em uma simples instruo
SQL SELECT.
A busca por unio externa pode ser desabilitada globalmente configurando a propriedade
hibernate.max_fetch_depth para 0. Um valor 1 ou maior habilita a busca por unio externa para
associaes um-para-um e muitos-para-um, cujos quais tm sido mapeados com fetch="join".
Isto faria com que os smbolos true e false passasem a ser traduzidos para literais inteiros no
SQL gerado.
hibernate.query.substitutions toLowercase=LOWER
47
Captulo 3. Configuration
3.5. Logging
O Hibernate utiliza o Simple Logging Facade for Java [http://www.slf4j.org/] (SLF4J) com o
objetivo de registrar os diversos eventos de sistema. O SLF4J pode direcionar a sua sada de
logging a diversos frameworks de logging (NOP, Simple, log4j version 1.2, JDK 1.4 logging,
JCL ou logback) dependendo de sua escolha de vinculao. Com o objetivo de determinar o
seu logging, voc precisar do slf4j-api.jar em seu classpatch juntamente com o arquivo
jar para a sua vinculao preferida - slf4j-log4j12.jar no caso do Log4J. Consulte o SLF4J
documentation [http://www.slf4j.org/manual.html] para maiores detalhes. Para usar o Log4j voc
precisar tambm colocar um arquivo log4j.properties em seu classpath. Um exemplo do
arquivo de propriedades est distribudo com o Hibernate no diretrio src/.
Ns recomendamos que voc se familiarize-se com mensagens de log do Hibernate. Tem sido
um rduo trabalho fazer o log Hibernate to detalhado quanto possvel, sem faz-lo ilegvel.
um dispositivo de controle de erros essencial. As categorias de log mais interessantes so as
seguintes:
Categoria Funo
org.hibernate.SQL Registra todas as instrues SQL DML a medida que elas so
executadas
org.hibernate.type Registra todos os parmetros JDBC
Registra todas as instrues SQL DDL a medida que elas so
org.hibernate.tool.hbm2ddl
executadas
org.hibernate.pretty Registra o estado de todas as entidades (mximo 20 entidades)
associadas sesso no momento da liberao (flush).
org.hibernate.cache Registra todas as atividades de cach de segundo nvel
Registra atividades relacionada transao
org.hibernate.transaction
Ao desenvolver aplicaes com Hibernate, voc deve quase sempre trabalhar com o depurador
debug habilitado para a categoria org.hibernate.SQL, ou, alternativamente, com a propriedade
hibernate.show_sql habilitada.
48
Arquivo de configurao XML
Voc deve criar regras para a gerao automaticamente de identificadores do banco de dados
a partir de identificadores Java ou para processar colunas "lgicas" e nomes de tabelas dado o
arquivo de mapeamento para nomes "fsicos" de tabelas e colunas. Este recurso ajuda a reduzir a
verbosidade do documento de mapeamento, eliminando interferncias repetitivas (TBL_ prefixos,
por exemplo). A estratgia padro usada pelo Hibernate bastante mnima.
O arquivo XML de configurao deve ser encontrado na raz do seu CLASSPATH. Veja um exemplo:
<hibernate-configuration>
49
Captulo 3. Configuration
<mapping resource="org/hibernate/auction/Item.hbm.xml"/>
<mapping resource="org/hibernate/auction/Bid.hbm.xml"/>
</session-factory>
</hibernate-configuration
>
Como voc pode ver, a vantagem deste enfoque a externalizao dos nomes dos arquivos
de mapeamento para configurao. O hibernate.cfg.xml tambm mais conveniente
caso voc tenha que ajustar o cache do Hibernate. Note que a escolha sua em usar
hibernate.properties ou hibernate.cfg.xml, ambos so equivalentes, exceto os acima
mencionados de usar a sintaxe de XML.
DataSources gerenciados pelo container: O Hibernate pode usar conexes JDBC gerenciadas
pelo Container e fornecidas pela JNDI. Geralmente, um TransactionManager compatvel com
JTA e um ResourceManager cuidam do gerenciamento da transao (CMT), especialmente
em transaes distribudas, manipuladas atravs de vrios DataSources. Naturalmente, voc
tambm pode demarcar os limites das transaes programaticamente (BMT) ou voc poderia
querer usar a API opcional do Hibernate Transaction para esta manter seu cdigo portvel.
50
Configurao de estratgia de transao
JMX deployment: Se voc usa um JMX servidor de aplicaes capaz (ex. Jboss AS), voc pode
fazer a instalao do Hibernate como um MBean controlado. Isto evita ter que iniciar uma linha
de cdigo para construir sua SessionFactory de uma Configuration. O container iniciar
seu HibernateService, e tambm cuidar das dependncias de servios (DataSources, tm
que estar disponveis antes do Hibernate iniciar, etc.).
Dependendo do seu ambiente, voc pode ter que ajustar a opo de configurao
hibernate.connection.aggressive_release para verdadeiro ( true ), se seu servidor de
aplicaes lanar exees "reteno de conexo".
Para manter seu cdigo portvel entre estes dois (e outros) ambientes, recomendamos a API
Hibernate Transaction, que envolve e esconde o sistema subjacente. Voc tem que especificar
uma classe construtora para instncias Transaction ajustando a propriedade de configurao
do hibernate.transaction.factory_class.
org.hibernate.transaction.JDBCTransactionFactory
delega as transaes (JDBC) para bases de dados (Padro)
org.hibernate.transaction.JTATransactionFactory
delega para uma transao um container gerenciado se uma transao existente estiver de
acordo neste contexto (ex: mtodo bean de sesso EJB). No entanto, uma nova transao
ser iniciada e sero usadas transaes controladas por um bean.
org.hibernate.transaction.CMTTransactionFactory
delega para um container gerenciador de transaes JTA
Voc tambm pode definir suas prprias estratgias de transao (para um servio de transao
CORBA, por exemplo).
Algumas caractersticas no Hibernate (ex., o cache de segundo nvel, sesses contextuais com
JTA, etc.) requerem acesso a JTA TransactionManager em um ambiente controlado. Em um
51
Captulo 3. Configuration
servidor de aplicao voc tem que especificar como o Hibernate pode obter uma referncia para
a TransactionManager, pois o J2EE no padroniza um mecanismo simples:
org.hibernate.transaction.OrionTransactionManagerLookup Orion
org.hibernate.transaction.ResinTransactionManagerLookup Resin
org.hibernate.transaction.JOTMTransactionManagerLookup JOTM
org.hibernate.transaction.JOnASTransactionManagerLookup JOnAS
org.hibernate.transaction.JRun4TransactionManagerLookup JRun4
org.hibernate.transaction.BESTransactionManagerLookup Borland ES
52
Gerenciamento de contexto de Sesso atual com JTA
<?xml version="1.0"?>
<server>
<mbean code="org.hibernate.jmx.HibernateService"
name="jboss.jca:service=HibernateFactory,name=HibernateFactory">
53
Captulo 3. Configuration
<attribute name="TransactionStrategy">
org.hibernate.transaction.JTATransactionFactory</attribute>
<attribute name="TransactionManagerLookupStrategy">
org.hibernate.transaction.JBossTransactionManagerLookup</attribute>
<attribute name="FlushBeforeCompletionEnabled"
>true</attribute>
<attribute name="AutoCloseSessionEnabled"
>true</attribute>
</mbean>
</server
>
54
Classes Persistentes
As classes persistentes so classes dentro de um aplicativo que implementa as entidades de
problemas de negcios (ex.: Cliente e Pedido em um aplicativo e-commerce). Nem todas as
instncias de uma classe persistente esto em estado persistente, uma instncia pode, ao invs
disso, ser transiente ou desanexada.
O Hibernate trabalha melhor se estas classes seguirem uma regra simples, tambm conhecida
como modelo de programao Objeto de Java Antigo Simples (POJO). No entanto, nenhuma
destas regras so difceis solicitaes. Certamente, o Hibernate3 considera muito pouco da
natureza de seus objetos persistentes. Voc pode expressar um modelo de domnio de outras
formas (por exemplo: utilizando rvores de instncias Map).
package eg;
import java.util.Set;
import java.util.Date;
55
Captulo 4. Classes Persistentes
return weight;
}
As quatro regras principais das classes persistentes so descritas em maiores detalhes nas
seguintes sees.
56
Providencie uma propriedade de identificador (opcional)
Cat possui uma propriedade chamada id. Esta propriedade mapeia para a coluna de chave
primria de uma tabela de banco de dados. A propriedade pode ter sido chamada por
qualquer nome e seu tipo pode ter sido qualquer um primitivo, ou qualquer tipo "wrapper",
java.lang.String ou java.util.Date. Se sua tabela de banco de dados de legacia possuir
chaves compostas, voc tambm poder usar uma classe de usurio definido, com propriedades
destes tipos (veja a seo de identificadores compostos mais adiante.)
Na verdade, algumas funcionalidades esto disponveis somente para classes que declaram uma
propriedade de identificador:
Transitive reattachment for detached objects (cascade update or cascade merge) - see
Seo 10.11, Persistncia Transitiva
Session.saveOrUpdate()
Session.merge()
Um recurso central do Hibernate, proxies, depende da classe persistente ser tanto no final como
uma implementao de uma interface que declare todos os mtodos pblicos.
Voc pode persistir as classes final que no implementam uma interface com o Hibernate, mas
no poder usar os proxies para busca por associao lazy, que ir limitar suas opes para
ajuste de desempenho.
Voc deve evitar declarar mtodos public final em classes no finais. Se voc desejar
usar uma classe com um mtodo public final voc deve desabilitar o proxy explicitamente,
ajustando lazy="false".
Cat declara os mtodos assessores para todos os seus campos persistentes. Muitas ferramentas
ORM persistem diretamente variveis de instncias. Acreditamos ser melhor prover uma
indireo entre o esquema relacional e as estruturas de dados internos da classe. Por padro,
o Hibernate persiste as propriedades de estilo JavaBeans, e reconhece nomes de mtodos da
57
Captulo 4. Classes Persistentes
forma getFoo, isFoo e setFoo. Caso solicitado, voc pode mudar para direcionar acesso ao
campo para certas propriedades, caso seja necessrio.
As propriedades precisam not ser declaradas como pblicas. O Hibernate pode persistir uma
propriedade com um par get/set padro protegido ou privado.
package eg;
58
Modelos dinmicos
...
public boolean equals(Object other) {
if (this == other) return true;
if ( !(other instanceof Cat) ) return false;
return true;
}
A business key does not have to be as solid as a database primary key candidate (see
Seo 12.1.3, Considerando a identidade do objeto). Immutable or unique properties are usually
good candidates for a business key.
Nota
The following features are currently considered experimental and may change in
the near future.
Entidades persistentes no precisam ser representadas como classes POJO ou como objetos
JavaBeans em tempo de espera. O Hibernate tambm suporta modelos dinmicos (usando Maps
de Maps em tempo de execuo) e a representao de entidades como rvores DOM4J. Com
esta abordagem, voc no escreve classes persistes, somente arquivos de mapeamentos.
By default, Hibernate works in normal POJO mode. You can set a default entity representation
mode for a particular SessionFactory using the default_entity_mode configuration option (see
Tabela 3.3, Propriedades de Configurao do Hibernate).
59
Captulo 4. Classes Persistentes
<hibernate-mapping>
<class entity-name="Customer">
<id name="id"
type="long"
column="ID">
<generator class="sequence"/>
</id>
<property name="name"
column="NAME"
type="string"/>
<property name="address"
column="ADDRESS"
type="string"/>
<many-to-one name="organization"
column="ORGANIZATION_ID"
class="Organization"/>
<bag name="orders"
inverse="true"
lazy="false"
cascade="all">
<key column="CUSTOMER_ID"/>
<one-to-many class="Order"/>
</bag>
</class>
</hibernate-mapping
>
Note que embora as associaes sejam declaradas utilizando nomes de classe, o tipo alvo de
uma associao pode tambm ser uma entidade dinmica, ao invs de um POJO.
Aps ajustar o modo de entidade padro para dynamic-map para a SessionFactory, voc poder
trabalhar com Maps de Maps no perodo de execuo:
Session s = openSession();
Transaction tx = s.beginTransaction();
// Create a customer
Map david = new HashMap();
david.put("name", "David");
// Create an organization
Map foobar = new HashMap();
60
Tuplizadores
// Link both
david.put("organization", foobar);
// Save both
s.save("Customer", david);
s.save("Organization", foobar);
tx.commit();
s.close();
Modos de representao de entidade podem ser tambm ajustados para base por Session:
// Create a customer
Map david = new HashMap();
david.put("name", "David");
dynamicSession.save("Customer", david);
...
dynamicSession.flush();
dynamicSession.close()
...
// Continue on pojoSession
Por favor, note que a chamada para a getSession() usando um EntityMode est na API
de Session e no na SessionFactory. Dessa forma, a nova Session compartilha a conexo,
transao e outra informao de contexto JDBC adjacente. Isto significa que voc no precisar
chamar flush() e close() na Session secundria, e tambm deixar a transao e o manuseio
da conexo para a unidade primria do trabalho.
More information about the XML representation capabilities can be found in Captulo 19,
Mapeamento XML.
4.5. Tuplizadores
org.hibernate.tuple.Tuplizer, e suas sub-interfaces, so responsveis por gerenciar
uma certa representao de uma parte de dado, dada a org.hibernate.EntityMode da
representao. Se uma parte de dado tida como uma estrutura de dado, ento o tuplizador
se encarrega de criar tal estrutura de dado e como extrair e injetar valores de e em tal estrutura
de dados. Por exemplo, para um modo POJO, o tuplizador correspondente sabe como criar um
61
Captulo 4. Classes Persistentes
POJO atravs de seu construtor. Alm disso, ele sabe como acessar propriedades de POJO
usando assessores de propriedades definidas.
Os usurios podem tambm plugar seu prprio tuplizador. Talvez voc queira usar uma
implementao java.util.Map ao invs de uma java.util.HashMap enquanto estiver no modo
de entidade mapa dinmico, ou talvez voc precise definir uma estratgia de gerao de
proxy diferente, ao invs de uma utilizada por padro. Ambas seriam alcanadas definindo
uma implementao de tuplizador personalizada. As definies do tuplizador esto anexadas
entidade ou ao mapeamento de componente que tiverem que gerenciar. Retornando ao exemplo
da entidade do nosso cliente:
<hibernate-mapping>
<class entity-name="Customer">
<!--
Override the dynamic-map entity-mode
tuplizer for the customer entity
-->
<tuplizer entity-mode="dynamic-map"
class="CustomMapTuplizerImpl"/>
62
EntityNameResolvers
4.6. EntityNameResolvers
A interface org.hibernate.EntityNameResolver um contrato para resolver o nome da
entidade de uma instncia de entidade dada. A interface define um resolveEntityName
de mtodo nico que passado instncia de entidade e esperado a retornar
ao nome de entidade apropriado (nulo permitido e indicaria que o solucionador no
saiba como resolver o nome de entidade da instncia de entidade dada). Normalmente,
um org.hibernate.EntityNameResolver ser mais til no caso de modelos dinmicos.
Um exemplo poder ser usado nas interfaces com proxie no caso dos modelos
dinmicos. O hibernate test suite possui um exemplo deste estilo exato de uso sob o
org.hibernate.test.dynamicentity.tuplizer2. Segue abaixo parte do cdigo a partir daquele pacote
para ilustrao.
/**
* A very trivial JDK Proxy InvocationHandler implementation where we proxy an interface as
* the domain model and simply store persistent state in an internal Map. This is an extremely
* trivial example meant only for illustration.
*/
public final class DataProxyHandler implements InvocationHandler {
private String entityName;
private HashMap data = new HashMap();
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
if ( methodName.startsWith( "set" ) ) {
String propertyName = methodName.substring( 3 );
data.put( propertyName, args[0] );
}
else if ( methodName.startsWith( "get" ) ) {
String propertyName = methodName.substring( 3 );
return data.get( propertyName );
}
else if ( "toString".equals( methodName ) ) {
return entityName + "#" + data.get( "Id" );
}
else if ( "hashCode".equals( methodName ) ) {
return new Integer( this.hashCode() );
}
return null;
}
63
Captulo 4. Classes Persistentes
/**
*
*/
public class ProxyHelper {
public static String extractEntityName(Object object) {
// Our custom java.lang.reflect.Proxy instances actually bundle
// their appropriate entity name, so we simply extract it from there
// if this represents one of our proxies; otherwise, we return null
if ( Proxy.isProxyClass( object.getClass() ) ) {
InvocationHandler handler = Proxy.getInvocationHandler( object );
if ( DataProxyHandler.class.isAssignableFrom( handler.getClass() ) ) {
DataProxyHandler myHandler = ( DataProxyHandler ) handler;
return myHandler.getEntityName();
}
}
return null;
}
/**
* The EntityNameResolver implementation.
* IMPL NOTE : An EntityNameResolver really defines a strategy for how entity names should be
* resolved. Since this particular impl can handle resolution for all of our entities we want to
* take advantage of the fact that SessionFactoryImpl keeps these in a Set so that we only ever
* have one instance registered. Why? Well, when it comes time to resolve an entity name,
* Hibernate must iterate over all the registered resolvers. So keeping that number down
* helps that process be as speedy as possible. Hence the equals and hashCode impls
*/
public class MyEntityNameResolver implements EntityNameResolver {
public static final MyEntityNameResolver INSTANCE = new MyEntityNameResolver();
64
EntityNameResolvers
if ( entityName == null ) {
entityName = super.determineConcreteSubclassEntityName( entityInstance, factory );
}
return entityName;
}
...
}
65
66
Mapeamento O/R Bsico
5.1. Declarao de mapeamento
O mapeamento de objeto/relacional geralmente definido em um documento XML. O documento
de mapeamento criado para ser de leitura e editvel manualmente. A linguagem do
mapeamento Java-centric, ou seja, os mapeamentos so construdos em torno de declaraes
de classe persistente e no de declaraes de tabelas.
Note que, embora muitos usurios do Hibernate escolham gravar o XML manualmente, existem
diversas ferramentas para gerar o documento de mapeamento, incluindo o XDoclet Middlegen
e AndroMDA.
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="eg">
<class name="Cat"
table="cats"
discriminator-value="C">
<id name="id">
<generator class="native"/>
</id>
<discriminator column="subclass"
type="character"/>
<property name="weight"/>
<property name="birthdate"
type="date"
not-null="true"
update="false"/>
<property name="color"
type="eg.types.ColorUserType"
not-null="true"
update="false"/>
<property name="sex"
not-null="true"
update="false"/>
<property name="litterId"
column="litterId"
update="false"/>
67
Captulo 5. Mapeamento O/R Bsico
<many-to-one name="mother"
column="mother_id"
update="false"/>
<set name="kittens"
inverse="true"
order-by="litter_id">
<key column="mother_id"/>
<one-to-many class="Cat"/>
</set>
<subclass name="DomesticCat"
discriminator-value="D">
<property name="name"
type="string"/>
</subclass>
</class>
<class name="Dog">
<!-- mapping for Dog could go here -->
</class>
</hibernate-mapping
>
5.1.1. Doctype
Todos os mapeamentos de XML devem declarar o doctype exibido. O DTD atual pode ser
encontrado na URL abaixo, no diretrio hibernate-x.x.x/src/org/ hibernate ou no
hibernate3.jar. O Hibernate sempre ir procurar pelo DTD inicialmente no seu classpath. Se
voc tentar localizar o DTD usando uma conexo de internet, compare a declarao do seu DTD
com o contedo do seu classpath.
68
Mapeamento do Hibernate
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC '-//Hibernate/Hibernate Mapping DTD 3.0//EN' 'http://
hibernate.sourceforge.net/hibernate-mapping-3.0.dtd' [
<!ENTITY version "3.5.6-Final">
<!ENTITY today "September 15, 2010">
]>
<hibernate-mapping package="your.domain">
<class name="MyEntity">
<id name="id" type="my-custom-id-type">
...
</id>
<class>
&types;
</hibernate-mapping>
<hibernate-mapping
schema="schemaName"
catalog="catalogName"
default-cascade="cascade_style"
default-access="field|property|ClassName"
default-lazy="true|false"
auto-import="true|false"
package="package.name"
69
Captulo 5. Mapeamento O/R Bsico
/>
Se voc tem duas classes persistentes com o mesmo nome (no qualificadas), voc deve ajustar
auto-import="false". Caso voc tentar ajustar duas classes para o mesmo nome "importado",
isto resultar numa exceo.
Observe que o elemento hibernate-mapping permite que voc aninhe diversos mapeamentos
de <class> persistentes, como mostrado abaixo. Entretanto, uma boa prtica (e esperado
por algumas ferramentas) o mapeamento de apenas uma classe persistente simples (ou
uma hierarquia de classes simples) em um arquivo de mapeamento e nome-la aps a
superclasse persistente, por exemplo: Cat.hbm.xml, Dog.hbm.xml, ou se estiver usando
herana, Animal.hbm.xml.
5.1.3. Classe
Voc pode declarar uma classe persistente utilizando o elemento class. Por exemplo:
<class
name="ClassName"
table="tableName"
discriminator-value="discriminator_value"
mutable="true|false"
schema="owner"
catalog="catalog"
proxy="ProxyInterface"
dynamic-update="true|false"
dynamic-insert="true|false"
select-before-update="true|false"
polymorphism="implicit|explicit"
70
Classe
persister="PersisterClass"
batch-size="N"
optimistic-lock="none|version|dirty|all"
lazy="true|false" (16)
entity-name="EntityName" (17)
check="arbitrary sql check condition" (18)
rowid="rowid" (19)
subselect="SQL expression" (20)
abstract="true|false" (21)
node="element-name"
/>
name (opcional): O nome da classe Java inteiramente qualificado da classe persistente (ou
interface). Se a funo ausente, assume-se que o mapeamento para entidades no-
POJO.
table (opcional padro para nomes de classes no qualificadas): O nome da sua tabela
do banco de dados.
discriminator-value (opcional padro para o nome da classe): Um valor que distingue
subclasses individuais, usadas para o comportamento polimrfico. Valores aceitos incluem
null e not null.
mutable (opcional - valor padro true): Especifica quais instncias da classe so (ou no)
mutveis.
schema (opcional): Sobrepe o nome do esquema especificado pelo elemento raz
<hibernate-mapping>.
catalog (opcional): Sobrepe o nome do catlogo especificado pelo elemento raz
<hibernate-mapping>.
proxy (opcional): Especifica uma interface para ser utilizada pelos proxies de inicializao
lazy. Voc pode especificar o nome da prpria classe.
dynamic-update (opcional, valor padro false): Especifica que o SQL de UPDATE deve
ser gerado em tempo de execuo e conter apenas aquelas colunas cujos valores foram
alterados.
dynamic-insert (opcional, valor padro falso): Especifica que o SQL de INSERT deve ser
gerado em tempo de execuo e conter apenas aquelas colunas cujos valores no esto
nulos.
select-before-update (opcional, valor padro false): Especifica que o Hibernate nunca
deve executar um SQL de UPDATE a no ser que seja certo que um objeto est atualmente
modificado. Em certos casos (na verdade, apenas quando um objeto transiente foi associado
a uma nova sesso utilizando update()), isto significa que o Hibernate ir executar uma
instruo SQL de SELECT adicional para determinar se um UPDATE necessrio nesse
momento.
polymorphism (opcional, padro para implicit): Determina se deve ser utilizado a consulta
polimrfica implcita ou explicitamente.
where (opicional): Especifica um comando SQL WHERE arbitrrio para ser usado quando da
recuperao de objetos desta classe.
persister (opcional): Especifica uma ClassPersister customizada.
71
Captulo 5. Mapeamento O/R Bsico
perfeitamente aceitvel uma classe persitente nomeada ser uma interface. Voc dever ento
declarar as classes implementadas desta interface utilizando o elemento <subclass>. Voc pode
persistir qualquer classe interna esttica. Voc dever especificar o nome da classe usando a
forma padro, por exemplo: eg.Foo$Bar.
A funo opcional proxy habilita a inicializao lazy das instncias persistentes da classe.
O Hibernate ir retornar CGLIB proxies como implementado na interface nomeada. O objeto
persistente atual ser carregado quando um mtodo do proxy for invocado. Veja "Inicializao
de Colees e Proxies" abaixo.
Polimorfismo implcito significa que instncias de uma classe sero retornadas por uma consulta
que d nome a qualquer superclasse ou interface e classe implementada, alm das instncias
de qualquer subclasse da classe sero retornadas por uma consulta que nomeia a classe
por si. Polimorfismo explcito significa que instncias da classe sero retornadas apenas
por consultas que explicitamente nomeiam a classe e que as consultas que nomeiam as
classes iro retornar apenas instncias de subclasses mapeadas dentro da declarao <class>
como uma <subclass> ou <joined-subclass>. Para a maioria dos casos, o valor padro
polymorphism="implicit", apropriado. Polimorfismo explicito til quando duas classes
distintas esto mapeadas para a mesma tabela. Isso aceita uma classe "peso leve" que contm
um subconjunto de colunas da tabela.
72
Classe
No h diferena entre uma viso e uma tabela para o mapeamento do Hibernate, e como
esperado isto transparente no nvel do banco de dados, mesmo que alguns bancos de dados
no suportam vises apropriadamente, especialmente com atualizaes. Algumas vezes, voc
quer utilizar uma viso, mas no pode cri-la no banco de dados (por exemplo, com um esquema
legado). Neste caso, voc pode mapear uma entidade imutvel e de somente leitura, para uma
dada expresso de subseleo SQL:
<class name="Summary">
<subselect>
select item.name, max(bid.amount), count(*)
from item
join bid on bid.item_id = item.id
group by item.name
</subselect>
<synchronize table="item"/>
73
Captulo 5. Mapeamento O/R Bsico
<synchronize table="bid"/>
<id name="name"/>
...
</class
>
Declare as tabelas para sincronizar com esta entidade, garantindo que a auto-liberao
ocorra corretamente, e que as consultas para esta entidade derivada no retornem dados
desatualizados. O <subselect> est disponvel tanto como um atributo como um elemento
mapeado aninhado.
5.1.4. id
Classes mapeadas devem declarar a coluna de chave primria da tabela do banco de dados.
Muitas classes iro tambm ter uma propriedade ao estilo Java-Beans declarando o identificador
nico de uma instncia. O elemento <id> define o mapeamento desta propriedade para a chave
primria.
<id
name="propertyName"
type="typename"
column="column_name"
unsaved-value="null|any|none|undefined|id_value"
access="field|property|ClassName">
node="element-name|@attribute-name|element/@attribute|."
<generator class="generatorClass"/>
</id
>
H uma declarao alternativa <composite-id> que permite o acesso dados legados com
chaves compostas. Ns realmente desencorajamos o uso deste para qualquer outra funo.
74
id
5.1.4.1. Gerador
O elemento filho opcional <generator> nomeia uma classe Java usada para gerar identificadores
nicos para instncias de uma classe persistente. Se algum parmetro requerido para
configurar ou inicializar a instncia geradora, eles so passados utilizando o elemento <param>.
increment
gera identificadores dos tipos long, short ou int que so nicos apenas quando nenhum
outro processo est inserindo dados na mesma tabela. No utilize em ambientes de cluster.
identity
suporta colunas de identidade em DB2, MySQL, Servidor MS SQL, Sybase e HypersonicSQL.
O identificador retornado do tipo long, short ou int.
sequence
utiliza uma seqncia em DB2, PostgreSQL, Oracle, SAP DB, McKoi ou um gerador no
Interbase. O identificador de retorno do tipo long, short ou int.
hilo
utiliza um algoritmo hi/lo para gerar de forma eficiente identificadores do tipo long, short
ou int, a partir de uma tabela e coluna fornecida (por padro hibernate_unique_key e
next_hi) como fonte para os valores hi. O algoritmo hi/lo gera identificadores que so nicos
apenas para um banco de dados especfico.
seqhilo
utiliza um algoritmo hi/lo para gerar de forma eficiente identificadores do tipo long, short ou
int, a partir de uma seqncia de banco de dados fornecida.
uuid
utiliza um algortimo UUID de 128-bits para gerar identificadores do tipo string, nicos em uma
rede (o endereo IP utilizado). O UUID codificado como um string de dgitos hexadecimais
de tamanho 32.
75
Captulo 5. Mapeamento O/R Bsico
guid
utiliza um string GUID gerado pelo banco de dados no Servidor MS SQL e MySQL.
native
seleciona entre identity, sequenceou hilo dependendo das capacidades do banco de
dados utilizado.
assigned
deixa a aplicao definir um identificador para o objeto antes que o save() seja chamado.
Esta a estratgia padro caso nenhum elemento <generator> seja especificado.
select
retorna a chave primria recuperada por um trigger do banco de dados, selecionando uma
linha pela chave nica e recuperando o valor da chave primria.
foreign
utiliza o identificador de um outro objeto associado. Normalmente utilizado em conjunto com
uma associao de chave primria do tipo <one-to-one>.
sequence-identity
uma estratgia de gerao de seqncia especializada que use uma seqncia de banco
de dados para a gerao de valor atual, mas combina isto com JDBC3 getGeneratedKeys
para de fato retornar o valor do identificador gerado como parte da execuo de instruo de
insero. Esta estratgia somente conhecida para suportar drivers da Oracle 10g, focados
em JDK 1.4. Note que os comentrios sobre estas instrues de insero esto desabilitados
devido a um bug nos drivers da Oracle.
76
id
>hi_value</param>
<param name="max_lo"
>100</param>
</generator>
</id
>
Infelizmente, voc no pode utilizar hilo quando estiver fornecendo sua prpria Connection
para o Hibernate. Quando o Hibernate estiver usando uma fonte de dados do servidor de
aplicaes para obter conexes suportadas com JTA, voc precisar configurar adequadamente
o hibernate.transaction.manager_lookup_class.
77
Captulo 5. Mapeamento O/R Bsico
especificado para a propriedade de identificao do objeto. Este gerador usado quando a chave
primria a chave natural em vez de uma chave substituta. Este o comportamento padro se
voc no especificar um elemento <generator>.
78
Otimizao do Gerador de Identificao
79
Captulo 5. Mapeamento O/R Bsico
group. This is the role of the pluggable optimizers. Currently only the two enhanced generators
(Seo 5.1.5, Aprimorao dos geradores de identificador support this operation.
none (geralmente este o padro, caso nenhum otimizador for especificado): isto no
executar quaisquer otimizaes e alcanar o banco de dados para cada e toda solicitao.
hilo: aplica-se ao algoritmo em volta dos valores restaurados do banco de dados. Espera-se
que os valores a partir do banco de dados para este otimizador sejam seqenciais. Os valores
restaurados a partir da estrutura do banco de dados para este otimizador indica um "nmero
de grupo". O increment_size multiplicado pelo valor em memria para definir um grupo "hi
value".
pooled: assim como o caso do hilo, este otimizador tenta minimizar o nmero de tentativas no
banco de dados. No entanto, ns simplesmente implementamos o valor de inicializao para o
"prximo grupo" na estrutura do banco de dados ao invs do valor seqencial na combinao
com um algoritmo de agrupamento em memria. Neste caso, o increment_size refere-se aos
valores de entrada a partir do banco de dados.
5.1.7. Composio-id
<composite-id
name="propertyName"
class="ClassName"
mapped="true|false"
access="field|property|ClassName">
node="element-name|."
Uma tabela com uma chave composta, pode ser mapeada com mltiplas propriedades da classe
como propriedades de identificao. O elemento <composite-id> aceita o mapeamento da
propriedade <key-property> e mapeamentos <key-many-to-one>como elementos filhos.
<composite-id>
<key-property name="medicareNumber"/>
<key-property name="dependent"/>
</composite-id
>
Infelizmente, esta soluo para um identificador composto significa que um objeto persistente
seu prprio identificador. No h outro "handle" conveniente a no ser o prprio objeto.
Voc mesmo precisa instanciar uma instncia de outra classe persistente e preencher suas
80
Discriminador
propriedades de identificao antes que voc possa dar um load() para o estado persistente
associado com uma chave composta. Ns chamamos esta soluo de identificador composto
incorporado e no aconselhamos para aplicaes srias.
Uma segunda soluo seria chamar de identificador composto mapped quando a propriedades
de identificao nomeadas dentro do elemento <composite-id> esto duplicadas tanto na classe
persistente como em uma classe de identificao separada.
mapped (opcional, false por padro): Indica que um identificar composto mapeado usado,
e que as propriedades de mapeamento contidas refere-se tanto classe entidade quanto
classe de identificao composta.
class (opcional, mas requerida para um identificador composto mapeado): A classe usada
como um identificador composto.
We will describe a third, even more convenient approach, where the composite identifier
is implemented as a component class in Seo 8.4, Componentes como identificadores
compostos. The attributes described below apply only to this alternative approach:
name (opcional, requerida para esta abordagem): Uma propriedade do tipo componente que
armazena o identificador composto. Para maiores informaes, por favor consulte o captulo 9.
access (opcional - padro para property): A estratgia que o Hiberante deve utilizar para
acessar o valor da propriedade.
class (opcional - valor padro para o tipo de propriedade determinando por reflexo): A classe
componente utilizada como um identificador composto. Por favor consulte a prxima seo
para maiores informaes.
5.1.8. Discriminador
O elemento <discriminator> necessrio para persistncia polimrfica utilizando a estratgia
de mapeamento de tabela-por-classe-hierrquica e declara uma coluna discriminadora da tabela.
81
Captulo 5. Mapeamento O/R Bsico
<discriminator
column="discriminator_column"
type="discriminator_type"
force="true|false"
insert="true|false"
O atributo force til (apenas) em tabelas contendo linhas com valores discriminadores "extras"
que no esto mapeados para uma classe persistente. Este no geralmente o caso.
Usando o atributo formula voc pode declarar uma expresso SQL arbitrria que ser utilizada
para avaliar o tipo de uma linha. Por exemplo:
<discriminator
formula="case when CLASS_TYPE in ('a', 'b', 'c') then 0 else 1 end"
type="integer"/>
<version
column="version_column"
name="propertyName"
82
Timestamp (opcional)
type="typename"
access="field|property|ClassName"
unsaved-value="null|negative|undefined"
generated="never|always"
insert="true|false"
node="element-name|@attribute-name|element/@attribute|."
/>
column (opcional - tem como padro o nome da propriedade name): O nome da coluna
mantendo o nmero da verso.
name: O nome da propriedade da classe persistente.
type (opcional - padro para integer): O tipo do nmero da verso.
access (opcional - padro para property): A estratgia que o Hiberante deve utilizar para
acessar o valor da propriedade.
unsaved-value (opcional valor padro para undefined ): Um valor para a propriedade
verso que indica que uma instncia foi instanciada recentemente (unsaved), distinguindo
de instncias desconectadas que foram salvas ou carregadas em sesses anteriores.
(undefined especifica que o valor da propriedade de identificao deve ser utilizado).
generated (opcional - valor padro never): Especifica que este valor de propriedade da
verso na verdade gerado pelo banco de dados. Veja o generated properties para maiores
informaes.
insert (opcional - padro para true): Especifica se a coluna de verso deve ser includa
na instruo de insero do SQL. Pode ser configurado como false se a coluna do banco
de dados estiver definida com um valor padro de 0.
Nmeros de verso podem ser dos tipos Hibernate long, integer, short, timestamp ou
calendar.
A verso ou timestamp de uma propriedade nunca deve ser nula para uma instncia
desconectada, assim o Hibernate ir identificar qualquer instncia com uma verso nula ou
timestamp como transiente, no importando qual outra estratgia unsaved-value tenha sido
especificada. A declarao de uma verso nula ou a propriedade timestamp um caminho
fcil para tratar problemas com reconexes transitivas no Hibernate, especialmente teis para
pessoas utilizando identificadores atribudos ou chaves compostas.
<timestamp
column="timestamp_column"
83
Captulo 5. Mapeamento O/R Bsico
name="propertyName"
access="field|property|ClassName"
unsaved-value="null|undefined"
source="vm|db"
generated="never|always"
node="element-name|@attribute-name|element/@attribute|."
/>
column (opcional - padro para o nome da propriedade): O nome da coluna que mantm
o timestamp.
name: O nome da propriedade no estilo JavaBeans do tipo Date ou Timestamp da classe
persistente.
access (opcional - padro para property): A estratgia que o Hiberante deve utilizar para
acessar o valor da propriedade.
unsaved-value (opcional - padro para null): Um valor de propriedade da verso que indica
que uma instncia foi recentemente instanciada (unsaved), distinguindo-a de instncias
desconectadas que foram salvas ou carregadas em sesses prvias. Undefined especifica
que um valor de propriedade de identificao deve ser utilizado.
source (opcional - padro para vm): De onde o Hibernate deve recuperar o valor timestamp?
Do banco de dados ou da JVM atual? Timestamps baseados em banco de dados levam
a um overhead porque o Hibernate precisa acessar o banco de dados para determinar o
"prximo valor", mas mais seguro para uso em ambientes de cluster. Observe tambm,
que nem todos os Dialects suportam a recuperao do carimbo de data e hora atual do
banco de dados, enquanto outros podem no ser seguros para utilizao em bloqueios, pela
falta de preciso (Oracle 8, por exemplo).
generated (opcional - padro para never): Especifica que o valor da propriedade timestamp
gerado pelo banco de dados. Veja a discusso do generated properties para maiores
informaes.
Nota
5.1.11. Propriedade
<property
name="propertyName"
column="column_name"
type="typename"
84
Propriedade
update="true|false"
insert="true|false"
access="field|property|ClassName"
lazy="true|false"
unique="true|false"
not-null="true|false"
optimistic-lock="true|false"
generated="never|insert|always"
node="element-name|@attribute-name|element/@attribute|."
index="index_name"
unique_key="unique_key_id"
length="L"
precision="P"
scale="S"
/>
85
Captulo 5. Mapeamento O/R Bsico
A funo access permite que voc controle como o Hibernate ir acessar a propriedade
em tempo de execuo. Por padro, o Hibernate ir chamar os mtodos get/set da
propriedades. Se voc especificar access="field", o Hibernate ir bipassar os metodos get/
set, acessando o campo diretamente, usando reflexo. Voc pode especificar sua prpria
estratgia para acesso da propriedade criando uma classe que implemente a interface
org.hibernate.property.PropertyAccessor.
<property name="totalPrice"
formula="( SELECT SUM (li.quantity*p.price) FROM LineItem li, Product p
WHERE li.productId = p.productId
AND li.customerId = customerId
AND li.orderNumber = orderNumber )"/>
Observe que voc pode referenciar as entidades da prpria tabela, atravs da no declarao de
um alias para uma coluna particular. Isto seria o customerId no exemplo dado. Observe tambm
que voc pode usar o mapeamento de elemento aninhado <formula>, se voc no gostar de
usar o atributo.
5.1.12. Muitos-para-um
Uma associao ordinria para outra classe persistente declarada usando o elemento many-
to-one. O modelo relacional uma associao muitos para um: uma chave exterior de uma
tabela referenciando as colunas da chave primria da tabela destino.
<many-to-one
name="propertyName"
column="column_name"
86
Muitos-para-um
class="ClassName"
cascade="cascade_style"
fetch="join|select"
update="true|false"
insert="true|false"
property-ref="propertyNameFromAssociatedClass"
access="field|property|ClassName"
unique="true|false"
not-null="true|false"
optimistic-lock="true|false"
lazy="proxy|no-proxy|false"
not-found="ignore|exception"
entity-name="EntityName"
87
Captulo 5. Mapeamento O/R Bsico
not-null (opcional): Habilita a gerao DDL de uma restrio de nulidade para as colunas
de chaves exteriores.
optimistic-lock (opcional - padro para true): Especifica se mudanas para esta
propriedade requerem ou no bloqueio otimista. Em outras palavras, determina se um
incremento de verso deve ocorrer quando esta propriedade est suja.
lazy(opcional padro para proxy): Por padro, associaes de ponto nico so
envoltas em um proxie. lazy="no-proxy" especifica que a propriedade deve ser trazida
de forma tardia quando a instncia da varivel acessada pela primeira vez. Isto
requer instrumentao bytecode em tempo de criao. O lazy="false" especifica que a
associao ser sempre procurada.
not-found (opcional - padro para exception): Especifica como as chaves exteriores que
informam que linhas que estejam faltando sero manuseadas. O ignore tratar a linha
faltante como uma associao nula.
entity-name (opcional): O nome da entidade da classe associada.
formula (optional): Uma instruo SQL que define um valor para uma chave exterior
computed.
Setting a value of the cascade attribute to any meaningful value other than none will propagate
certain operations to the associated object. The meaningful values are divided into three
categories. First, basic operations, which include: persist, merge, delete, save-update,
evict, replicate, lock and refresh; second, special values: delete-orphan; and third,
all comma-separated combinations of operation names: cascade="persist,merge,evict"
or cascade="all,delete-orphan". See Seo 10.11, Persistncia Transitiva for a full
explanation. Note that single valued, many-to-one and one-to-one, associations do not support
orphan delete.
O atributo property-ref deve apenas ser usado para mapear dados legados onde uma chave
exterior se refere uma chave exclusiva da tabela associada que no seja a chave primria.
Este um modelo relacional desagradvel. Por exemplo, suponha que a classe Product tenha
um nmero seqencial exclusivo, que no seja a chave primria. O atributo unique controla a
gerao de DDL do Hibernate com a ferramenta SchemaExport.
88
Um-para-um
5.1.13. Um-para-um
Uma associao um-pra-um para outra classe persistente declarada usando um elemento one-
to-one .
<one-to-one
name="propertyName"
class="ClassName"
cascade="cascade_style"
constrained="true|false"
fetch="join|select"
property-ref="propertyNameFromAssociatedClass"
access="field|property|ClassName"
lazy="proxy|no-proxy|false"
entity-name="EntityName"
node="element-name|@attribute-name|element/@attribute|."
embed-xml="true|false"
foreign-key="foreign_key_name"
/>
89
Captulo 5. Mapeamento O/R Bsico
Associaes de chave primria no necessitam de uma coluna extra de tabela. Se duas linhas
forem relacionadas pela associao, ento as duas linhas da tabela dividem o mesmo valor da
chave primria. Assim, se voc quiser que dois objetos sejam relacionados por uma associao
de chave primria, voc deve ter certeza que foram atribudos com o mesmo valor identificador.
Agora devemos assegurar que as chaves primrias de linhas relacionadas nas tabelas PERSON
e EMPLOYEE so iguais. Ns usamos uma estratgia especial de gerao de identificador do
Hibernate chamada foreign:
90
Id Natural
>employee</param>
</generator>
</id>
...
<one-to-one name="employee"
class="Employee"
constrained="true"/>
</class
>
Uma nova instncia de Person atribuda com o mesmo valor da chave primria da instncia de
Employee referenciada com a propriedade employee daquela Person.
Alternativamente, uma chave exterior com uma restrio nica, de Employee para Person, pode
ser expressada como:
Esta associao pode ser feita de forma bi-direcional adicionando o seguinte no mapeamento
de Person:
5.1.14. Id Natural
<natural-id mutable="true|false"/>
<property ... />
<many-to-one ... />
......
</natural-id
>
Embora recomendemos o uso das chaves substitutas como chaves primrias, voc deve ainda
identificar chaves naturais para todas as entidades. Uma chave natural uma propriedade ou
combinao de propriedades que exclusiva e no nula. Mapeie as propriedades da chave
natural dentro do elemento <natural-id>. O Hibernate ir gerar a chave exclusiva necessria e
as restries de anulabilidade, e seu mapeamento ser apropriadamente auto documentado.
Ns recomendamos com nfase que voc implemente equals() e hashCode() para comparar
as propriedades da chave natural da entidade.
Este mapeamento no pretende ser utilizado com entidades com chaves naturais primrias.
91
Captulo 5. Mapeamento O/R Bsico
<component
name="propertyName"
class="className"
insert="true|false"
update="true|false"
access="field|property|ClassName"
lazy="true|false"
optimistic-lock="true|false"
unique="true|false"
node="element-name|."
>
<property ...../>
<many-to-one .... />
........
</component
>
A tag filha <property> acrescenta a propriedade de mapeamento da classe filha para colunas
de uma tabela.
92
Propriedades
5.1.16. Propriedades
O elemento <properties> permite a definio de um grupo com nome, lgico de propriedades
de uma classe. A funo mais importante do construtor que ele permite que a combinao
de propriedades seja o objetivo de uma property-ref. tambm um modo conveninente para
definir uma restrio nica de mltiplas colunas. Por exemplo:
<properties
name="logicalName"
insert="true|false"
update="true|false"
optimistic-lock="true|false"
unique="true|false"
>
<property ...../>
<many-to-one .... />
........
</properties
>
<class name="Person">
<id name="personNumber"/>
...
<properties name="name"
unique="true" update="false">
<property name="firstName"/>
<property name="initial"/>
<property name="lastName"/>
</properties>
93
Captulo 5. Mapeamento O/R Bsico
</class
>
Ento podemos ter uma associao de dados legados que referem a esta chave exclusiva da
tabela Person, ao invs de se referirem a chave primria:
<many-to-one name="person"
class="Person" property-ref="name">
<column name="firstName"/>
<column name="initial"/>
<column name="lastName"/>
</many-to-one
>
5.1.17. Subclass
<subclass
name="ClassName"
discriminator-value="discriminator_value"
proxy="ProxyInterface"
lazy="true|false"
dynamic-update="true|false"
dynamic-insert="true|false"
entity-name="EntityName"
node="element-name"
extends="SuperclassName">
94
Subclasses Unidas
<joined-subclass
name="ClassName"
table="tablename"
proxy="ProxyInterface"
lazy="true|false"
dynamic-update="true|false"
dynamic-insert="true|false"
schema="schema"
catalog="catalog"
extends="SuperclassName"
persister="ClassName"
subselect="SQL expression"
entity-name="EntityName"
node="element-name">
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
95
Captulo 5. Mapeamento O/R Bsico
<hibernate-mapping package="eg">
<class name="eg.Dog">
<!-- mapping for Dog could go here -->
</class>
</hibernate-mapping
>
<union-subclass
name="ClassName"
table="tablename"
proxy="ProxyInterface"
lazy="true|false"
dynamic-update="true|false"
dynamic-insert="true|false"
schema="schema"
catalog="catalog"
96
Unio
extends="SuperclassName"
abstract="true|false"
persister="ClassName"
subselect="SQL expression"
entity-name="EntityName"
node="element-name">
5.1.20. Unio
Usando o elemento <join>>, possvel mapear propriedades de uma classe para vrias tabelas
que possuem uma relao um por um. Por exemplo:
<join
table="tablename"
schema="owner"
catalog="catalog"
fetch="join|select"
inverse="true|false"
optional="true|false">
97
Captulo 5. Mapeamento O/R Bsico
fetch(opcional valor padro join): Se ajustado para join, o padro, o Hibernate ir usar
uma unio interna para restaurar um join definido por uma classe ou suas subclasses e uma
unio externa para um join definido por uma subclasse. Se ajustado para select, ento o
Hibernate ir usar uma seleo seqencial para um <join> definida numa subclasse, que
ser emitido apenas se uma linha representar uma instncia da subclasse. Unies internas
ainda sero utilizadas para restaurar um <join> definido pela classe e suas superclasses.
inverse (opcional padro para false): Se habilitado, o Hibernate no tentar inserir ou
atualizar as propriedades definidas por esta unio.
optional (opcional padro para false): Se habilitado, o Hibernate ir inserir uma linha
apenas se as propriedades, definidas por esta juno, no forem nulas. Isto ir sempre usar
uma unio externa para recuperar as propriedades.
Por exemplo, a informao de endereo para uma pessoa pode ser mapeada para uma tabela
separada, enquanto preservando o valor da semntica de tipos para todas as propriedades:
<class name="Person"
table="PERSON">
<join table="ADDRESS">
<key column="ADDRESS_ID"/>
<property name="address"/>
<property name="zip"/>
<property name="country"/>
</join>
...
Esta caracterstica til apenas para modelos de dados legados. Ns recomendamos menos
tabelas do que classes e um modelo de domnio fine-grained. Porm, til para ficar trocando
entre estratgias de mapeamento de herana numa hierarquia simples, como explicaremos mais
a frente.
5.1.21. Key
Vimos que o elemento <key> (chave) surgiu algumas vezes at agora. Ele aparece em qualquer
lugar que o elemento pai define uma juno para a nova tabela, e define a chave exterior para a
tabela associada. Ele tambm referencia a chave primria da tabela original:
<key
column="columnname"
on-delete="noaction|cascade"
property-ref="propertyName"
not-null="true|false"
update="true|false"
98
Elementos coluna e frmula
unique="true|false"
/>
column (opcional): O nome da coluna da chave exterior. Isto pode tambm ser especificado
atravs de elementos aninhados <column>.
on-delete (opcional, padro para noaction): Especifica se a restrio da chave exterior no
banco de dados est habilitada para o deletar cascade.
property-ref (opcional): Especifica que a chave exterior se refere a colunas que no so
chave primria da tabela original. til para os dados legados.
not-null (opcional): Especifica que a coluna da chave exterior no aceita valores nulos. Isto
implcito em qualquer momento que a chave exterior tambm fizer parte da chave primria.
update (opcional): Especifica que a chave exterior nunca deve ser atualizada. Isto est
implcito em qualquer momento que a chave exterior tambm fizer parte da chave primria.
unique (opcional): Especifica que a chave exterior deve ter uma restrio nica. Isto ,
implcito em qualquer momento que a chave exterior tambm fizer parte da chave primria.
Ns recomendamos que para sistemas que o desempenho deletar seja importante, todas as
chaves devem ser definidas on-delete="cascade". O Hibernate ir usar uma restrio a nvel
de banco de dados ON CASCADE DELETE, ao invs de muitas instrues DELETE. Esteja ciente
que esta caracterstica um atalho da estratgia usual de bloqueio otimista do Hibernate para
dados versionados.
<column
name="column_name"
length="N"
precision="N"
scale="N"
not-null="true|false"
unique="true|false"
unique-key="multicolumn_unique_key_name"
index="index_name"
sql-type="sql_type_name"
check="SQL expression"
default="SQL expression"
read="SQL expression"
write="SQL expression"/>
99
Captulo 5. Mapeamento O/R Bsico
<formula
>SQL expression</formula
>
A maioria das funes no column fornecem um significado de juno do DDL durante a gerao
automtica do esquema. As funes read e write permitem que voc especifique o SQL
personalizado, do qual o Hibernate usar para acessar o valor da coluna. Consulte a discusso
da column read and write expressions para maiores informaes.
5.1.23. Importar
Vamos supor que a sua aplicao tenha duas classes persistentes com o mesmo nome, e voc
no quer especificar o nome qualificado do pacote nas consultas do Hibernate. As Classes
devero ser "importadas" explicitamente, de preferncia contando com auto-import="true".
Voc pode at importar classes e interfaces que no esto explicitamente mapeadas:
<import
class="ClassName"
rename="ShortName"
/>
5.1.24. Any
100
Any
requer mais de uma coluna. A primeira coluna possui o tipo da entidade associada. A outra
coluna restante possui o identificador. impossvel especificar uma restrio de chave exterior
para este tipo de associao, portanto isto certamente no visto como um caminho usual para
associaes (polimrficas) de mapeamento. Voc deve usar este mapeamento apenas em casos
muito especiais. Por exemplo: audit logs, dados de sesso do usurio, etc.
A funo meta-type permite que a aplicao especifique um tipo adaptado que mapeia valores de
colunas de banco de dados para classes persistentes que possuem propriedades identificadoras
do tipo especificado atravs do id-type. Voc deve especificar o mapeamento de valores do
meta-type para nome de classes.
<any
name="propertyName"
id-type="idtypename"
meta-type="metatypename"
cascade="cascade_style"
access="field|property|ClassName"
optimistic-lock="true|false"
>
<meta-value ... />
<meta-value ... />
.....
<column .... />
<column .... />
.....
</any
>
101
Captulo 5. Mapeamento O/R Bsico
Uma entidade existe independentemente de qualquer outro objeto guardando referncias para
a entidade. Em contraste com o modelo usual de Java que um objeto no referenciado
coletado pelo coletor de lixo. Entidades devem ser explicitamente salvas ou deletadas (exceto em
operaes de salvamento ou deleo que possam ser executada em cascata de uma entidade pai
para seus filhos). Isto diferente do modelo ODMG de persistncia do objeto por acessibilidade
e se refere mais forma como os objetos de aplicaes so geralmente usados em grandes
sistemas. Entidades suportam referncias circulares e comuns. Eles podem ser versionados.
102
Valores de tipos bsicos
Todos os tipos internos do hibernate exceto colees, suportam semnticas nulas com a exceo
das colees.
integer, long, short, float, double, character, byte, boolean, yes_no, true_false
Tipos de mapeamentos de classes primitivas ou wrapper Java especficos (vendor-specific)
para tipos de coluna SQL. Boolean, boolean, yes_no so todas codificaes alternativas
para um boolean ou java.lang.Boolean do Java.
string
Um tipo de mapeamento de java.lang.String para VARCHAR (ou VARCHAR2 no Oracle).
calendar, calendar_date
Tipo de mapeamento de java.util.Calendar para os tipos SQL TIMESTAMP e DATE (ou
equivalente).
big_decimal, big_integer
Tipo de mapeamento de java.math.BigDecimal and java.math.BigInteger para NUMERIC
(ou NUMBER no Oracle).
class
Um tipo de mapeamento de java.lang.Class para VARCHAR (ou VARCHAR2 no Oracle). Uma
Class mapeada pelo seu nome qualificado (completo).
binary
Mapeia matrizes de bytes para um tipo binrio de SQL apropriado.
text
Mapeia strings de Java longos para um tipo SQL CLOB ou TEXT.
serializable
Mapeia tipos Java serializveis para um tipo binrio SQL apropriado. Voc pode tambm
indicar o tipo serializable do Hibernate com o nome da classe ou interface Java serializvel
que no padro para um tipo bsico.
103
Captulo 5. Mapeamento O/R Bsico
clob, blob
Tipos de mapeamentos para as classes JDBC java.sql.Clob and java.sql.Blob. Estes
tipos podem ser inconvenientes para algumas aplicaes, visto que o objeto blob ou clob
no pode ser reusado fora de uma transao. Alm disso, o suporte de driver imcompleto
e inconsistente.
Identificadores nicos das entidades e colees podem ser de qualquer tipo bsico exceto
binary, blob ou clob. (Identificadores compostos tambm so permitidos. Leia abaixo para
maiores informaes.
Observe o uso da tag <column> para mapear uma propriedade para colunas mltiplas.
Voc mesmo pode fornecer parmetros a um UserType no arquivo de mapeamento. Para isto,
seu UserType deve implementar a interface org.hibernate.usertype.ParameterizedType.
104
Mapeando uma classe mais de uma vez
Para fornecer parmetros a seu tipo personalizado, voc pode usar o elemento <type> em seus
arquivos de mapeamento.
<property name="priority">
<type name="com.mycompany.usertypes.DefaultValueIntegerType">
<param name="default"
>0</param>
</type>
</property
>
O UserType pode agora recuperar o valor para o parmetro chamado padro da Propriedade
do passado a ele.
Se voc usar freqentemente um determinado UserType, pode ser til definir um nome mais
curto para ele. Voc pode fazer isto usando o elemento <typedef>. Typedefs atribui um nome
a um tipo personalizado, e pode tambm conter uma lista de valores de parmetro padro se o
tipo for parametrizado.
105
Captulo 5. Mapeamento O/R Bsico
106
Usando a marcao XDoclet.
neste documento, uma vez que estritamente considerado parte de um XDoclet. No entanto,
inclumos os seguintes exemplos da classe Cat com os mapeamentos de XDoclet:
package eg;
import java.util.Set;
import java.util.Date;
/**
* @hibernate.class
* table="CATS"
*/
public class Cat {
private Long id; // identifier
private Date birthdate;
private Cat mother;
private Set kittens
private Color color;
private char sex;
private float weight;
/*
* @hibernate.id
* generator-class="native"
* column="CAT_ID"
*/
public Long getId() {
return id;
}
private void setId(Long id) {
this.id=id;
}
/**
* @hibernate.many-to-one
* column="PARENT_ID"
*/
public Cat getMother() {
return mother;
}
void setMother(Cat mother) {
this.mother = mother;
}
/**
* @hibernate.property
* column="BIRTH_DATE"
*/
public Date getBirthdate() {
return birthdate;
}
void setBirthdate(Date date) {
birthdate = date;
}
/**
* @hibernate.property
* column="WEIGHT"
*/
107
Captulo 5. Mapeamento O/R Bsico
/**
* @hibernate.property
* column="COLOR"
* not-null="true"
*/
public Color getColor() {
return color;
}
void setColor(Color color) {
this.color = color;
}
/**
* @hibernate.set
* inverse="true"
* order-by="BIRTH_DATE"
* @hibernate.collection-key
* column="PARENT_ID"
* @hibernate.collection-one-to-many
*/
public Set getKittens() {
return kittens;
}
void setKittens(Set kittens) {
this.kittens = kittens;
}
// addKitten not needed by Hibernate
public void addKitten(Cat kitten) {
kittens.add(kitten);
}
/**
* @hibernate.property
* column="SEX"
* not-null="true"
* update="false"
*/
public char getSex() {
return sex;
}
void setSex(char sex) {
this.sex=sex;
}
}
Veja o web site do Hibernate para maiores detalhes sobre um XDoclet e Hibernate.
108
Propriedades geradas
suportado pelas ferramentas e IDEs. O IntelliJ IDEA por exemplo, suporta a auto complexo e
destaque da sintaxe das anotaes JDK 5.0. A nova reviso da especificao EJB (JSR-220) usa
as anotaes JDK 5.0 como mecanismos de metadados para beans de entidade. O Hibernate3
implementa o EntityManager do JSR-220 (o API de persistncia). O suporte para mapear
metadados est disponvel atravs do pacote Anotaes do Hibernate, como um download
separado. Ambos os EJB3 (JSR-220) e o metadado Hibernate3 so suportados.
Este um exemplo de uma classe POJO anotado como um bean de entidade EJB:
@Entity(access = AccessType.FIELD)
public class Customer implements Serializable {
@Id;
Long id;
String firstName;
String lastName;
Date birthday;
@Transient
Integer age;
@Embedded
private Address homeAddress;
@OneToMany(cascade=CascadeType.ALL)
@JoinColumn(name="CUSTOMER_ID")
Set<Order
> orders;
Nota
Note que o suporte para Anotaes JDK 5.0 (e JSR-220) ainda est em
construo. Consulte o mdulo de Anotaes do Hibernate para maiores detalhes.
109
Captulo 5. Mapeamento O/R Bsico
never (padro) - significa que o valor de propriedade dado no gerado dentro do banco de
dados.
insert: informa que o valor de propriedade dado gerado ao inserir, mas no novamente
gerado nas prximas atualizaes. Propriedades do tipo data criada, se encaixam nesta
categoria. Note que embora as propriedades version e timestamp podem ser marcadas como
geradas, esta opo no est disponvel.
always - informa que o valor da propriedade gerado tanto ao inserir quanto ao atualizar.
<property name="creditCardNumber">
<column
name="credit_card_num"
read="decrypt(credit_card_num)"
write="encrypt(?)"/>
</property
>
Esta propriedade suportada por uma ou mais colunas que so exportadas como parte da
gerao do esquema automtico.
Esta propriedade de gravao-leitura, e no de leitura apenas.
110
Objetos de Banco de Dados Auxiliares
<hibernate-mapping>
...
<database-object>
<create
>CREATE TRIGGER my_trigger ...</create>
<drop
>DROP TRIGGER my_trigger</drop>
</database-object>
</hibernate-mapping
>
O segundo mdulo para fornecer uma classe padro que sabe como construir
os comandos CREATE e DROP. Esta classe padro deve implementar a interface
org.hibernate.mapping.AuxiliaryDatabaseObject.
<hibernate-mapping>
...
<database-object>
<definition class="MyTriggerDefinition"/>
</database-object>
</hibernate-mapping
>
Alm disso, estes objetos de banco de dados podem ter um escopo opcional que s ser aplicado
quando certos dialetos forem utilizados.
<hibernate-mapping>
...
<database-object>
<definition class="MyTriggerDefinition"/>
<dialect-scope name="org.hibernate.dialect.Oracle9iDialect"/>
<dialect-scope name="org.hibernate.dialect.Oracle10gDialect"/>
</database-object>
</hibernate-mapping
>
111
112
Mapeamento de coleo
6.1. Colees persistentes
O Hibernate requer que os campos de colees de valor persistente sejam declarados como um
tipo de interface. Por exemplo:
Observe como inicializamos a varivel da instncia com uma instncia de HashSet. Esta a
melhor maneira de inicializar propriedades de colees de valor de instncias recentemente
instanciadas (no persistentes). Quando voc fizer uma instncia persistente, chamando
persist(), como por exemplo: o Hibernate substituir o HashSet por uma instncia da prpria
implementao do Hibernate do Set. Cuidado com erros como este:
113
Captulo 6. Mapeamento de col...
Use as colees persistentes da mesma forma que usa colees Java comuns. No entanto,
somente tenha a certeza de entender as semnticas de associaes bidirecionais (as quais sero
discutidas mais tarde).
Dica
O elemento do mapeamento do Hibernate, usado para mapear uma coleo, depende do tipo de
interface. Por exemplo, um elemento <set> usado para mapear propriedades do tipo Set.
<class name="Product">
<id name="serialNumber" column="productSerialNumber"/>
<set name="parts">
<key column="productSerialNumber" not-null="true"/>
<one-to-many class="Part"/>
</set>
</class
>
Alm do <set>, existe tambm os elementos de mapeamento <list>, <map>, <bag>, <array>
and <primitive-array>. O elemento <map> de representao:
<map
name="propertyName"
table="table_name"
schema="schema_name"
lazy="true|extra|false"
inverse="true|false"
cascade="all|none|save-update|delete|all-delete-orphan|delete-orphan"
sort="unsorted|natural|comparatorClass"
order-by="column_name asc|desc"
fetch="join|select|subselect"
batch-size="N"
114
Mapeamento de coleo
access="field|property|ClassName"
optimistic-lock="true|false"
mutable="true|false"
node="element-name|."
embed-xml="true|false"
>
115
Captulo 6. Mapeamento de col...
Pode existir uma restrio de nulabilidade na coluna da chave exterior. Para a maioria das
colees, isto est implcito. Para associaes unidirecionais um-para-muitos, a coluna de chave
estrangeira anulvel por padro, portanto voc pode precisar especificar not-null="true".
<list-index
column="column_name"
116
Colees de valores e associaes muitos-para-muitos
base="0|1|..."/>
column_name (required): the name of the column holding the collection index values.
base (optional - defaults to 0): the value of the index column that corresponds to the first
element of the list or array.
<map-key
column="column_name"
type="type_name"
node="@attribute-name"
length="N"/>
column (optional): the name of the column holding the collection index values.
formula (optional): a SQL formula used to evaluate the key of the map.
type (required): the type of the map keys.
<map-key-many-to-many
column="column_name"
column (optional): the name of the foreign key column for the collection index values.
formula (optional): a SQ formula used to evaluate the foreign key of the map key.
class (required): the entity class used as the map key.
Se sua tabela no possui uma coluna de ndice e voc ainda quiser usar a Lista como tipo de
propriedade, voc deve mapeiar a propriedade como uma <bag> do Hibernate. Uma bag no
mantm sua ordem quando recuperadada do banco de dados, mas pode ser escolhida de forma
opcional ou ordenada.
Para uma coleo com valores, utilizamos a tag <element>. Por exemplo:
<element
column="column_name"
117
Captulo 6. Mapeamento de col...
type="typename"
length="L"
precision="P"
scale="S"
not-null="true|false"
unique="true|false"
node="element-name"
/>
column (optional): the name of the column holding the collection element values.
formula (optional): an SQL formula used to evaluate the element.
type (required): the type of the collection element.
<many-to-many
column="column_name"
class="ClassName"
fetch="select|join"
unique="true|false"
not-found="ignore|exception"
entity-name="EntityName"
property-ref="propertyNameFromAssociatedClass"
node="element-name"
embed-xml="true|false"
/>
118
Colees de valores e associaes muitos-para-muitos
Um conjunto de strings:
Uma bag contendo inteiros com uma ordem de iterao determinada pelo atributo order-by):
<bag name="sizes"
table="item_sizes"
order-by="size asc">
<key column="item_id"/>
<element column="size" type="integer"/>
</bag
>
<array name="addresses"
table="PersonAddress"
cascade="persist">
<key column="personId"/>
<list-index column="sortOrder"/>
<many-to-many column="addressId" class="Address"/>
</array
>
<map name="holidays"
table="holidays"
schema="dbo"
order-by="hol_name asc">
<key column="id"/>
<map-key column="hol_name" type="string"/>
<element column="hol_date" type="date"/>
</map
>
<list name="carComponents"
table="CarComponents">
119
Captulo 6. Mapeamento de col...
<key column="carId"/>
<list-index column="sortOrder"/>
<composite-element class="CarComponent">
<property name="price"/>
<property name="type"/>
<property name="serialNumber" column="serialNum"/>
</composite-element>
</list
>
Uma associao um para muitos liga as tabelas das duas classes atravs de uma chave exterior,
sem a interveno da tabela de coleo. Este mapeamento perde um pouco da semntica das
colees normais do Java:
Uma instncia de classes entidades contidas, podem no pertencer mais de uma instncia
da coleo.
Uma instncia da classe de entidade contida pode no aparecer em mais de um valor do ndice
da coleo.
Uma associao a partir do Produto at a Parte requer a existncia de uma coluna de chave
exterior e possivelmente uma coluna de ndice para a tabela Part Uma tag <one-to-many> indica
que esta uma associao um para muitos.
<one-to-many
class="ClassName"
not-found="ignore|exception"
entity-name="EntityName"
node="element-name"
embed-xml="true|false"
/>
Note que o elemento <one-to-many> no precisa declarar qualquer coluna. Nem necessrio
especificar o nome da table em qualquer lugar.
120
Mapeamentos de coleo avanados.
Ateno
Este exemplo demonstra um mapa das entidades Part por nome, onde partName uma
propriedade persistente de Part. Note que o uso de um ndice baseado em frmula:
<map name="parts"
cascade="all">
<key column="productId" not-null="true"/>
<map-key formula="partName"/>
<one-to-many class="Part"/>
</map
>
<set name="aliases"
table="person_aliases"
sort="natural">
<key column="person"/>
<element column="name" type="string"/>
</set>
121
Captulo 6. Mapeamento de col...
Se voc quiser que o prprio banco de dados ordene os elementos da coleo use a funo
order-by do set, bag ou mapeamentos map. Esta soluo est disponvel somente sob JDK
1.4 ou verses posteriores e implementada usando LinkedHashSet ou LinkedHashMap). Este
desempenha a ordenao na consulta SQL, no em memria.
Nota
Associaes podem tambm ser escolhidas por algum critrio arbritrrio em tempo de espera
usando uma coleo filter():
Um-para-muitos
conjunto ou bag de valor em um dos lados, valor nico do outro
Muitos-para-muitos
Conjunto ou bag com valor em ambos os lados
122
Associaes Bidirecionais
<class name="Category">
<id name="id" column="CATEGORY_ID"/>
...
<bag name="items" table="CATEGORY_ITEM">
<key column="CATEGORY_ID"/>
<many-to-many class="Item" column="ITEM_ID"/>
</bag>
</class>
<class name="Item">
<id name="id" column="ITEM_ID"/>
...
Voc pode definir uma associao bidirecional um para muitos atravs de uma associao
um-para-muitos indicando as mesmas colunas da tabela que associao muitos-para-um e
declarando a propriedade inverse="true".
<class name="Parent">
<id name="id" column="parent_id"/>
....
<set name="children" inverse="true">
<key column="parent_id"/>
<one-to-many class="Child"/>
</set>
</class>
<class name="Child">
<id name="id" column="child_id"/>
123
Captulo 6. Mapeamento de col...
....
<many-to-one name="parent"
class="Parent"
column="parent_id"
not-null="true"/>
</class
>
Mapear apenas uma das pontas da associao com inverse="true" no afeta as operaes
em cascata, uma vez que isto um conceito ortogonal.
<class name="Parent">
<id name="id" column="parent_id"/>
....
<map name="children" inverse="true">
<key column="parent_id"/>
<map-key column="name"
type="string"/>
<one-to-many class="Child"/>
</map>
</class>
<class name="Child">
<id name="id" column="child_id"/>
....
<property name="name"
not-null="true"/>
<many-to-one name="parent"
class="Parent"
column="parent_id"
not-null="true"/>
</class
>
Mas, se no houver nenhuma propriedade na classe filha, no podemos ver essa associao
como verdadeiramente bidirecional (h uma informao disponvel em um lado da associao
que no est disponvel no extremo oposto). Nesse caso, ns no podemos mapear a coleo
usando inverse="true". Devemos usar o seguinte mapeamento:
<class name="Parent">
<id name="id" column="parent_id"/>
....
<map name="children">
<key column="parent_id"
124
Associaes Ternrias
not-null="true"/>
<map-key column="name"
type="string"/>
<one-to-many class="Child"/>
</map>
</class>
<class name="Child">
<id name="id" column="child_id"/>
....
<many-to-one name="parent"
class="Parent"
column="parent_id"
insert="false"
update="false"
not-null="true"/>
</class
>
Veja que neste mapeamento, o lado de coleo vlida da associao responsvel pela
atualizao da chave exterior.
<map name="contracts">
<key column="employer_id" not-null="true"/>
<map-key-many-to-many column="employee_id" class="Employee"/>
<one-to-many class="Contract"/>
</map
>
<map name="connections">
<key column="incoming_node_id"/>
<map-key-many-to-many column="outgoing_node_id" class="Node"/>
<many-to-many column="connection_id" class="Connection"/>
</map
>
Uma alternativa final usar os elementos compostos, que ns discutiremos mais tarde.
A maioria das associaes e colees muitos para muitos de valores apresentados anteriormente
mapeiam s tabelas com as chaves de composio, mesmo que foi sugerido que as entidades
125
Captulo 6. Mapeamento de col...
devem ser identificadores sintticos (chaves substitutas). Uma tabela de associao pura no
parece tirar muito proveito de uma chave substituta, mesmo que uma coleo de valores
compostos usufruam disto. por este motivo que o Hibernate prov uma maneira de mapear uma
associao muitos para muitos com uma coleo de valores para uma tabela com uma chave
substituta.
O elemento <idbag> permite mapear um List (ou uma Collection) com uma semntica de
bag. Por exemplo:
O <idbag> possui um gerador de id sinttico, igual a uma classe de entidade. Uma chave
substituta diferente associada para cada elemento de coleo. Porm, o Hibernate no prov
de nenhum mecanismo para descobrir qual a chave substituta de uma linha em particular.
package eg;
import java.util.Set;
....
....
126
Exemplos de colees
Se cada Filho tiver no mximo um Pai, o mapeamento natural uma associao um para muitos:
<hibernate-mapping>
<class name="Parent">
<id name="id">
<generator class="sequence"/>
</id>
<set name="children">
<key column="parent_id"/>
<one-to-many class="Child"/>
</set>
</class>
<class name="Child">
<id name="id">
<generator class="sequence"/>
</id>
<property name="name"/>
</class>
</hibernate-mapping
>
<hibernate-mapping>
<class name="Parent">
<id name="id">
<generator class="sequence"/>
</id>
<set name="children" inverse="true">
<key column="parent_id"/>
<one-to-many class="Child"/>
</set>
</class>
<class name="Child">
<id name="id">
<generator class="sequence"/>
</id>
<property name="name"/>
127
Captulo 6. Mapeamento de col...
</hibernate-mapping
>
Uma outra alternativa, no caso de voc insistir que esta associao deva ser unidirecional, voc
pode declarar a restrio como NOT NULL no mapeamento <key>:
<hibernate-mapping>
<class name="Parent">
<id name="id">
<generator class="sequence"/>
</id>
<set name="children">
<key column="parent_id" not-null="true"/>
<one-to-many class="Child"/>
</set>
</class>
<class name="Child">
<id name="id">
<generator class="sequence"/>
</id>
<property name="name"/>
</class>
</hibernate-mapping
>
Por outro lado, se um filho puder ter os mltiplos pais, a associao apropriada ser muitos-para-
muitos:
<hibernate-mapping>
<class name="Parent">
<id name="id">
<generator class="sequence"/>
</id>
<set name="children" table="childset">
128
Exemplos de colees
<key column="parent_id"/>
<many-to-many class="Child" column="child_id"/>
</set>
</class>
<class name="Child">
<id name="id">
<generator class="sequence"/>
</id>
<property name="name"/>
</class>
</hibernate-mapping
>
For more examples and a complete explanation of a parent/child relationship mapping, see
Captulo 22, Exemplo: Pai/Filho for more information.
129
130
Mapeamento de associaes
7.1. Introduo
Os mapeamentos de associaes so, geralmente, os mais difceis de se acertar. Nesta
seo ns examinaremos pelos casos cannicos um por um, comeando com mapeamentos
unidirecionais e considerando os casos bidirecionais. Usaremos Person e Address em todos os
exemplos.
O uso de chaves externas anulveis no considerado uma boa prtica na modelagem de dados
tradicional, assim todos os nossos exemplos usam chaves externas anulveis. Esta no uma
exigncia do Hibernate, e todos os mapeamentos funcionaro se voc remover as restries de
anulabilidade.
7.2.1. Muitos-para-um
<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<many-to-one name="address"
column="addressId"
not-null="true"/>
</class>
<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
</class
>
create table Person ( personId bigint not null primary key, addressId bigint not null )
create table Address ( addressId bigint not null primary key )
131
Captulo 7. Mapeamento de ass...
7.2.2. Um-para-um
Uma associao unidirecional um-para-um em uma chave externa quase idntica. A nica
diferena a restrio nica na coluna.
<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<many-to-one name="address"
column="addressId"
unique="true"
not-null="true"/>
</class>
<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
</class
>
create table Person ( personId bigint not null primary key, addressId bigint not null unique )
create table Address ( addressId bigint not null primary key )
<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
</class>
<class name="Address">
<id name="id" column="personId">
<generator class="foreign">
<param name="property"
>person</param>
</generator>
</id>
<one-to-one name="person" constrained="true"/>
</class
>
132
Um-para-muitos
7.2.3. Um-para-muitos
Uma associao unidirecional um-para-muitos em uma chave externa um caso muito incomum,
e realmente no recomendada.
<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<set name="addresses">
<key column="personId"
not-null="true"/>
<one-to-many class="Address"/>
</set>
</class>
<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
</class
>
Acreditamos ser melhor usar uma tabela associativa para este tipo de associao.
<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<set name="addresses" table="PersonAddress">
133
Captulo 7. Mapeamento de ass...
<key column="personId"/>
<many-to-many column="addressId"
unique="true"
class="Address"/>
</set>
</class>
<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
</class
>
7.3.2. Muitos-para-um
Uma associao unidirecional muitos-para-um em uma tabela associativa bastante comum
quando a associao for opcional.
<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<join table="PersonAddress"
optional="true">
<key column="personId" unique="true"/>
<many-to-one name="address"
column="addressId"
not-null="true"/>
</join>
</class>
<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
</class
>
134
Um-para-um
7.3.3. Um-para-um
<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<join table="PersonAddress"
optional="true">
<key column="personId"
unique="true"/>
<many-to-one name="address"
column="addressId"
not-null="true"
unique="true"/>
</join>
</class>
<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
</class
>
7.3.4. Muitos-para-muitos
<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<set name="addresses" table="PersonAddress">
<key column="personId"/>
<many-to-many column="addressId"
class="Address"/>
</set>
</class>
<class name="Address">
<id name="id" column="addressId">
135
Captulo 7. Mapeamento de ass...
<generator class="native"/>
</id>
</class
>
7.4.1. Um-para-muitos/muitos-para-um
<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<many-to-one name="address"
column="addressId"
not-null="true"/>
</class>
<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
<set name="people" inverse="true">
<key column="addressId"/>
<one-to-many class="Person"/>
</set>
</class
>
create table Person ( personId bigint not null primary key, addressId bigint not null )
create table Address ( addressId bigint not null primary key )
Se voc usar uma List ou outra coleo indexada, voc precisar especificar a coluna key da
chave externa como not null. O Hibernate administrar a associao do lado da coleo para
136
Um-para-um
que seja mantido o ndice de cada elemento da coleo (fazendo com que o outro lado seja
virtualmente inverso ajustando update="false" e insert="false"):
<class name="Person">
<id name="id"/>
...
<many-to-one name="address"
column="addressId"
not-null="true"
insert="false"
update="false"/>
</class>
<class name="Address">
<id name="id"/>
...
<list name="people">
<key column="addressId" not-null="true"/>
<list-index column="peopleIdx"/>
<one-to-many class="Person"/>
</list>
</class
>
Caso uma coluna chave externa adjacente for NOT NULL, importante que voc defina not-
null="true" no elemento <key> no mapeamento na coleo se a coluna de chave externa para
NOT NULL. No declare como not-null="true" apenas um elemento aninhado <column>, mas
sim o elemento <key>.
7.4.2. Um-para-um
<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<many-to-one name="address"
column="addressId"
unique="true"
not-null="true"/>
</class>
<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
<one-to-one name="person"
property-ref="address"/>
</class
>
137
Captulo 7. Mapeamento de ass...
create table Person ( personId bigint not null primary key, addressId bigint not null unique )
create table Address ( addressId bigint not null primary key )
Uma associao bidirecional um para um em uma chave primria usa um gerador de id especial:
<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<one-to-one name="address"/>
</class>
<class name="Address">
<id name="id" column="personId">
<generator class="foreign">
<param name="property"
>person</param>
</generator>
</id>
<one-to-one name="person"
constrained="true"/>
</class
>
7.5.1. Um-para-muitos/muitos-para-um
Segue abaixo uma amostra da associao bidirecional um para muitos em uma tabela de unio.
Veja que inverse="true" pode ser colocado em qualquer ponta da associao, na coleo, ou
na unio.
<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<set name="addresses"
table="PersonAddress">
<key column="personId"/>
138
Um para um
<many-to-many column="addressId"
unique="true"
class="Address"/>
</set>
</class>
<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
<join table="PersonAddress"
inverse="true"
optional="true">
<key column="addressId"/>
<many-to-one name="person"
column="personId"
not-null="true"/>
</join>
</class
>
7.5.2. Um para um
Uma associao bidirecional um-para-um em uma tabela de unio algo bastante incomum,
mas possvel.
<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<join table="PersonAddress"
optional="true">
<key column="personId"
unique="true"/>
<many-to-one name="address"
column="addressId"
not-null="true"
unique="true"/>
</join>
</class>
<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
<join table="PersonAddress"
optional="true"
139
Captulo 7. Mapeamento de ass...
inverse="true">
<key column="addressId"
unique="true"/>
<many-to-one name="person"
column="personId"
not-null="true"
unique="true"/>
</join>
</class
>
7.5.3. Muitos-para-muitos
<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<set name="addresses" table="PersonAddress">
<key column="personId"/>
<many-to-many column="addressId"
class="Address"/>
</set>
</class>
<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
<set name="people" inverse="true" table="PersonAddress">
<key column="addressId"/>
<many-to-many column="personId"
class="Person"/>
</set>
</class
>
140
Mapeamento de associaes mais complexas
<properties name="currentAccountKey">
<property name="accountNumber" type="string" not-null="true"/>
<property name="currentAccount" type="boolean">
<formula
>case when effectiveEndDate is null then 1 else 0 end</formula>
</property>
</properties>
<property name="effectiveEndDate" type="date"/>
<property name="effectiveStateDate" type="date" not-null="true"/>
Ento ns podemos mapear uma associao para a instncia atual, aquela com
effectiveEndDate nulo, usando:
<many-to-one name="currentAccountInfo"
property-ref="currentAccountKey"
class="AccountInfo">
<column name="accountNumber"/>
<formula
>'1'</formula>
</many-to-one
>
<join>
<key column="employeeId"/>
<subselect>
select employeeId, orgId
from Employments
group by orgId
having startDate = max(startDate)
</subselect>
<many-to-one name="mostRecentEmployer"
class="Organization"
141
Captulo 7. Mapeamento de ass...
column="orgId"/>
</join
>
Esta funcionalidade permite um grau de criatividade e flexibilidade, mas geralmente mais prtico
tratar estes tipos de casos, usando uma pesquisa HQL ou uma pesquisa por critrio.
142
Mapeamento de Componentes
A noo de componente re-utilizada em vrios contextos diferentes, para propsitos diferentes,
pelo Hibernate.
143
Captulo 8. Mapeamento de Com...
Agora Name pode ser persistido como um componente de Person. Note que Name define mtodos
getter e setter para suas propriedades persistentes, mas no necessita declarar nenhuma
interface ou propriedades identificadoras.
A tabela person teria as seguintes colunas pid, birthday, initial, first and last.
Assim como todos tipos por valor, componentes no suportam referncias cruzadas. Em outras
palavras, duas persons podem ter o mesmo nome, mas os dois objetos person podem ter dois
objetos de nome independentes, apenas "o mesmo" por valor. A semntica dos valores null de
um componente so ad hoc. No recarregameno do contedo do objeto, o Hibernate entender
que se todas as colunas do componente so null, ento todo o componente null. Isto seria o
certo para a maioria dos propsitos.
144
Colees de objetos dependentes
Importante
145
Captulo 8. Mapeamento de Com...
No pode haver uma referncia de compra no outro lado, para a navegao da associao
bidirecional. Lembre-se que componentes so tipos por valor e no permitem referncias
compartilhadas. Uma classe Purchase simples pode estar no conjunto de uma classe Order, mas
ela no pode ser referenciada por Item no mesmo momento.
Elementos compostos podem aparecer em pesquisas usando a mesma sintaxe assim como
associaes para outras entidades.
146
Componentes como identificadores compostos
Nota
Voc no pode usar um IdentifierGenerator para gerar chaves compostas. Ao invs disso, o
aplicativo deve gerenciar seus prprios identificadores.
<class name="OrderLine">
<property name="name"/>
</class
>
Agora, qualquer chave exterior referenciando a tabela OrderLine tambm ser composta. Voc
deve declarar isto em seus mapeamentos para outras classes. Uma associao para OrderLine
seria mapeada dessa forma:
147
Captulo 8. Mapeamento de Com...
<column name="lineId"/>
<column name="orderId"/>
<column name="customerId"/>
</many-to-one
>
Dica
Uma associao many-to-many para many-to-many tambm usa a chave estrangeira composta:
<set name="undeliveredOrderLines">
<key column name="warehouseId"/>
<many-to-many class="OrderLine">
<column name="lineId"/>
<column name="orderId"/>
<column name="customerId"/>
</many-to-many>
</set
>
Se OrderLine possui uma coleo, ela tambm tem uma chave externa composta.
<class name="OrderLine">
....
....
<list name="deliveryAttempts">
<key
> <!-- a collection inherits the composite key type -->
<column name="lineId"/>
<column name="orderId"/>
148
Componentes Dinmicos
<column name="customerId"/>
</key>
<list-index column="attemptId" base="1"/>
<composite-element class="DeliveryAttempt">
...
</composite-element>
</set>
</class
>
<dynamic-component name="userAttributes">
<property name="foo" column="FOO" type="string"/>
<property name="bar" column="BAR" type="integer"/>
<many-to-one name="baz" class="Baz" column="BAZ_ID"/>
</dynamic-component
>
149
150
Mapeamento de Herana
9.1. As trs estratgias
O Hibernate suporta as trs estratgias bsicas de mapeamento de herana:
polimorfismo implcito
<hibernate-mapping>
<subclass name="DomesticCat" extends="Cat" discriminator-value="D">
<property name="name" type="string"/>
</subclass>
</hibernate-mapping
>
151
Captulo 9. Mapeamento de Her...
requisitado exatamente uma tabela. Existe uma grande limitao desta estratgia de
mapeamento: colunas declaradas por subclasses, tais como CCTYPE, podem no ter restries
NOT NULL.
152
Tabela por subclasse: usando um discriminador
Voc pode at mesmo mesclar a estratgia de tabela por hierarquia e tabela por subclasse
usando esta abordagem:
153
Captulo 9. Mapeamento de Her...
Para qualquer uma dessas estratgias de mapeamento, uma associao polimrfica para a
classe raz Payment deve ser mapeada usando <many-to-one>.
Existem duas formas que poderamos usar a respeito da estratgia de mapeamento de tabela
por classe concreta. A primeira usar <union-subclass>.
<class name="Payment">
<id name="id" type="long" column="PAYMENT_ID">
<generator class="sequence"/>
</id>
<property name="amount" column="AMOUNT"/>
...
<union-subclass name="CreditCardPayment" table="CREDIT_PAYMENT">
<property name="creditCardType" column="CCTYPE"/>
...
</union-subclass>
<union-subclass name="CashPayment" table="CASH_PAYMENT">
...
</union-subclass>
<union-subclass name="ChequePayment" table="CHEQUE_PAYMENT">
...
</union-subclass>
</class
>
154
Tabela por classe concreta usando polimorfismo implcito
Trs tabelas esto envolvidas para as subclasses. Cada tabela define colunas para todas as
propriedades da classe, incluindo propriedades herdadas.
Se sua superclasse abstrata, mapeie-a com abstract="true". Claro, que se ela no for
abstrata, uma tabela adicional (padro para PAYMENT no exemplo acima), ser necessria para
segurar as instncias da superclasse.
Veja que em nenhum lugar mencionamos a interface Payment explicitamente. Note tambm
que propriedades de Payment so mapeadas em cada uma das subclasses. Se voc quiser
evitar duplicao, considere usar entidades de XML (ex. [ <!ENTITY allproperties SYSTEM
"allproperties.xml"> ] na declarao do DOCTYPE e & allproperties; no mapeamento).
A desvantagem dessa abordagem que o Hibernate no gera UNIONs de SQL quando executa
pesquisas polimrficas.
155
Captulo 9. Mapeamento de Her...
Para essa estratgia, uma associao polimrfica para Payment geralmente mapeada usando
<any>.
Existe ainda um item a ser observado sobre este mapeamento. Como as subclasses so
mapeadas em seu prprio elemento <class>, e como o Payment apenas uma interface, cada
uma das subclasses pode ser facilmente parte de uma outra hierarquia de herana! (E voc ainda
pode usar pesquisas polimrficas em cima da interface Payment.)
156
Limitaes
9.2. Limitaes
Existem certas limitaes para a abordagem do "polimorfismo implcito" comparada com a
estratgia de mapeamento da tabela por classe concreta. Existe uma limitao um tanto menos
restritiva para mapeamentos <union-subclass>.
157
158
Trabalhando com objetos
O Hibernate uma soluo completa de mapeamento objeto/relacional que no apenas poupa
o desenvolvedor dos detalhes de baixo nvel do sistema de gerenciamento do banco de dados,
como tambm oferece um gerenciamento de estado para objetos. Isto , ao contrrio do
gerenciamento de instrues SQL em camadas de persistncia JDBC/SQL comuns, uma viso
natural da persistncia orientada a objetos em aplicaes Java.
Transient - um objeto transiente se ele foi instanciando usando apenas o operador new e
no foi associado a uma Session do Hibernate. Ele no possui uma representao persistente
no banco de dados e no lhe foi atribudo nenhum identificador. Instncias transientes sero
destrudas pelo coletor de lixo se a aplicao no mantiver sua referncia. Use uma Session
do Hibernate para tornar o objeto persistente (e deixe o Hibernate gerenciar as instrues SQL
que sero necessrias para executar esta transio).
Detached uma instncia desanexada um objeto que foi persistido, mas sua Session
foi fechada. A referncia ao objeto continua vlida, claro, e a instncia desanexada pode
ser acoplada a uma nova Session no futuro, tornando-o novamente persistente (e todas as
modificaes sofridas). Essa caracterstica habilita um modelo de programao para unidades
de trabalho de longa execuo, que requeira um tempo de espera do usurio. Podemos cham-
las de transaes da aplicao, ou seja, uma unidade de trabalho do ponto de vista do usurio.
Agora iremos discutir os estados e suas transies (e os mtodos do Hibernate que disparam
uma transio) em mais detalhes.
159
Captulo 10. Trabalhando com ...
Se Cat possui um identificador gerado, o identificador gerado e atribudo cat quando save()
for chamado. Se Cat possuir um identificador Associado, ou uma chave composta, o identificador
dever ser atribudo instncia de cat antes que save() seja chamado. Pode-se usar tambm
persist() ao invs de save(), com a semntica definida no novo esboo do EJB3.
persist() faz uma instncia transciente persistente. No entanto, isto no garante que o valor
do identificador ser determinado instncia persistente imediatamente, pois a determinao
pode acontecer no perodo de limpeza. O persist() tambm garante que isto no executar
uma declarao INSERT caso esta seja chamada fora dos limites da transao. Isto til em
transaes de longa-execuo com um contexto de Sesso/persistncia estendido.
save() garante retornar um identificador. Caso um INSERT necessita ser executado para
obter o identificador (ex.: gerador "identidade" e no "seqncia"), este INSERT acontece
imediatamente, independente de voc estar dentro ou fora da transao. Isto problemtico
numa conversao de longa execuo com um contexto de Sesso/persistncia estendido.
Se o objeto persistido tiver associado objetos (ex.: a coleo kittens no exemplo anterior), esses
objetos podem se tornar persistentes em qualquer ordem que se queira, a no ser que se tenha
uma restrio NOT NULL em uma coluna de chave estrangeira. Nunca h risco de violao de
restries de chave estrangeira. Assim, pode-se violar uma restrio NOT NULL se save() for
usado nos objetos em uma ordem errada.
Geralmente voc no precisa se preocupar com esses detalhes, pois muito provavelmente
usar a caracterstica de persistncia transitiva do Hibernate para salvar os objetos associados
automaticamente. Assim, enquanto uma restrio NOT NULL no ocorrer, o Hibernate tomar
conta de tudo. Persistncia transitiva ser discutida mais adiante nesse mesmo captulo.
160
Carregando o objeto
Repare que load() ir lanar uma exceo irrecupervel se no houver na tabela no banco de
dados um registro que combine. Se a classe for mapeada com um proxy, load() simplesmente
retorna um proxy no inicializado e realmente no chamar o banco de dados at que um
mtodo do proxy seja invocado. Esse comportamento muito til para criar uma associao
com um objeto sem que realmente o carregue do bando de dados. Isto tambm permite que
sejam carregadas mltiplas instncias como um grupo se o batch-size estiver definido para o
mapeamento da classe.
Se voc no tiver certeza da existncia do registro no banco, voc deve usar o mtodo get(),
que consulta o banco imediatamente e retorna um null se no existir o registro.
Tambm pode-se carregar um objeto usando SELECT ... FOR UPDATE, usando um LockMode.
Veja a documentao da API para maiores informaes.
161
Captulo 10. Trabalhando com ...
sess.save(cat);
sess.flush(); //force the SQL INSERT
sess.refresh(cat); //re-read the state (after the trigger executes)
How much does Hibernate load from the database and how many SQL SELECTs will it use? This
depends on the fetching strategy. This is explained in Seo 20.1, Estratgias de Busca .
10.4. Consultando
Se o identificador do objeto que se est buscando no for conhecido, ser necessrio realizar
uma consulta. O Hibernate suporta uma linguagem de consulta (HQL) orientada a objetos fceis
de usar, porm poderosos. Para criao via programao de consultas, o Hibernate suporta
caractersticas sofisticadas de consulta por Critrio e Exemplo (QBCe QBE). Pode-se tambm
expressar a consulta por meio de SQL nativa do banco de dados, com suporte opcional do
Hibernate para converso do conjunto de resultados em objetos.
162
Executando consultas
.setEntity(0, izi)
.uniqueResult();]]
Geralmente uma consulta executada ao invocar list().O resultado da consulta ser carregado
completamente em uma coleo na memria. Instncias de entidades recuperadas por uma
consulta esto no estado persistente. O uniqueResult() oferece um atalho se voc souber
previamente, que a consulta retornar apenas um nico objeto. Repare que consultas que fazem
uso da busca antecipada (eager fetching) de colees, geralmente retornam duplicatas dos
objetos raiz, mas com suas colees inicializadas. Pode-se filtrar estas duplicatas atravs de um
simples Set.
// fetch ids
Iterator iter = sess.createQuery("from eg.Qux q order by q.likeliness").iterate();
while ( iter.hasNext() ) {
Qux qux = (Qux) iter.next(); // fetch the object
// something we couldnt express in the query
if ( qux.calculateComplicatedAlgorithm() ) {
// delete the current instance
iter.remove();
// dont need to process the rest
break;
}
}
Algumas vezes as consultas do Hibernate retornam tuplas de objetos. Cada tupla retornada
como uma matriz:
163
Captulo 10. Trabalhando com ...
while ( kittensAndMothers.hasNext() ) {
Object[] tuple = (Object[]) kittensAndMothers.next();
Cat kitten = (Cat) tuple[0];
Cat mother = (Cat) tuple[1];
....
}
As consultas devem especificar uma propriedade da classe na clusula select. Elas tambm
podem chamar funes SQL de agregaes. Propriedades ou agregaes so consideradas
resultados agregados e no entidades no estado persistente.
while ( results.hasNext() ) {
Object[] row = (Object[]) results.next();
Color type = (Color) row[0];
Date oldest = (Date) row[1];
Integer count = (Integer) row[2];
.....
}
//positional parameter
Query q = sess.createQuery("from DomesticCat cat where cat.name = ?");
q.setString(0, "Izi");
164
Executando consultas
10.4.1.5. Paginao
Se voc precisar especificar vnculos do conjunto de resultados, o mximo de nmeros por linha
que quiser recuperar e/ou a primeira linha que quiser recuperar, voc deve usar mtodos de
interface Consulta:
O Hibernate sabe como traduzir esta consulta de limite para a SQL nativa de seu DBMS
Se seu driver JDBC driver suportar ResultSets rolveis, a interface da Consulta poder ser
usada para obter um objeto de ScrollableResults, que permite uma navegao flexvel dos
resultados de consulta.
// find the first name on each page of an alphabetical list of cats by name
firstNamesOfPages = new ArrayList();
do {
String name = cats.getString(0);
firstNamesOfPages.add(name);
}
while ( cats.scroll(PAGE_SIZE) );
165
Captulo 10. Trabalhando com ...
}
cats.close()
Note que uma conexo aberta de banco de dados (e cursor) requerida para esta funo, use
setMaxResult()/setFirstResult() se precisar da funo de paginao offline.
<query name="ByNameAndMaximumWeight"
><![CDATA[
from eg.DomesticCat as cat
where cat.name = ?
and cat.weight
> ?
] ]></query
>
Query q = sess.getNamedQuery("ByNameAndMaximumWeight");
q.setString(0, name);
q.setInt(1, minWeight);
List cats = q.list();
Note que o cdigo de programa atual independente da linguagem de consulta que utilizada,
voc tambm pode definir as consultas SQL nativas no metadado, ou migrar consultas existentes
para o Hibernate, colocando-os em arquivos de mapeamento.
166
Consulta por critrio
A coleo retornada considerada uma bolsa, e a cpia da coleo dada. A coleo original no
modificada. Ela oposta implicao do nome "filtro", mas consistente com o comportamento
esperado.
Observe que os filtros no requerem uma clusula from embora possam ter um, se requerido.
Os filtros no so limitados a retornar aos elementos de coleo.
At mesmo um filtro vazio til, ex.: para carregar um subconjunto em uma coleo enorme:
The Criteria and the associated Example API are discussed in more detail in Captulo 16,
Consultas por critrios.
Voc pode expressar uma consulta em SQL utilizando createSQLQuery() e deixar o Hibernate
tomar conta do mapeamento desde conjuntos de resultados at objetos. Note que voc
pode chamar uma session.connection() a qualquer momento e usar a Connection JDBC
diretamente. Se voc escolher utilizar a API Hibernate, voc deve incluir as aliases SQL dentro
de chaves:
167
Captulo 10. Trabalhando com ...
SQL queries can contain named and positional parameters, just like Hibernate queries. More
information about native SQL queries in Hibernate can be found in Captulo 17, SQL Nativo.
Algumas vezes, este modelo de programao ineficiente, uma vez que ele requer ambos SQL
SELECT (para carregar um objeto) e um SQLUPDATE (para persistir seu estado atualizado) na
mesma sesso. Por isso, o Hibernate oferece uma abordagem alternativa, usando instncias
desanexadas.
Importante
Hibernate does not offer its own API for direct execution of UPDATE or DELETE
statements. Hibernate is a state management service, you do not have to think
in statements to use it. JDBC is a perfect API for executing SQL statements,
you can get a JDBC Connection at any time by calling session.connection().
Furthermore, the notion of mass operations conflicts with object/relational
mapping for online transaction processing-oriented applications. Future versions
168
Modificando objetos desacoplados
Use update() se voc tiver certeza de que a sesso j no contm uma instncia persistente
com o mesmo identificador, e merge() se voc quiser mesclar suas modificaes a qualquer
momento sem considerar o estado da sesso. Em outras palavras, update() geralmente o
primeiro mtodo que voc chama em uma nova sesso, assegurando que o re-acoplamento de
suas instncias seja a primeira operao executada.
The application should individually update() detached instances that are reachable from the given
detached instance only if it wants their state to be updated. This can be automated using transitive
persistence. See Seo 10.11, Persistncia Transitiva for more information.
O mtodo lock() tambm permite que um aplicativo re-associe um objeto com uma nova sesso.
No entanto, a instncia desanexada no pode ser modificada.
//just reassociate:
sess.lock(fritz, LockMode.NONE);
//do a version check, then reassociate:
sess.lock(izi, LockMode.READ);
//do a version check, using SELECT ... FOR UPDATE, then reassociate:
sess.lock(pk, LockMode.UPGRADE);
169
Captulo 10. Trabalhando com ...
Note que lock() pode ser usado com diversos LockModes, veja a documentao API e o captulo
sobre manuseio de transaes para maiores informaes. Re-acoplamento no o nico caso
de uso para lock().
Other models for long units of work are discussed in Seo 12.3, Controle de concorrncia
otimista.
O uso e semntica do saveOrUpdate() parecem ser confusos para novos usurios. A princpio,
enquanto voc no tentar usar instncias de uma sesso em outra nova sesso, no precisar
utilizar update(), saveOrUpdate(), ou merge(). Algumas aplicaes inteiras nunca precisaro
utilizar estes mtodos.
170
Apagando objetos persistentes
se existir uma instncia persistente com um mesmo identificador associado atualmente com a
sesso, copie o estado do objeto dado para a instncia persistente.
se no existir uma instncia persistente atualmente associada com a sesso, tente carreg-la
a partir do banco de dados, ou crie uma nova instncia persistente
a instncia persistente retornada
a instncia dada no se torna associada com a sesso, ela permanece desanexada
sess.delete(cat);
Voc poder deletar objetos na ordem que desejar, sem risco de violao de restrio da chave
estrangeira. possvel violar uma restrio NOT NULL em uma coluna de chave estrangeira,
apagando objetos na ordem inversa, ex.: se apagar o pai, mas esquecer de apagar o filho.
171
Captulo 10. Trabalhando com ...
O caso de uso para este recurso inclui dados de reconciliao em instncias de banco de dados
diferentes, atualizando informaes da configurao do sistema durante a atualizao do produto,
retornando mudanas realizadas durante transaes no ACID entre outras funes.
Uma exceo que o objeto que utiliza a gerao de ID native inserido quando salvo.
Exceto quando voc explicitamente limpar(), no h nenhuma garantia sobre quando a Sesso
executar as chamadas de JDBC, somente se sabe a ordem na qual elas so executadas.
No entanto, o Hibernate garante que a Query.list(..) nunca retornar dados antigos, nem
retornar dados errados.
It is possible to change the default behavior so that flush occurs less frequently. The FlushMode
class defines three different modes: only flush at commit time when the Hibernate Transaction
API is used, flush automatically using the explained routine, or never flush unless flush() is
called explicitly. The last mode is useful for long running units of work, where a Session is kept
172
Persistncia Transitiva
open and disconnected for a long time (see Seo 12.3.2, Sesso estendida e versionamento
automtico).
sess = sf.openSession();
Transaction tx = sess.beginTransaction();
sess.setFlushMode(FlushMode.COMMIT); // allow queries to return stale state
During flush, an exception might occur (e.g. if a DML operation violates a constraint). Since
handling exceptions involves some understanding of Hibernate's transactional behavior, we
discuss it in Captulo 12, Transaes e Concorrncia .
Agora considere o mesmo cenrio com objeto pai e filho sendo entidades, e no de valores
(ex.: categorias e tens, ou cats pai e filho). As entidades possuem seus prprios ciclos de vida,
suportam referncias compartilhadas (portanto, remover uma entidade da coleo no significa
que possa ter sido deletada), e no existe efeito cascata de estado, por padro, a partir de uma
entidade para outras entidades associadas. O Hibernate no implementa persistncia por alcance
por padro.
173
Captulo 10. Trabalhando com ...
Voc pode at utilizar cascade="all" para especificar que todas as operaes devem estar em
cascata junto associao. O padro cascade="none" especifica que nenhuma operao deve
estar em cascata.
Recomendaes:
Ao mapear uma associao (tanto uma associao de valor nico como uma coleo) com casca
de="all", a associao demarcada como um relacionamento de estilo parent/child onde salvar/
atualizar/deletar do pai, resulta em salvar/atualizar/deletar do(s) filho(s).
Alm disso, uma mera referncia ao filho de um pai persistente ir resultar em salvar/atualizar/
o filho. Entretanto, esta metfora est incompleta. Um filho, que no referenciado por seu
pai no deletado automaticamente, exceto no caso de uma associao <one-to-many>
mapeada com casca de="delete-orphan". A semntica exata, de operaes em cascata para
o relacionamento pai/filho, so como as que se seguem:
174
Usando metadados
Finalmente, note que o cascateamento das operaes podem ser aplicados a um grafo de objeto
em tempo de chamada ou em tempo de limpeza. Todas as operaes, se habilitadas, so
colocadas em cascata para entidades associadas atingveis quando a operao for executada.
No entanto, save-upate e delete-orphan so transitivas para todas as entidades associadas
atingveis durante a limpeza da Sesso.
175
176
Read-only entities
Importante
Hibernate's treatment of read-only entities may differ from what you may have
encountered elsewhere. Incorrect usage may cause unexpected results.
Hibernate does not dirty-check the entity's simple properties or single-ended associations;
Hibernate will not update the version of the read-only entity if only simple properties or single-
ended updatable associations are changed;
In some ways, Hibernate treats read-only entities the same as entities that are not read-only:
Hibernate updates the version if the entity has a collection with changes that dirties the entity;
Even if an entity is not read-only, its collection association can be affected if it contains a read-
only entity.
For details about the affect of read-only entities on different property and association types, see
Seo 11.2, Read-only affect on property type.
For details about how to make entities read-only, see Seo 11.1, Making persistent entities
read-only
177
Captulo 11. Read-only entities
you can map an entity class as immutable; when an entity of an immutable class is made
persistent, Hibernate automatically makes it read-only. see Seo 11.1.1, Entities of immutable
classes for details
you can change a default so that entities loaded into the session by Hibernate are automatically
made read-only; see Seo 11.1.2, Loading persistent entities as read-only for details
you can make an HQL query or criteria read-only so that entities loaded when the query or
criteria executes, scrolls, or iterates, are automatically made read-only; see Seo 11.1.3,
Loading read-only entities from an HQL query/criteria for details
you can make a persistent entity that is already in the in the session read-only; see Seo 11.1.4,
Making a persistent entity read-only for details
An entity of an immutable class can created and deleted the same as an entity of a mutable class.
Hibernate treats a persistent entity of an immutable class the same way as a read-only persistent
entity of a mutable class. The only exception is that Hibernate will not allow an entity of an
immutable class to be changed so it is not read-only.
Nota
To change the default behavior so Hibernate loads entity instances of mutable classes into the
session and automatically makes them read-only, call:
Session.setDefaultReadOnly( true );
To change the default back so entities loaded by Hibernate are not made read-only, call:
Session.setDefaultReadOnly( false );
178
Loading read-only entities from an HQL query/criteria
Session.isDefaultReadOnly();
Session.load()
Session.get()
Session.merge()
executing, scrolling, or iterating HQL queries and criteria; to override this setting for a particular
HQL query or criteria see Seo 11.1.3, Loading read-only entities from an HQL query/criteria
persistent entities already in the session when the default was changed
persistent entities that are refreshed via Session.refresh(); a refreshed persistent entity will only
be read-only if it was read-only before refreshing
Nota
If Session.isDefaultReadOnly() returns false (the default) when an HQL query or criteria executes,
then entities and proxies of mutable classes loaded by the query will not be read-only.
You can override this behavior so that entities and proxies loaded by an HQL query or criteria are
automatically made read-only.
Query.setReadOnly( true );
179
Captulo 11. Read-only entities
Criteria.setReadOnly( true );
Entities and proxies that exist in the session before being returned by an HQL query or criteria
are not affected.
Uninitialized persistent collections returned by the query are not affected. Later, when
the collection is initialized, entities loaded into the session will be read-only if
Session.isDefaultReadOnly() returns true.
When it is not possible to load and initialize all necessary entities in a single query or criteria,
you can temporarily change the session default to load entities as read-only before the query is
executed. Then you can explicitly initialize proxies and collections before restoring the session
default.
setDefaultReadOnly( true );
Contract contract =
( Contract ) session.createQuery(
"from Contract where customerName = 'Sherman'" )
.uniqueResult();
Hibernate.initialize( contract.getPlan() );
Hibernate.initialize( contract.getVariations() );
Hibernate.initialize( contract.getNotes() );
setDefaultReadOnly( false );
...
tx.commit();
session.close();
If Session.isDefaultReadOnly() returns true, then you can use Query.setReadOnly( false ) and
Criteria.setReadOnly( false ) to override this session setting and load entities that are not read-
only.
Nota
180
Read-only affect on property type
Session.setReadOnly(entityOrProxy, true)
Session.setReadOnly(entityOrProxy, false)
Importante
To throw away non-flushed changes and make the persistent entity consistent with its database
representation, call:
session.refresh( entity );
To flush changes made before or while the entity was read-only and make the database
representation consistent with the current state of the persistent entity:
181
Captulo 11. Read-only entities
* Behavior is different when the entity having the property/association is read-only, compared to
when it is not read-only.
When a persistent object is read-only, Hibernate does not dirty-check simple properties.
Hibernate will not synchronize simple property state changes to the database. If you have
automatic versioning, Hibernate will not increment the version if any simple properties change.
// contract.getCustomerName() is "Sherman"
contract.setCustomerName( "Yogi" );
182
Unidirectional associations
tx.commit();
tx = session.beginTransaction();
Hibernate treats unidirectional one-to-one and many-to-one associations in the same way when
the owning entity is read-only.
We use the term unidirectional single-ended association when referring to functionality that is
common to unidirectional one-to-one and many-to-one associations.
Hibernate does not dirty-check unidirectional single-ended associations when the owning entity
is read-only.
Nota
If automatic versioning is used, Hibernate will not increment the version due to local changes to
unidirectional single-ended associations.
In the following examples, Contract has a unidirectional many-to-one association with Plan.
Contract cascades save and update operations to the association.
The following shows that changing a read-only entity's many-to-one association reference to null
has no effect on the entity's database representation.
183
Captulo 11. Read-only entities
contract.setPlan( null );
tx.commit();
tx.commit();
session.close();
The following shows that, even though an update to a read-only entity's many-to-one association
has no affect on the entity's database representation, flush still cascades the save-update
operation to the locally changed association.
tx.commit();
session.close();
The collection can contain entities that are read-only, as well as entities that are not read-only.
Entities can be added and removed from the collection; changes are flushed to the database.
If automatic versioning is used, Hibernate will update the version due to changes in the collection
if they dirty the owning entity.
184
Bidirectional associations
updates that change the association reference to null or to refer to a different entity will not be
flushed to the database.
If automatic versioning is used, Hibernate will not increment the version due to local changes
to the association.
Nota
When the owner is not read-only, Hibernate treats an association with a read-only entity the same
as when the association is with an entity that is not read-only.
the one-to-many side uses a non-inverse collection that contains the read-only entity
a read-only entity can only be removed from the collection by an orphan delete or by explicitly
deleting the entity.
Hibernate treats bidirectional many-to-many associations owned by a read-only entity the same
as when owned by an entity that is not read-only.
185
Captulo 11. Read-only entities
The collection on either side of the association can contain entities that are read-only, as well as
entities that are not read-only.
Entities are added and removed from both sides of the collection; changes are flushed to the
database.
If automatic versioning is used, Hibernate will update the version due to changes in both sides of
the collection if they dirty the entity owning the respective collections.
186
Transaes e Concorrncia
O fator mais importante sobre o Hibernate e o controle de concorrncia que muito fcil de ser
compreendido. O Hibernate usa diretamente conexes de JDBC e recursos de JTA sem adicionar
nenhum comportamento de bloqueio a mais. Recomendamos que voc gaste algum tempo com
o JDBC, o ANSI e a especificao de isolamento de transao de seu sistema de gerncia da
base de dados.
Uma Session um objeto de baixo custo de criao, no threadsafe, deve ser usado uma vez,
para uma nica requisio, uma conversao, uma nica unidade do trabalho e ento deve ser
descartado. Um Session no obter um JDBC Connection, ou um Datasource, a menos que
necessite. Isto no consome nenhum recurso at ser usado.
Uma transao precisa ser o mais curta possvel, para reduzir a disputa pelo bloqueio na base de
dados. Transaes longas impediro que sua aplicao escale a carga altamente concorrente.
Por isso, no bom manter uma transao de base de dados aberta durante o tempo que o
usurio pensa, at que a unidade do trabalho esteja completa.
Qual o escopo de uma unidade de trabalho? Pode uma nica Session do Hibernate gerenciar
diversas transaes ou este um o relacionamento um-para-um dos escopos? Quando voc
deve abrir e fechar uma Session e como voc demarca os limites da transao? Estas questes
esto endereadas nas seguintes sees.
187
Captulo 12. Transaes e Con...
of changes and the resolution of concurrency problems. [PoEAA] In other words, its a series of
operations we wish to carry out against the database together. Basically, it is a transaction, though
fulfilling a unit of work will often span multiple physical database transactions (see Seo 12.1.2,
Longas conversaes). So really we are talking about a more abstract notion of a transaction.
The term "business transaction" is also sometimes used in lieu of unit of work.
Primeiro, no use o antipattern sesso-por-operao: isto , no abra e feche uma Session para
cada simples chamada ao banco de dados em uma nica thread. Naturalmente, o mesmo se
aplica s transaes do banco de dados. As chamadas ao banco de dados em uma aplicao so
feitas usando uma seqncia planejada, elas so agrupadas em unidades de trabalho atmicas.
Veja que isso tambm significa que realizar um auto-commit depois de cada instruo SQL
intil em uma aplicao, esta modalidade ideal para o trabalho ad hoc do console do SQL. O
Hibernate impede, ou espera que o servidor de aplicao impessa isso, aplique a modalidade
auto-commit imediatamente. As transaes de banco de dados nunca so opcionais, toda a
comunicao com um banco de dados tem que ocorrer dentro de uma transao, no importa se
voc vai ler ou escrever dados. Como explicado, o comportamento auto-commit para leitura de
dados deve ser evitado, uma vez que muitas transaes pequenas so improvveis de executar
melhor do que uma unidade de trabalho claramente definida. A ltima opo tambm muito
mais sustentvel e expandida.
Your application code can access a "current session" to process the request by calling
sessionFactory.getCurrentSession(). You will always get a Session scoped to the current
database transaction. This has to be configured for either resource-local or JTA environments,
see Seo 2.5, Sesses Contextuais.
188
Longas conversaes
utilizam uma fase de renderizao separada depois da requisio ter sido processada. Estender
a transao at que a renderizao da viso esteja completa fcil de fazer se voc implementar
seu prprio interceptador. Entretanto, no ser fcil se voc confiar em EJBs com transaes
gerenciadas por recipiente, porque uma transao ser terminada quando um mtodo de EJB
retornar, antes que a renderizao de toda viso possa comear. Veja o website e o frum do
Hibernate para dicas e exemplos em torno deste modelo de Sesso Aberta na Visualizao.
A primeira tela de um dilogo se abre e os dados vistos pelo usurio so carregados em uma
Session e transao de banco de dados particulares. O usurio est livre para modificar os
objetos.
O usurio clica em "Salvar" aps 5 minutos e espera suas modificaes serem persistidas. O
usurio tambm espera que ele seja a nica pessoa que edita esta informao e que nenhuma
modificao conflitante possa ocorrer.
Uma primeira implementao simples pode manter a Session e a transao aberta durante o
tempo de interao do usurio, com bloqueios na base de dados para impedir a modificao
concorrente e para garantir o isolamento e a atomicidade. Esse naturalmente um anti-pattern,
uma vez que a disputa do bloqueio no permitiria o escalonameneto da aplicao com o nmero
de usurios concorrentes.
Claramente, temos que usar diversas transaes para implementar a conversao. Neste caso,
manter o isolamento dos processos de negcio, torna-se responsabilidade parcial da camada
da aplicao. Uma nica conversao geralmente usa diversas transaes. Ela ser atmica
se somente uma destas transaes (a ltima) armazenar os dados atualizados, todas as outras
simplesmente leram os dados (por exemplo em um dilogo do estilo wizard que mede diversos
ciclos de requisio/resposta). Isto mais fcil de implementar do parece, especialmente se voc
usar as caractersticas do Hibernate:
189
Captulo 12. Transaes e Con...
usurio estiver pensando. O Hibernate permite que voc re-anexe os objetos e persista
as modificaes, esse pattern chamado sesso-por-solicitao-com-objetos-desanexados.
Utiliza-se versionamento automtico para isolar as modificaes concorrentes.
Sesso Estendida (ou Longa) A Session do Hibernate pode ser desligada da conexo
adjacente do JDBC depois que a transao foi submetida, e ser reconectada quando uma
nova requisio do cliente ocorrer. Este pattern conhecido como sesso-por-conversao
e faz o reatamento uniforme desnecessrio. Versionamento automtico usado para
isolar modificaes concorrentes e a sesso-por-conversao geralmente pode ser nivelada
automaticamente, e sim explicitamente.
Identidade da JVM
foo==bar
Ento para os objetos acoplados a uma Session especfica (ex.: isto est no escopo de
uma Session), as duas noes so equivalentes e a identidade da JVM para a identidade
da base de dados garantida pelo Hibernate. Entretanto, embora a aplicao possa acessar
concorrentemente o "mesmo" objeto do negcio (identidade persistente) em duas sesses
diferentes, as duas instncias sero realmente "diferentes" (identidade de JVM). Os conflitos
so resolvidos usando (versionamento automtico) no flush/commit, usando uma abordagem
otimista.
No entanto, uma aplicao que usa == fora de uma Session, pode ver resultados inesperados.
Isto pode ocorrer mesmo em alguns lugares inesperados, por exemplo, se voc colocar duas
instncias desacopladas em um mesmo Set. Ambas podem ter a mesma identidade na base de
dados (ex.: elas representam a mesma linha), mas a identidade da JVM no , por definio,
garantida para instncias em estado desacoplado. O desenvolvedor tem que substituir os
mtodos equals() e hashCode() em classes persistentes e implementar sua prpria noo da
190
Edies comuns
igualdade do objeto. Advertncia: nunca use o identificador da base de dados para implementar a
igualdade, use atributos de negcio, uma combinao nica, geralmente imutvel. O identificador
da base de dados mudar se um objeto transiente passar para o estado persistente. Se a instncia
transiente (geralmente junto com instncias desacopladas) for inserida em um Set, a mudana
do hashcode quebrar o contrato do Set. As funes para chaves de negcio no tm que
ser to estvel quanto s chaves primrias da base de dados, voc somente tem que garantir
a estabilidade durante o tempo que os objetos estiverem no mesmo Set. Veja o website do
Hibernate para uma discusso mais completa sobre o assunto. Note tambm que esta no uma
caracterstica do Hibernate, mas simplesmente a maneira como a identidade e a igualdade do
objeto de Java tm que ser implementadas.
Uma exceo lanada pelo Hibernate significa que voc tem que dar rollback na sua transao
no banco de dados e fechar a Session imediatamente (discutido mais tarde em maiores
detalhes). Se sua Session limitada pela aplicao, voc tem que parar a aplicao. Fazer o
rollback na transao no banco de dados no retorna seus objetos do negcio ao estado que
estavam no incio da transao. Isto significa que o estado da base de dados e os objetos de
negcio perdem a sincronizao. Geralmente, no um problema porque as excees no
so recuperveis e voc tem que iniciar aps o rollback de qualquer maneira.
The Session caches every object that is in a persistent state (watched and checked for dirty
state by Hibernate). If you keep it open for a long time or simply load too much data, it will
grow endlessly until you get an OutOfMemoryException. One solution is to call clear() and
evict() to manage the Session cache, but you should consider a Stored Procedure if you need
mass data operations. Some solutions are shown in Captulo 14, Batch processing. Keeping a
Session open for the duration of a user session also means a higher probability of stale data.
191
Captulo 12. Transaes e Con...
liberar a sesso
submeter a transao
fechar a sesso
tratar as excees
A liberao da sesso j foi bem discutida, agora ns daremos uma olhada na demarcao da
transao e na manipulao de exceo em ambientes controlados e no controlados.
// do some work
...
tx.commit();
192
Usando JTA
}
catch (RuntimeException e) {
if (tx != null) tx.rollback();
throw e; // or display error message
}
finally {
sess.close();
}
Uma soluo muito mais flexvel o gerenciamento de contexto "sesso atual" da construo
interna do Hibernate, como descrito anteriormente:
// do some work
...
factory.getCurrentSession().getTransaction().commit();
}
catch (RuntimeException e) {
factory.getCurrentSession().getTransaction().rollback();
throw e; // or display error message
}
Voc muito provavelmente nunca ver estes fragmentos de cdigo em uma aplicao regular; as
excees fatais (do sistema) devem sempre ser pegas no "topo". Ou seja, o cdigo que executa
chamadas do Hibernate (na camada de persistncia) e o cdigo que trata RuntimeException
(e geralmente pode somente limpar acima e na sada) esto em camadas diferentes. O
gerenciamento do contexto atual feito pelo Hibernate pode significativamente simplificar este
projeto, como tudo que voc necessita do acesso a um SessionFactory. A manipulao de
exceo discutida mais tarde neste captulo.
193
Captulo 12. Transaes e Con...
standalone de JTA e us-la sem EJB. O Hibernate oferece duas estratgias para a integrao
de JTA.
Se voc usar transaes de bean gerenciado (BMT) o Hibernate dir ao servidor de aplicao
para comear e para terminar uma transao de BMT se voc usar a Transaction API. Assim,
o cdigo de gerncia de transao idntico ao ambiente no gerenciado.
// BMT idiom
Session sess = factory.openSession();
Transaction tx = null;
try {
tx = sess.beginTransaction();
// do some work
...
tx.commit();
}
catch (RuntimeException e) {
if (tx != null) tx.rollback();
throw e; // or display error message
}
finally {
sess.close();
}
Se voc quiser usar uma Session limitada por transao, isto , a funcionalidade do
getCurrentSession() para a propagao fcil do contexto, voc ter que usar diretamente a
API JTA UserTransaction:
tx.begin();
tx.commit();
}
catch (RuntimeException e) {
tx.rollback();
throw e; // or display error message
}
194
Tratamento de Exceo
// CMT idiom
Session sess = factory.getCurrentSession();
// do some work
...
A exceo HibernateException, a qual envolve a maioria dos erros que podem ocorrer em
uma camada de persistncia do Hibernate, uma exceo no verificada. Ela no constava em
verses mais antigas de Hibernate. Em nossa opinio, ns no devemos forar o desenvolvedor
a tratar uma exceo irrecupervel em uma camada mais baixa. Na maioria dos sistemas, as
excees no verificadas e fatais so tratadas em um dos primeiros frames da pilha da chamada
do mtodo (isto , em umas camadas mais elevadas) e uma mensagem de erro apresentada ao
usurio da aplicao (ou alguma outra ao apropriada feita). Note que Hibernate pode tambm
lanar outras excees no verificadas que no sejam um HibernateException. Estas, tambm
so, irrecuperveis e uma ao apropriada deve ser tomada.
195
Captulo 12. Transaes e Con...
// do some work
...
sess.getTransaction().commit()
}
catch (RuntimeException e) {
sess.getTransaction().rollback();
throw e; // or display error message
}
finally {
sess.close();
196
Controle de concorrncia otimista
Veja que setTimeout() no pode ser chamado em um bean CMT, onde o tempo de espera das
transaes deve ser definido declaradamente.
Em uma implementao sem muita ajuda do Hibernate, cada interao com o banco de dados
ocorre em uma nova Session e o desenvolvedor responsvel por recarregar todas as instncias
persistentes da base de dados antes de manipul-las. Este caminho fora a aplicao a realizar
sua prpria checagem de verso para assegurar a conversao do isolamento da transao.
Este caminho menos eficiente em termos de acesso ao banco de dados. o caminho mais
similar entidade EJBs.
t.commit();
session.close();
197
Captulo 12. Transaes e Con...
Uma nica instncia de Session e suas instncias persistentes so usadas para a conversao
inteira, isto conhecido como sesso-por-conversao. O Hibernate verifica verses da instncia
no momento da liberao, lanando uma exceo se a modificao concorrente for detectada. At
o desenvolvedor pegar e tratar essa exceo. As opes comuns so a oportunidade para que
o usurio intercale as mudanas ou reinicie a conversao do negcio com dados no antigos.
foo.setProperty("bar");
O objeto foo sabe que a Session j foi carregada. Ao comear uma nova transao ou uma
sesso velha, voc obter uma conexo nova e reiniciar a sesso. Submeter uma transao
implica em desconectar uma sesso da conexo JDBC e retornar conexo ao pool. Aps a
reconexo, para forar uma checagem de verso em dados que voc no esteja atualizando, voc
poder chamar Session.lock() com o LockMode.READ em todos os objetos que possam ter sido
atualizados por uma outra transao. Voc no precisa bloquear nenhum dado que voc est
atualizando. Geralmente, voc configuraria FlushMode.NEVER em uma Session estendida, de
modo que somente o ltimo ciclo da transao tenha permisso de persistir todas as modificaes
feitas nesta conversao. Por isso, somente esta ltima transao incluiria a operao flush()
e ento tambm iria close() a sesso para terminar a conversao.
Este modelo problemtico se a Session for demasiadamente grande para ser armazenada
durante o tempo de espera do usurio (por exemplo uma HttpSession deve ser mantida o menor
possvel). Como a Session tambm cache de primeiro nvel (imperativo) e contm todos os
objetos carregados, ns podemos provavelmente usar esta estratgia somente para alguns ciclos
de requisio/resposta. Voc deve usar a Session somente para uma nica conversao, porque
ela logo tambm estar com dados velhos.
198
Objetos destacados e versionamento automtico
Nota
Note que verses mais atuais de Hibernate requerem a desconexo e reconexo
explcitas de uma Session. Estes mtodos so desatualizados, pois o incio e
trmino de uma transao tm o mesmo efeito.
Note tambm que voc deve manter a Session desconectada, fechada para a camada de
persistncia. Ou seja, use um bean de sesso com estado EJB para prender a Session em um
ambiente de trs camadas. No transfira camada web, ou at serializ-lo para uma camada
separada, para armazen-lo no HttpSession.
Outra vez, o Hibernate verificar verses da instncia durante a liberao, lanando uma exceo
se ocorrer conflitos de atualizaes.
Voc pode tambm chamar o lock() em vez de update() e usar LockMode.READ (executando
uma checagem de verso, ignorando todos os caches) se voc estiver certo de que o objeto no
foi modificado.
199
Captulo 12. Transaes e Con...
s vezes a modificao concorrente pode ser permitida, desde que as mudanas realizadas
no se sobreponham. Se voc configurar optimistic-lock="dirty" ao mapear o <class>, o
Hibernate comparar somente campos modificados durante a liberao.
O Hibernate usar sempre o mecanismo de bloqueio da base de dados, nunca bloquiar objetos
na memria.
A classe LockMode define os diferentes nveis de bloqueio que o Hibernate pode adquirir. Um
bloqueio obtido pelos seguintes mecanismos:
200
Modos para liberar a conexo
LockMode.NONE representa a ausncia do bloqueio. Todos os objetos mudam para esse estado
de bloqueio no final da Transaction. Objetos associados com a sesso atravs do mtodo
update() ou saveOrUpdate() tambm so inicializados com esse modo de bloqueio.
ON_CLOSE: o modo legado descrito acima. A sesso do Hibernate obtm a conexo quando
precisar executar alguma operao JDBC pela primeira vez e mantm enquanto a conexo
no for fechada.
AFTER_TRANSACTION: informa que a conexo deve ser liberada aps a concluso de uma
org.hibernate.Transaction.
AFTER_STATEMENT (tambm conhecida como liberao agressiva): informa que a conexo
deve ser liberada aps a execuo de cada instruo. A liberao agressiva no ocorre se a
instruo deixa pra trs algum recurso aberto associado com a sesso obtida. Atualmente, a
nica situao em que isto ocorre com o uso de org.hibernate.ScrollableResults.
201
Captulo 12. Transaes e Con...
202
Interceptadores e Eventos
muito til quando a aplicao precisa reagir a certos eventos que ocorrem dentro do Hibernate.
Isso permite a implementao de certas funes genricas, assim como permite estender as
funcionalidades do Hibernate.
13.1. Interceptadores
A interface Interceptor permite fornecer informaes da sesso para o aplicativo, permitindo
que o aplicativo inspecione e/ou manipule as propriedades de um objeto persistente antes de ser
salvo, atualizado, excludo ou salvo. Pode ser usado para gerar informaes de auditoria. Por
exemplo, o seguinte Interceptor ajusta a funo automaticamente createTimestamp quando
um Auditable criado e atualiza a funo lastUpdateTimestamp quando um Auditable
atualizado.
package org.hibernate.test;
import java.io.Serializable;
import java.util.Date;
import java.util.Iterator;
import org.hibernate.EmptyInterceptor;
import org.hibernate.Transaction;
import org.hibernate.type.Type;
203
Captulo 13. Interceptadores ...
204
Sistema de Eventos
Para todos os efeitos esses listeners devem ser considerados singletons. Isto significa que eles
so compartilhados entre as requisies, e assim sendo, no devem salvar nenhum estado das
variveis instanciadas.
205
Captulo 13. Interceptadores ...
}
}
}
Voc tambm precisa adicionar uma entrada no XML de configurao do Hibernate para registrar
declarativamente qual listener deve se utilizado em conjunto com o listener padro:
<hibernate-configuration>
<session-factory>
...
<event type="load">
<listener class="com.eg.MyLoadListener"/>
<listener class="org.hibernate.event.def.DefaultLoadEventListener"/>
</event>
</session-factory>
</hibernate-configuration
>
Mas, por qu implementar uma interface e definir o tipo especfico durante a configurao? Bem,
um listener pode implementar vrios listeners de evento. Com o tipo sendo definido durante o
registro, fica fcil ligar ou desligar listeners personalizados durante a configurao.
Primeiro, voc precisa configurar um evento listener apropriado, para possibilitar o uso da
autorizao JAAS.
206
Segurana declarativa do Hibernate
207
208
Batch processing
Uma alternativa para inserir 100.000 linhas no banco de dados usando o Hibernate pode ser a
seguinte:
Isto ir falhar com um OutOfMemoryException em algum lugar prximo a linha 50.000. Isso ocorre
devido ao fato do Hibernate fazer cache de todas as instncias de Customer inseridas num cach
em nvel de sesso. Ns demonstraremos neste capitulo como evitar este problema.
Entretanto, se voc vai realizar processamento em lotes, muito importante que voc habilite o
uso de lotes JDBC, se voc pretende obter um desempenho razovel. Defina o tamanho do lote
JDBC em um valor razovel (algo entre 10-50, por exemplo):
hibernate.jdbc.batch_size 20
Note que o Hibernate desabilita o loteamento de insero no nvel JDBC de forma transparente
se voc utilizar um gerador de identificador identiy.
Voc tambm pode querer rodar esse tipo de processamento em lotes com o cache secundrio
completamente desabilitado:
hibernate.cache.use_second_level_cache false
Mas isto no absolutamente necessrio, desde que possamos ajustar o CacheMode para
desabilitar a interao com o cache secundrio.
209
Captulo 14. Batch processing
tx.commit();
session.close();
tx.commit();
session.close();
210
Operaes no estilo DML
devido falta do cach primrio. Uma Sesso sem Estado uma abstrao de baixo nvel, muito
mais prxima do JDBC adjacente.
tx.commit();
session.close();
211
Captulo 14. Batch processing
Nenhum joins, tanto implcito ou explcito, pode ser especificado em uma consulta de volume
HQL. As Sub-consultas podem ser utilizadas na clusula onde, em que as subconsultas podem
conter unies.
A clausula onde tambm opcional.
String hqlUpdate = "update Customer c set c.name = :newName where c.name = :oldName";
// or String hqlUpdate = "update Customer set name = :newName where name = :oldName";
int updatedEntities = s.createQuery( hqlUpdate )
.setString( "newName", newName )
.setString( "oldName", oldName )
.executeUpdate();
tx.commit();
session.close();
212
Operaes no estilo DML
.executeUpdate();
tx.commit();
session.close();
Apenas a forma INSERT INTO ... SELECT ... suportada; INSERT INTO ... VALUES ... no
suportada.
213
Captulo 14. Batch processing
a partir da instruo select correspondente, ou ele pode ser omitido da properties_list (neste
caso utiliza-se o seed value definido pela classe org.hibernate.type.VersionType).
String hqlInsert = "insert into DelinquentAccount (id, name) select c.id, c.name from Customer
c where ...";
int createdEntities = s.createQuery( hqlInsert )
.executeUpdate();
tx.commit();
session.close();
214
HQL: A Linguagem de Consultas do
Hibernate
O Hibernate vem com uma poderosa linguagem de consulta (HQL) que muito parecida com o
SQL. No entanto, comparado com o SQL o HQL totalmente orientado objetos, e compreende
noes de herana, polimorfismo e associaes.
Esse manual usa as palavras chave HQL em letras minsculas. Alguns usurios acreditam que
com letras maisculas as consultas ficam mais legveis, mas ns acreditamos que este formato
no apropriado para o cdigo Java.
from eg.Cat
from Cat
Com o objetivo de referir-se ao Cat em outras partes da consulta, voc precisar determinar um
alias. Por exemplo:
Essa consulta atribui um alias a cat para as instncias de Cat, portanto poderemos usar esse
alias mais tarde na consulta. A palavra chave as opcional. Voc tambm pode escrever assim:
215
Captulo 15. HQL: A Linguagem...
considerada uma boa prtica nomear alias de consulta, utilizando uma letra minscula inicial,
consistente com os padres de nomeao Java para variveis locais (ex.: domesticCat).
inner join
left outer join
right outer join
unio completa (geralmente no til)
As construes inteiro, unio esquerda externa e unio direita externa podem ser
abreviadas.
Voc pode fornecer condies extras de unio usando a palavra chave do HQL with.
216
Associaes e unies
A "fetch" join allows associations or collections of values to be initialized along with their parent
objects using a single select. This is particularly useful in the case of a collection. It effectively
overrides the outer join and lazy declarations of the mapping file for associations and collections.
See Seo 20.1, Estratgias de Busca for more information.
Geralmente, uma unio de busca no precisa atribuir um alias, pois o objeto associado no deve
ser usado na clusula where (ou em qualquer outra clusula). Tambm, os objetos associados
no so retornados diretamente nos resultados da consulta. Ao invs disso, eles devem ser
acessados usando o objeto pai. A nica razo pela qual precisariamos de um alias quando
fazemos uma unio de busca recursivamente em uma coleo adicional:
Observe que a construo busca no deve ser usada em consultas invocadas usando iterate()
(embora possa ser usado com scroll()). O Fetch tambm no deve ser usado junto com
o setMaxResults() ou setFirstResult() pois essas operaes so baseadas nas linhas
retornadas, que normalmente contm duplicidade devido busca das colees, ento o nmero
de linhas pode no ser o que voc espera. A Fetch no deve ser usada junto com uma condio
with. possvel que seja criado um produto cartesiano pela busca de unio em mais do que uma
coleo em uma consulta, ento tome cuidado nesses casos. Uma busca de unio em vrias
colees pode trazer resultados inesperados para mapeamentos do tipo bag, tome cuidado na
hora de formular consultas como essas. Finalmente, observe o seguinte, a busca de unio
completa e busca de unio direita no so importantes.
217
Captulo 15. HQL: A Linguagem...
from Document doc fetch all properties where lower(doc.name) like '%cats%'
As consultas apresentadas na seo anterior usam a forma explcita, onde a palavra chave
unio explicitamente usada na clusula from. Essa a forma recomendada.
A propriedade especial (em letra minscula) id pode ser usada para se referir propriedade
do identificador de uma entidade considerando que a entidade no define uma propriedade
no identificadora chamada id.
Se a entidade definir a propriedade do identificador nomeada, voc poder usar este nome
de propriedade.
Importante
218
A clusula select
select mate
from Cat as cat
inner join cat.mate as mate
As consultas podem retornar mltiplos objetos e/ou propriedades como uma matriz do tipo
Object[]:
Ou como um List:
Ou - considerando que a classe Family tenha um construtor apropriado - como um objeto Java
typesafe atual:
219
Captulo 15. HQL: A Linguagem...
Isto bem mais til quando usado junto comselecione novo mapa:
As palavras distinct e all podem ser usadas e tm a mesma semntica que no SQL.
220
Pesquisas Polimrficas
from java.lang.Object o
Note que as duas ltimas consultas requerem mais de um SQL SELECT. Isto significa que a
clusula order by no ordena corretamente todo o resultado. Isso tambm significa que voc
no pode chamar essas consultas usando consulta.scroll().
221
Captulo 15. HQL: A Linguagem...
A seguinte consulta:
select foo
from Foo foo, Bar bar
where foo.startDate = bar.date
retornar todas as instncias de Foo, para cada um que tiver uma instncia de bar com a
propriedade date igual a propriedade startDate de Foo. Expresses de caminho compostas
fazem da clusula where, extremamente poderosa. Consideremos:
Esta consulta traduz para uma consulta SQL com uma tabela (inner) unio. Por exemplo:
O operador = pode ser usado para comparar no apenas propriedades, mas tambm instncias:
The special property (lowercase) id can be used to reference the unique identifier of an object.
See Seo 15.5, Referncia propriedade do identificador for more information.
222
Expresses
See Seo 15.5, Referncia propriedade do identificador for more information regarding
referencing identifier properties)
You can also use components or composite user types, or properties of said component types.
See Seo 15.17, Componentes for more information.
Um tipo "any" possui as propriedades id e class especiais, nos permitindo expressar uma unio
da seguinte forma (onde AuditLog.item uma propriedade mapeada com<any>):
15.10. Expresses
As expresses permitidas na clusula where incluem o seguinte:
operadores matemticos: +, -, *, /
operadores de comparao binrios: =, >=, <=, <>, !=, like
operadores lgicos and, or, not
Parnteses ( ) que indica o agrupamento
in, not in, between, is null, is not null, is empty, is not empty, member of and
not member of
case "simples" , case ... when ... then ... else ... end, and "searched" case, case
when ... then ... else ... end
223
Captulo 15. HQL: A Linguagem...
from DomesticCat cat where cat.name not between 'A' and 'B'
Da mesma forma, is null e is not null podem ser usados para testar valores nulos.
<property name="hibernate.query.substitutions"
>true 1, false 0</property
>
224
Expresses
Isso ir substituir as palavras chave true e falsepelos literais 1 e 0 na traduo do HQL para
SQL.
Pode-se testar o tamanho de uma coleo com a propriedade especial size ou a funo especial
size().
Para colees indexadas, voc pode se referir aos ndices mximo e mnimo, usando as funes
minindex e maxindex. Igualmente, pode-se referir aos elementos mximo e mnimo de uma
coleo de tipos bsicos usando as funes minelement e maxelement. Por exemplo:
As funes SQL any, some, all, exists, in so suportadas quando passado o elemento
ou o conjunto de ndices de uma coleo (elements e ndices de funes) ou o resultado de
uma subconsulta (veja abaixo):
225
Captulo 15. HQL: A Linguagem...
Note que essas construes - tamanho, elementos, ndices, minindex, maxindex, minelement,
maxelement s podem ser usados na clusula where do Hibernate3.
Elementos de colees com ndice (matriz, listas, mapas) podem ser referenciadas pelo ndice
(apenas na clusula where):
O HQL tambm prov a funo interna index() para elementos de associao um-para-muitos
ou coleo de valores.
226
A clusula ordenar por
Funes escalares SQL, suportadas pelo banco de dados subjacente podem ser usadas:
Se ainda no estiver totalmente convencido, pense o quo maior e menos legvel poderia ser a
consulta a seguir, em SQL:
select cust
from Product prod,
Store store
inner join store.customers cust
where prod.name = 'widget'
and store.location.name in ( 'Melbourne', 'Sydney' )
and prod = all elements(cust.currentOrder.lineItems)
227
Captulo 15. HQL: A Linguagem...
Funes SQL e funes agregadas so permitidas nas clusulas having e order by, se
suportadas pelo banco de dados subjacentes (ex: no no MeuSQL).
select cat
from Cat cat
join cat.kittens kitten
group by cat.id, cat.name, cat.other, cat.properties
having avg(kitten.weight)
> 100
order by count(kitten) asc, sum(kitten.weight) desc
Note que, nem a clusula group by ou order by podem conter expresses aritmticas. O
Hibernate tambm no expande atualmente uma entidade agrupada, portanto voc no pode
escrever group by cat caso todas as propriedades do cat no estiverem agregadas. Voc
precisa listar claramente todas as propriedades no-agregadas.
15.13. Subconsultas
Para bancos de dados que suportam subselees, o Hibernate suporta subconsultas dentro
de consultas. Uma subconsulta precisa estar entre parnteses (normalmente uma chamada
de funo agregada SQL). Mesmo subconsultas co-relacionadas (subconsultas que fazem
referncia alias de outras consultas), so aceitas.
228
Exemplos de HQL
Note que HQL subconsultas podem aparecer apenas dentro de clusulas select ou where.
Note that subqueries can also utilize row value constructor syntax. See Seo 15.18, Sintxe
do construtor de valores de linha for more information.
A consulta a seguir retorna o id de ordenar, nmero de tens e o valor total do ordenar para
todos os ordenar no pagos para um cliente particular e valor total mnimo dado, ordenando os
resultados por valor total. Para determinar os preos, utiliza-se o catlogo atual. A consulta SQL
resultante, usando tabelas ORDER, ORDER_LINE, PRODUCT, CATALOG e PRICE, tm quatro unies
inteiras e uma subseleo (no correlacionada).
229
Captulo 15. HQL: A Linguagem...
Que monstro! Na verdade, na vida real, eu no sou muito afeioado subconsultas, ento minha
consulta seria mais parecida com isto:
230
Exemplos de HQL
statusChange.timeStamp = (
select max(change.timeStamp)
from PaymentStatusChange change
where change.payment = payment
)
and statusChange.user <
> :currentUser
)
group by status.name, status.sortOrder
order by status.sortOrder
A prxima consulta usa a funo isNull() do Servidor MS SQL, para retornar todas as contas
e pagamentos no efetuados para a organizao, para aquele que o usurio atual pertencer.
Traduz-se para uma consulta SQL com trs unies inteiras, uma unio externa e uma subseleo
nas tabelas ACCOUNT, PAYMENT, PAYMENT_STATUS, ACCOUNT_TYPE, ORGANIZATION e ORG_USER .
231
Captulo 15. HQL: A Linguagem...
Para ordenar um resultado pelo tamanho de uma coleo, use a consulta a seguir.
Se seu banco de dados suporta subselees, pode-se colocar uma condio sobre tamanho de
seleo na clusula where da sua consulta:
Com essa soluo no se pode retornar um User sem nenhuma menssagem, por causa da unio
inteira, a forma a seguir tambm til:
232
Componentes
15.17. Componentes
Os componentes podem ser usados de quase todas as formas que os tipos de valores simples
so usados nas consultas HQL. Eles podem aparecer na clusula select:
233
Captulo 15. HQL: A Linguagem...
Esta uma sintxe vlida, embora um pouco verbosa. Seria timo tornar essa sintxe um pouco
mais concisa e utilizar a sintxe row value constructor:
Com o uso da sintxe row value constructor, e que pode ser de benfico, seria quando utilizar
as subconsultas que precisem comparar com os valores mltiplos:
Ao decidir se voc quer usar esta sintxe ou no, deve-se considerar o fato de que a consulta
ser dependente da ordenao das sub-propriedades do componente no metadados.
234
Consultas por critrios
O Hibernate prov uma API de consulta por critrio intuitiva e extensvel.
235
Captulo 16. Consultas por cr...
Uma maneira alternativa de obter um critrio apartir de uma instncia Property. Voc pode
criar uma Property chamando Property.forName():
236
Associaes
16.4. Associaes
Atravs da navegao de associaes usando createCriteria(), voc pode especificar
restries por entidades relacionadas:
Note que o segundo createCriteria() retorna uma nova instncia de Criteria, que refere aos
elementos da coleo kittens.
Note que as colees de kittens mantidas pelas instncias Cat, retornadas pelas duas consultas
anteriores no so pr-filtradas pelo critrio. Se voc desejar recuperar somente os kittens que
se encaixarem ao critrios, voc dever usar um ResultTransformer.
Voc pode ainda manipular o conjunto do resultado usando a juno exterior restante:
237
Captulo 16. Consultas por cr...
.list();
Isto retornar todos os Cats com um mate (amigo) cujo nome inicia com "bom" ordenado pela
idade de seu mate e todos os cats que no tem mates. Isto til quando houver necessidade
de pedir ou limitar a prioridade do banco de dados em retornar conjuntos de resultado complexo/
grande e remover muitas instncias onde consultas mltiplas deveriam ter sido executadas e os
resultados unidos pelo java em memria.
Sem este recurso, o primeiro de todos os cats sem um mate teria que ser carregado em uma
consulta.
Uma segunda consulta teria que restaurar os cats com os mates cujos os nomes iniciem com
"bom" selecionados pelas idades dos mates.
This query will fetch both mate and kittens by outer join. See Seo 20.1, Estratgias de Busca
for more information.
238
Projees, agregaes e agrupamento.
Um alias pode ser atribudo de forma opcional uma projeo, assim o valor projetado pode ser
referenciado em restries ou ordenaes. Aqui seguem duas formas diferentes para fazer isto:
239
Captulo 16. Consultas por cr...
Os mtodos alias() e as() simplesmente envolvem uma instncia de projeo outra instncia
de Projeo em alias. Como um atalho, voc poder atribuir um alias quando adicionar a projeo
uma lista de projeo:
240
Consultas e subconsultas desanexadas.
.add( Property.forName("weight").avg().as("avgWeight") )
.add( Property.forName("weight").max().as("maxWeight") )
.add( Property.forName("color").group().as("color" )
)
.addOrder( Order.desc("catCountByColor") )
.addOrder( Order.desc("avgWeight") )
.list();
Um DetachedCriteria tambm pode ser usado para expressar uma subconsulta. As instncias
de critrios, que envolvem subconsultas, podem ser obtidas atravs das Subqueries ou
Property.
241
Captulo 16. Consultas por cr...
Primeiro, voc deve mapear a chave natural de sua entidade usando um <natural-id> e habilitar
o uso de um cache de segundo nvel.
<class name="User">
<cache usage="read-write"/>
<id name="id">
<generator class="increment"/>
</id>
<natural-id>
<property name="name"/>
<property name="org"/>
</natural-id>
<property name="password"/>
</class
>
Note que esta funcionalidade no proposta para o uso com entidades com chaves naturais
mutveis.
Uma vez que voc tenha ativado o cache de consulta Hibernate, o Restrictions.naturalId()
nos permite que utilizemos um algoritmo de cache mais eficiente.
session.createCriteria(User.class)
.add( Restrictions.naturalId()
.set("name", "gavin")
.set("org", "hb")
).setCacheable(true)
.uniqueResult();
242
SQL Nativo
Voc tambm pode expressar consultas no dialeto SQL nativo de seu banco de dados. Isto
bastante til para usar recursos especficos do banco de dados, assim como dicas de consultas
ou a palavra chave em Oracle CONNECT. Ele tambm oferece um caminho de migrao limpo de
uma aplicao baseada em SQL/JDBC direta at o Hibernate.
O Hibernate3 permite que voc especifique o SQL escrito mo, incluindo procedimentos
armazenados, para todas as operaes de criar, atualizar, deletar e carregar.
Eles iro retornar uma matriz de Lista de Objeto (Object[]) com valores escalares para cada coluna
na tabela CATS. O Hibernate usar o ResultSetMetadata para deduzir a ordem atual e tipos de
valores escalares retornados.
Este ainda ir retornar as matrizes de Objeto, mas desta vez ele no usar o ResultSetMetdata,
ao invs disso, obter explicitamente a coluna de ID, NOME e DATA DE NASCIMENTO como
243
Captulo 17. SQL Nativo
possvel deixar de fora o tipo de informao para todos ou alguns dos escalares.
Esta a mesma consulta de antes, mas desta vez, o ResultSetMetaData utilizado para decidir
o tipo de NOME e DATA DE NASCIMENTO onde o tipo de ID explicitamente especificado.
Considerando que o Cat esteja mapeado como uma classe com colunas ID,NOME e DATA DE
NASCIMENTO, as consultas acima iro devolver uma Lista onde cada elemento uma entidade
de Cat.
Se a entidade estiver mapeada com um muitos-para-um para outra entidade, requer-se que
devolva tambm este ao desempenhar a consulta nativa, seno ocorrer um erro de banco
de dados especfico "coluna no encontrada". As colunas adicionais sero automaticamente
retornadas ao usar a anotao, mas preferimos ser explcitos como no seguinte exemplo para
umamuitos-para-um para um Dog:
244
Manuseio de associaes e colees
sess.createSQLQuery("SELECT c.ID, NAME, BIRTHDATE, DOG_ID, D_ID, D_NAME FROM CATS c, DOGS d
WHERE c.DOG_ID = d.D_ID")
.addEntity("cat", Cat.class)
.addJoin("cat.dog");
Neste exemplo, a devoluo do Cat ter sua propriedade dog totalmente inicializada sem
nenhuma viagem extra ao banco de dados. Note que adicionamos um nome alias ("cat") para
poder especificar o caminho da propriedade alvo na unio. possvel fazer a mesma unio para
colees, ex.: se ao invs disso, o Cat tivesse um-para-muitos para Dog.
sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE, D_ID, D_NAME, CAT_ID FROM CATS c, DOGS d WHERE
c.ID = d.CAT_ID")
.addEntity("cat", Cat.class)
.addJoin("cat.dogs");
Neste estgio, estamos chegando no limite do que possvel fazer com as consultas nativas sem
comear a destacar as colunas sql para torn-las til no Hibernate. Os problemas comeam a
surgir quando se retorna entidades mltiplas do mesmo tipo ou quando o padro de nomes de
alias/coluna no so suficientes.
necessrio uma injeo de alias de coluna na seguinte consulta (a qual bem provvel que
falhe):
A inteno para esta consulta retornar duas instncias Cat por linha: um cat e sua me. Isto
ir falhar pois existe um conflito de nomes, so mapeados aos mesmos nomes de colunas e em
alguns bancos de dados os aliases de colunas retornadas estaro, muito provavelmente, na forma
245
Captulo 17. SQL Nativo
a string da consulta SQL, com espao reservado para Hibernate para injetar aliases de coluna.
A anotao {cat.*} e {me.*} usada acima, um atalho para "todas as propriedades". De forma
alternativa, voc pode listar as colunas explicitamente, mas at neste caso ns deixamos o
Hibernate injetar os aliases de coluna SQL para cada propriedade. O espao reservado para
um alias de coluna simplesmente o nome de propriedade qualificado pelo alias de tabela. No
seguinte exemplo, recuperamos os Cats e suas mes de uma tabela diferente (cat_log) para
aquele declarado no metadado de mapeamentos. Note que podemos at usar os aliases de
propriedade na clusula where se quisermos.
As seguintes tabelas mostram as diferentes formas de usar uma injeo de alias. Por favor
note que os nomes de alias no resultado so exemplos, cada alias ter um nome nico e
provavelmente diferente quando usado.
246
Retorno de entidades no gerenciadas
Discriminador de {[aliasname].class}
DISC as {item.class}
uma entidade
Todas as {[aliasname].*} {item.*}
propriedades de
uma entidade
Uma chave de {[aliasname].key} ORGID as {coll.key}
coleo
O id de uma {[aliasname].id} EMPID as {coll.id}
coleo
O elemento de uma {[aliasname].element}
XID as {coll.element}
coleo
propriedade de {[aliasname].element.
NAME as {coll.element.name}
elemento na [propertyname]}
coleo
Todas as {[aliasname].element.*}
{coll.element.*}
propriedades de
elemento na
coleo
Todas as {[aliasname].*} {coll.*}
propriedades da
coleo
um transformador de resultado
A consulta acima ir devolver uma lista de CatDTO que foi instanciada e injetada com valores dos
comandos NAME e BIRTHDATE em suas propriedades correspondentes ou campos.
247
Captulo 17. SQL Nativo
17.1.7. Parmetros
Consultas sql Nativas suportam parmetros posicionais assim como parmetros nomeados:
<sql-query name="persons">
<return alias="person" class="eg.Person"/>
SELECT person.NAME AS {person.name},
person.AGE AS {person.age},
person.SEX AS {person.sex}
FROM PERSON person
WHERE person.NAME LIKE :namePattern
</sql-query
>
<sql-query name="personsWith">
<return alias="person" class="eg.Person"/>
<return-join alias="address" property="person.mailingAddress"/>
SELECT person.NAME AS {person.name},
person.AGE AS {person.age},
person.SEX AS {person.sex},
address.STREET AS {address.street},
248
Consultas SQL Nomeadas
address.CITY AS {address.city},
address.STATE AS {address.state},
address.ZIP AS {address.zip}
FROM PERSON person
JOIN ADDRESS address
ON person.ID = address.PERSON_ID AND address.TYPE='MAILING'
WHERE person.NAME LIKE :namePattern
</sql-query
>
Uma consulta SQL nomeada pode devolver um valor escalar. Voc deve declarar um alias de
coluna e um tipo Hibernate usando o elemento <return-scalar>:
<sql-query name="mySqlQuery">
<return-scalar column="name" type="string"/>
<return-scalar column="age" type="long"/>
SELECT p.NAME AS name,
p.AGE AS age,
FROM PERSON p WHERE p.NAME LIKE 'Hiber%'
</sql-query
>
<resultset name="personAddress">
<return alias="person" class="eg.Person"/>
<return-join alias="address" property="person.mailingAddress"/>
</resultset>
Voc pode tambm, como forma alternativa, usar a informao de mapeamento de conjunto de
resultado em seus arquivos hbm em cdigo de java.
249
Captulo 17. SQL Nativo
"select {cat.*}, {kitten.*} from cats cat, cats kitten where kitten.mother = cat.id"
)
.setResultSetMapping("catAndKitten")
.list();
Com a <return-property> voc pode informar explicitamente, quais aliases de coluna utilizar,
ao invs de usar a sintxe {} para deixar o Hibernate injetar seus prprios aliases. Por exemplo:
<sql-query name="mySqlQuery">
<return alias="person" class="eg.Person">
<return-property name="name" column="myName"/>
<return-property name="age" column="myAge"/>
<return-property name="sex" column="mySex"/>
</return>
SELECT person.NAME AS myName,
person.AGE AS myAge,
person.SEX AS mySex,
FROM PERSON person WHERE person.NAME LIKE :name
</sql-query>
<return-property> tambm funciona com colunas mltiplas. Isto resolve a limitao com a
sintxe {} que no pode permitir controle granulado fino de muitas propriedades de colunas
mltiplas.
<sql-query name="organizationCurrentEmployments">
<return alias="emp" class="Employment">
<return-property name="salary">
<return-column name="VALUE"/>
<return-column name="CURRENCY"/>
</return-property>
<return-property name="endDate" column="myEndDate"/>
</return>
SELECT EMPLOYEE AS {emp.employee}, EMPLOYER AS {emp.employer},
STARTDATE AS {emp.startDate}, ENDDATE AS {emp.endDate},
REGIONCODE as {emp.regionCode}, EID AS {emp.id}, VALUE, CURRENCY
FROM EMPLOYMENT
WHERE EMPLOYER = :id AND ENDDATE IS NULL
ORDER BY STARTDATE ASC
</sql-query
>
250
Usando procedimentos de armazenamento para consultas
Para usar esta consulta no Hibernate voc vai precisar mape-lo atravs de uma consulta
nomeada
251
Captulo 17. SQL Nativo
O procedimento deve retornar um conjunto de resultados. Observe que, como este servidor
pode retornar mltiplos conjuntos de resultados e contas atualizadas, o Hibernate ir inteirar os
resultados e pegar o primeiro resultado, o qual o valor de retorno do conjunto de resultados.
O resto ser descartado.
Se voc habilitar SET NOCOUNT ON no seu procedimento, ele provavelmente ser mais eficiente.
Mas, isto no obrigatrio
<class name="Person">
<id name="id">
252
SQL padronizado para criar, atualizar e deletar
<generator class="increment"/>
</id>
<property name="name" not-null="true"/>
<sql-insert
>INSERT INTO PERSON (NAME, ID) VALUES ( UPPER(?), ? )</sql-insert>
<sql-update
>UPDATE PERSON SET NAME=UPPER(?) WHERE ID=?</sql-update>
<sql-delete
>DELETE FROM PERSON WHERE ID=?</sql-delete>
</class
>
O SQL executado diretamente no seu banco de dados, ento voc pode usar qualquer
linguagem que quiser. Isto com certeza reduzir a portabilidade do seu mapeamento se voc
utilizar um SQL para um banco de dados especfico.
<class name="Person">
<id name="id">
<generator class="increment"/>
</id>
<property name="name" not-null="true"/>
<sql-insert callable="true"
>{call createPerson (?, ?)}</sql-insert>
<sql-delete callable="true"
>{? = call deletePerson (?)}</sql-delete>
<sql-update callable="true"
>{? = call updatePerson (?, ?)}</sql-update>
</class
>
A ordem de posies dos parmetros so vitais, pois eles devem estar na mesma seqncia
esperada pelo Hibernate.
253
Captulo 17. SQL Nativo
update PERSON
set
NAME = uname,
where
ID = uid;
return SQL%ROWCOUNT;
END updatePerson;
<sql-query name="person">
<return alias="pers" class="Person" lock-mode="upgrade"/>
SELECT NAME AS {pers.name}, ID AS {pers.id}
FROM PERSON
WHERE ID=?
FOR UPDATE
</sql-query
>
Este apenas uma instruo de consulta nomeada, como discutido anteriormente. Voc pode
referenciar esta consulta nomeada em um mapeamento de classe:
<class name="Person">
<id name="id">
<generator class="increment"/>
</id>
<property name="name" not-null="true"/>
<loader query-ref="person"/>
</class
>
Voc pode tambm definir uma consulta para carregar uma coleo:
254
SQL padronizado para carga
<sql-query name="employments">
<load-collection alias="emp" role="Person.employments"/>
SELECT {emp.*}
FROM EMPLOYMENT emp
WHERE EMPLOYER = :id
ORDER BY STARTDATE ASC, EMPLOYEE ASC
</sql-query
>
Voc pode at definir um carregador de entidade que carregue uma coleo por busca de unio:
<sql-query name="person">
<return alias="pers" class="Person"/>
<return-join alias="emp" property="pers.employments"/>
SELECT NAME AS {pers.*}, {emp.*}
FROM PERSON pers
LEFT OUTER JOIN EMPLOYMENT emp
ON pers.ID = emp.PERSON_ID
WHERE ID=?
</sql-query
>
255
256
Filtrando dados
O Hibernate3 prov um novo mtodo inovador para manusear dados com regras de "visibilidade".
Um Filtro do Hibernate um filtro global, nomeado e parametrizado que pode ser habilitado ou
no dentro de uma Sesso do Hibernate.
Para usar esses filtros, eles devem inicialmente ser definidos e anexados aos elementos do
mapeamento apropriados. Para definir um filtro, use o elemento <filter-def/> dentro do
elemento <hibernate-mapping/>:
<filter-def name="myFilter">
<filter-param name="myFilterParam" type="string"/>
</filter-def
>
<set ...>
<filter name="myFilter" condition=":myFilterParam = MY_FILTERED_COLUMN"/>
</set
>
257
Captulo 18. Filtrando dados
dentro de qualquer sesso. Eles devem ser explicitamente habilitados usando o mtodo
Session.enabledFilter(), que retorna uma instncia da interface Filter. Usando o filtro
simples definido acima, o cdigo se pareceria com o seguinte:
session.enableFilter("myFilter").setParameter("myFilterParam", "some-value");
Um exemplo completo, usando dados temporais com um padro de datas de registro efetivo:
<filter-def name="effectiveDate">
<filter-param name="asOfDate" type="date"/>
</filter-def>
Para garantir que voc sempre tenha registro efetivos, simplesmente habilite o filtro na sesso
antes de recuperar os dados dos empregados:
258
Filtros do Hibernate
No HQL acima, mesmo que tenhamos mencionado apenas uma restrio de salrio nos
resultados, por causa do filtro habilitado, a consulta retornar apenas os funcionrios ativos cujo
salrio maior que um milho de dlares.
Nota: se voc planeja usar filtros com unio externa (por HQL ou por busca de carga) seja
cuidadoso quanto direo da expresso de condio. mais seguro configur-lo para uma
unio externa esquerda. Coloque o parmetro primeiro seguido pelo(s) nome(s) da coluna aps
o operador.
Aps ser definido, o filtro deve ser anexado s entidades mltiplas e/ou colees, cada uma com
sua prpria condio. Isto pode ser tedioso quando as condies se repetem. Assim, usando o
<filter-def/> permite denifir uma condio padro, tanto como uma funo quanto CDATA:
Esta condio padro ser utilizada todas as vezes que um filtro for anexado a algo sem uma
condio especfica. Note que isto significa que voc pode dar uma condio especfica como
parte de um anexo de filtro que substitua a condio padro neste caso em particular.
259
260
Mapeamento XML
XML Mapping is an experimental feature in Hibernate 3.0 and is currently under active
development.
O Hibernate suporta a API dom4j para manipular rvores XML. Voc pode escrever queries que
retornem rvores dom4j do banco de dados e automaticamente sincronizar com o banco de
dados qualquer modificao feita nessas rvores. Voc pode at mesmo pegar um documento
XML, analis-lo usando o dom4j, e escrever as alteraes no banco de dados usando
quaisquer operaes bsicas do Hibernate: persist(), saveOrUpdate(),merge(), delete(),
replicate() (a mesclagem ainda no suportada)
Um mapeamento simples pode ser usado para simultaneamente mapear propriedades da classe
e ns de um documento XML para um banco de dados ou, se no houver classe para mapear,
pode ser usado simplesmente para mapear o XML.
<class name="Account"
table="ACCOUNTS"
node="account">
<id name="accountId"
column="ACCOUNT_ID"
node="@id"/>
<many-to-one name="customer"
column="CUSTOMER_ID"
node="customer/@id"
embed-xml="false"/>
<property name="balance"
column="BALANCE"
node="balance"/>
261
Captulo 19. Mapeamento XML
...
</class
>
<class entity-name="Account"
table="ACCOUNTS"
node="account">
<id name="id"
column="ACCOUNT_ID"
node="@id"
type="string"/>
<many-to-one name="customerId"
column="CUSTOMER_ID"
node="customer/@id"
embed-xml="false"
entity-name="Customer"/>
<property name="balance"
column="BALANCE"
node="balance"
type="big_decimal"/>
...
</class
>
Esse mapeamento permite que voc acesse os dados como uma rvore dom4j ou um grfico de
pares de nome/valor de propriedade ou Maps do Java. Os nomes de propriedades so somente
construes lgicas que podem ser referenciadas em consultas HQL.
262
Mapeando metadados com XML
Para colees e associaes de valores simples, existe uma funo adicional embed-xml. Se a
funo embed-xml="true", que o valor padro, a rvore XML para a entidade associada (ou
coleo de determinado tipo de valor) ser embutida diretamente na rvore XML que contm
a associao. Por outro lado, se embed-xml="false", ento apenas o valor do identificador
referenciado ir aparecer no XML para associaes simples e as colees simplesmente no
iro aparecer.
Voc precisa tomar cuidado para no deixar o embed-xml="true" para muitas associaes, pois
o XML no suporta bem referncias circulares.
<class name="Customer"
table="CUSTOMER"
node="customer">
<id name="id"
column="CUST_ID"
node="@id"/>
<map name="accounts"
node="."
embed-xml="true">
<key column="CUSTOMER_ID"
not-null="true"/>
<map-key column="SHORT_DESC"
node="@short-desc"
type="string"/>
<one-to-many entity-name="Account"
embed-xml="false"
node="account"/>
</map>
<component name="name"
node="name">
<property name="firstName"
node="first-name"/>
<property name="initial"
node="initial"/>
<property name="lastName"
node="last-name"/>
</component>
...
</class
>
Nesse caso, decidimos incorporar a coleo de ids de contas, e no os dados de contas. Segue
a abaixo a consulta HQL:
from Customer c left join fetch c.accounts where c.lastName like :lastName
263
Captulo 19. Mapeamento XML
<customer id="123456789">
<account short-desc="Savings"
>987632567</account>
<account short-desc="Credit Card"
>985612323</account>
<name>
<first-name
>Gavin</first-name>
<initial
>A</initial>
<last-name
>King</last-name>
</name>
...
</customer
>
<customer id="123456789">
<account id="987632567" short-desc="Savings">
<customer id="123456789"/>
<balance
>100.29</balance>
</account>
<account id="985612323" short-desc="Credit Card">
<customer id="123456789"/>
<balance
>-2370.34</balance>
</account>
<name>
<first-name
>Gavin</first-name>
<initial
>A</initial>
<last-name
>King</last-name>
</name>
...
</customer
>
264
Manipulando dados em XML
tx.commit();
session.close();
tx.commit();
session.close();
265
266
Aumentando o desempenho
20.1. Estratgias de Busca
Uma estratgia de busca a estratgia que o Hibernate ir usar para recuperar objetos
associados se a aplicao precisar navegar pela associao. Estratgias de Busca podem ser
declaradas nos metadados de mapeamento O/R, ou sobrescritos por uma consulta HQL ou
consulta com Criteria.
Join fetching - o Hibernate busca o objeto ou coleo associada no mesmo SELECT, usando
um OUTER JOIN.
Select fetching - um segundo SELECT usado para buscar a entidade ou coleo associada. A
menos que voc desabilite a busca lazy, especificando lazy="false", esse segundo SELECT
ser executado apenas quando voc acessar a associao.
Subselect fetching - um segundo SELECT ser usado para recuperar as colees associadas
de todas as entidades recuperadas em uma consulta ou busca anterior. A menos que voc
desabilite a busca lazy especificando lazy="false", esse segundo SELECT ser executado
apenas quando voc acessar a associao.
Batch fetching - uma opo de otimizao para selecionar a busca. O Hibernate recupera um
lote de instncias ou entidades usando um nico SELECT, especificando uma lista de chaves
primrias ou chaves externas.
Lazy collection fetching - a coleo recuperada quando a aplicao invoca uma operao
sobre aquela coleo. Esse o padro para colees.
Proxy fetching: uma associao de um valor carregada quando um mtodo diferente do getter
do identificador invocado sobre o objeto associado.
267
Captulo 20. Aumentando o des...
Ns temos aqui duas noes ortogonais: quando a associao buscada e como ela buscada.
importante que voc no os confuda. Ns usamos fetch para ajustar o desempenho. Podemos
usar lazy para definir um contrato para qual dado sempre disponvel em qualquer instncia
desconectada de uma classe particular.
Perceba que o acesso a associaes preguiosas fora do contexto de uma sesso aberta do
Hibernate ir resultar numa exceo. Por exemplo:
s = sessions.openSession();
Transaction tx = s.beginTransaction();
tx.commit();
s.close();
Como a coleo de permisses no foi inicializada quando a Session for fechada, a coleo
no poder carregar o seu estado. O Hibernate no suporta inicializao preguiosa para objetos
desconectados. Para consertar isso, necessrio mover o cdigo que carrega a coleo para
logo antes da transao ser submetida.
268
Personalizando as estratgias de busca
Por outro lado, ns geralmente escolhemos a busca de unio (que no preguiosa por natureza)
ao invs do selecionar busca em uma transao particular. Ns agora veremos como customizar
a estratgia de busca. No Hibernate3, os mecanismos para escolher a estratgia de busca so
idnticos para as associaes de valor nico e para colees.
<set name="permissions"
fetch="join">
<key column="userId"/>
<one-to-many class="Permission"/>
</set
Independentemente da estratgia de busca que voc usar, o grfico no preguioso definido ser
certamente carregado na memria. Note que isso ir resultar em diversas selees imediatas
sendo usadas para rodar uma consulta HQL em particular.
Se voc quiser mudar a estratgia de busca usada pelo get() ou load(), simplesmente use
uma consulta por Criteria, por exemplo:
269
Captulo 20. Aumentando o des...
Isto o equivalente do Hibernate para o que algumas solues ORM chamam de "plano de
busca".
Um meio totalmente diferente de evitar problemas com selects N+1 usar um cache de segundo
nvel.
Por padro, o Hibernate3 gera proxies (na inicializao) para todas as classes persistentes que
os usem para habilitar recuperao preguiosa de associaes many-to-one e one-to-one.
O arquivo de mapeamento deve declarar uma interface para usar como interface de proxy para
aquela classe, com a funo proxy. Por padro, o Hibernate usa uma subclasse dessa classe.
Note que a classe a ser usada via proxy precisa implementar o construtor padro com pelo menos
visibilidade de package. Ns recomendamos esse construtor para todas as classes persistentes.
Existe alguns truques que voc deve saber quando estender esse comportamento para classes
polimrficas. Por exemplo:
Primeiramente, instncias de Cat nunca sero convertidas para DomesticCat, mesmo que a
instncia em questo seja uma instncia de DomesticCat:
Cat cat = (Cat) session.load(Cat.class, id); // instantiate a proxy (does not hit the db)
if ( cat.isDomesticCat() ) { // hit the db to initialize the proxy
DomesticCat dc = (DomesticCat) cat; // Error!
....
}
270
Proxies de associao final nico
Porm a situao no to ruim como parece. Mesmo quando temos duas referncias para
objetos proxies diferentes, a instncia adjacente ser do mesmo objeto:
E por terceiro, voc no pode usar um proxy CGLIB em uma classe final ou com quaisquer
mtodos final.
Finalmente, se o seu objeto persistente adquirir qualquer recurso durante a instanciao (ex. em
inicializadores ou construtor padro), ento esses recursos sero adquiridos pelo proxy tambm.
A classe de proxy uma subclasse da classe persistente.
Ento, os proxies para instncias de Cat e DomesticCat podem ser retornadas pelo load() ou
iterate().
Nota
Relacionamentos so tambm inicializados de forma preguiosa. Isso significa que voc precisa
declarar qualquer propriedade como sendo do tipo Cat, e no CatImpl.
271
Captulo 20. Aumentando o des...
Algumas vezes precisamos garantir que o proxy ou coleo inicializado antes de fechar
a Session. Claro que sempre podemos forar a inicializao chamando cat.getSex() ou
cat.getKittens().size(), por exemplo. Mas isto parece confuso para quem l o cdigo e no
conveniente para cdigos genricos.
Uma outra opo manter a Session aberta at que todas as colees e os proxies necessrios
sejam carregados. Em algumas arquiteturas de aplicaes, particularmente onde o cdigo que
acessa os dados usando Hibernate e o cdigo que os usa, se encontram em diferentes camadas
da aplicao ou diferentes processos fsicos, ser um problema garantir que a Session esteja
aberta quando uma coleo for inicializada. Existem dois caminhos bsicos para lidar com esse
problema:
Em uma aplicaes web, um filtro servlet pode ser usado para fechar a Session somente
no final da requisio do usurio, quando a renderizao da view estiver completa (o modelo
Abrir Sesso em View). Claro, que isto demanda uma exatido no manuseio de excees na
infraestrutura de sua aplicao. extremamente importante que a Session seja fechada e a
transao terminada antes de retornar para o usurio, mesmo que uma exceo ocorra durante
a renderizao da view. Veja o Wiki do Hibernate para exemplos do pattern "Abrir Sesso em
View".
Em uma aplicao com uma camada de negcios separada, a lgica de negcios deve
"preparar" todas as colees que sero usadas pela camada web antes de retornar. Isto
sgnifica que a camada de negcios deve carregar todos os dados e retorn-los j inicializados
para a camada de apresentao que representada para um caso de uso particular.
272
Usando busca em lote
Geralmente, a aplicao chama Hibernate.initialize() para cada coleo que ser usada
pela camada web (essa chamada deve ocorrer antes da sesso ser fechada) ou retorna a
coleo usando uma consulta Hibernate com uma clusula FETCH ou um FetchMode.JOIN
na Criteria. Fica muito mais fcil se voc adotar o modelo Command ao invs do Session
Facade.
Voc tambm pode anexar um objeto previamente carregado em uma nova Sessionmerge()
ou lock() antes de acessar colees no inicializadas (ou outros proxies). O Hibernate no
faz e certamente no deve fazer isso automaticamente, pois isso introduziria semntica em
transaes impromptu.
s vezes voc no quer inicializar uma coleo muito grande, mas precisa de algumas
informaes, como o mesmo tamanho, ou um subconjunto de seus dados.
Voc pode usar um filtro de coleo para saber seu tamanho sem inicializ-la:
O mtodo createFilter() usado tambm para retornar algus dados de uma coleo
eficientemente sem precisar inicializar a coleo inteira:
O Hibernate pode fazer uso eficiente de busca em lote, ou seja o Hibernate pode carregar
diversos proxies no inicializados, se um proxy for acessado (ou colees). A busca em lote
uma otimizao da estratgia da busca de seleo lazy. Existem duas maneiras para voc usar
a busca em lote: no nvel da classe ou no nvel da coleo.
A recuperao em lote para classes/entidades mais fcil de entender. Imagine que voc tem
a seguinte situao em tempo de execuo: voc tem 25 instncias de Cat carregadas em uma
Session, cada Cat possui uma referncia ao seu owner, que da classe Person. A classe
Person mapeada com um proxy, lazy="true". Se voc interar sobre todos os Cat's e chamar
getOwner() em cada, o Hibernate ir por padro executar 25 comandos SELECT(), para buscar
os proxies de owners. Voc pode melhorar esse comportamento especificando um batch-size
no mapeamento da classe Person:
273
Captulo 20. Aumentando o des...
Voc tambm pode habilitar busca em lote de uma coleo. Por exemplo, se cada Person tem
uma coleo preguiosa de Cats e 10 persons esto j carregadas em uma Session, sero
gerados 10 SELECTs ao se interar todas as persons, um para cada chamada de getCats().
Se voc habilitar busca em lote para a coleo de cats no mapeamento da classe Person, o
Hibernate pode fazer uma pr carga das colees:
<class name="Person">
<set name="cats" batch-size="3">
...
</set>
</class
>
A busca em lote de colees particularmente til quando voc tem uma rvore encadeada
de tens, ex.: o tpico padro bill-of-materials (Se bem que um conjunto encadeado ou caminho
materializado pode ser uma opo melhor para rvores com mais leitura.
O que isto significa? A explicao ser atravs de um exemplo. Vamos dizer que ns temos os
seguintes mapeamentos:
<hibernate-mapping>
<class name="Customer">
...
<set name="orders" inverse="true">
<key column="cust_id"/>
<one-to-many class="Order"/>
</set>
</class>
<class name="Order">
...
</class>
274
Perfis de Busca
</hibernate-mapping
>
Normalmente, quando voc recebe uma referncia para um cliente em particular, o conjunto do
cliente de pedidos ser lento, significando que ns ainda no baixamos estes pedidos a partir do
banco de dados. Na maioria das vezes isto bom. Agora vamos imaginar que voc possui um
determinado caso de uso, onde mais eficiente carregar o cliente e outros pedidos juntos. Uma
maneira correta utilizar as estratgias de "busca dinmica" atravs de um HQL ou consultas de
critrio. Entretanto, outra opo usar um perfil de busca para atingir o mesmo objeto. Apenas
adicione o seguinte a seu mapeamento:
<hibernate-mapping>
...
<fetch-profile name="customer-with-orders">
<fetch entity="Customer" association="orders" style="join"/>
</fetch-profile>
</hibernate-mapping
>
ou ainda:
<hibernate-mapping>
<class name="Customer">
...
<fetch-profile name="customer-with-orders">
<fetch association="orders" style="join"/>
</fetch-profile>
</class>
...
</hibernate-mapping
>
275
Captulo 20. Aumentando o des...
Para habilitar a carga de propriedade lazy, preciso ajustar a funo lazy no seu mapeamento
de propriedade:
<class name="Document">
<id name="id">
<generator class="native"/>
</id>
<property name="name" not-null="true" length="50"/>
<property name="summary" not-null="true" length="200" lazy="true"/>
<property name="text" not-null="true" length="2000" lazy="true"/>
</class
>
<instrument verbose="true">
<fileset dir="${testclasses.dir}/org/hibernate/auction/model">
<include name="*.class"/>
</fileset>
</instrument>
</target
>
Uma forma diferente de evitar leitura de coluna desnecessria, ao menos para transaes de
somente leitura, deve-se usar os recursos de projeo do HQL ou consultas por Critrio. Isto evita
a necessidade de processamento de bytecode em build-time e certamente uma melhor soluo.
Voc pode forar a busca antecipada comum de propriedades usando buscar todas as
propriedades no HQL.
276
O Cach de Segundo Nvel
Voc tem a opo de informar o Hibernate sobre qual implementao de cache utilizar,
especificando o nome de uma classe que implementa org.hibernate.cache.CacheProvider
usando a propriedade hibernate.cache.provider_class. O Hibernate vem envolvido com um
nmero de integraes construdas com provedores de cache de fonte aberta (listados abaixo).
Alm disso, voc pode implementar seu prprio e plug-lo como mencionado acima. Note que
as verses anteriores ao padro 3.2 utilizam EhCache como provedor de cache padro.
277
Captulo 20. Aumentando o des...
<cache
usage="transactional|read-write|nonstrict-read-write|read-only"
region="RegionName"
include="all|non-lazy"
/>
278
Estratgia: leitura/escrita no estrita
Importante
Nenhum provedor de cache suporta todas as estratgias de concorrncia de
cache.
A seguinte tabela mostra qual provedor compatvel com qual estratgia de concorrncia.
279
Captulo 20. Aumentando o des...
Quando o flush() for subsequentemente chamado, o estado deste objeto ser sincronizado
com o banco de dados. Se voc no desejar que esta sincronizao acontea ou se voc
estiver processando uma grande quantidade de objetos e precisar gerenciar a memria de forma
eficiente, o mtodo evict() pode ser usado para remover o objeto de suas colees de cache
de primeiro nvel.
Para o cache de segundo nvel, existem mtodos definidos na SessionFactory para despejar o
estado de cache de uma instncia, classe inteira, instncia de coleo ou papel de coleo inteiro.
O CacheMode controla como uma sesso em particular interage com o cache de segundo nvel:
280
O Cache de Consulta
Para navegar o contedo do segundo nvel ou regio de cache de consulta, use oStatistics
API:
hibernate.generate_statistics true
hibernate.cache.use_structured_entries true
hibernate.cache.use_query_cache true
281
Captulo 20. Aumentando o des...
Importante
Nota
Se voc quiser forar um cache de consulta para uma atualizao de sua regio
(independente de quaisquer resultados com cache encontrados nesta regio), voc poder
282
Entendendo o desempenho da Coleo
20.5.1. Taxonomia
O Hibernate define trs tipos bsicos de colees:
Colees de valores
Associaes um-para-muitos
Associaes muitos-para-muitos
A classificao distingue as diversas tabelas e relacionamento de chave externa, mas no nos diz
tudo que precisamos saber sobre o modelo relacional. Para entender completamente a estrutura
relacional e as caractersticas de desempenho, devemos tambm considerar a estrutura da chave
primria que usada pelo Hibernate para atualizar ou deletar linhas de colees. Isto sugere a
seguinte classificao:
Colees indexadas
conjuntos
Bags
Todas as colees indexadas (mapas, listas, matrizes) possuem uma chave primria, que
consiste em colunas <key> e <index>. Neste caso, as atualizaes de coleo so geralmente
muito eficientes. A chave primria pode ser indexada de forma eficiente e uma linha em particular
pode ser localizada de forma eficiente quando o Hibernate tentar atualizar ou delet-la.
Os conjuntos possuem uma chave primria que consiste em <key> e colunas de elemento. Isto
pode ser menos eficiente para alguns tipos de elementos de colees, especialmente elementos
compostos ou textos grandes ou ainda campos binrios. O banco de dados pode no ser capaz de
indexar uma chave primria complexa de forma to eficiente. Por um outro lado, para associaes
um-para-muitos ou muitos-para-muitos, especialmente no caso de identificadores sintticos,
bem provvel que seja to eficiente quanto. Se voc quiser que o SchemaExport crie para voc
uma chave primria de um <set> voc dever declarar todas as colunas como not-null="true".
Os mapeamentos <idbag> definem uma chave substituta, para que elas sejam sempre muito
eficientes ao atualizar. Na verdade, este o melhor caso.
283
Captulo 20. Aumentando o des...
As Bags so os piores casos. Como uma bag permite duplicar valores de elementos e no
possui coluna de ndice, no se deve definir nenhuma chave primria. O Hibernate no tem como
distinguir entre linhas duplicadas. O Hibernate resolve este problema, removendo completamente
em um nico DELETE e recria a coleo quando mudar. Isto pode ser bastante ineficiente.
Note que para uma associao um-para-muitos, a chave primria pode no ser a chave primria
fsica da tabela do banco de dados, mas mesmo neste caso, a classificao acima ainda til.
Isto reflete como o Hibernate "localiza" linhas individuais da coleo.
Existe ainda, mais uma vantagem, das colees indexadas sob conjuntos para associaes
muitos-para-muitos. Por causa da estrutura de um Set, o Hibernate nunca utiliza o comando
UPDATE em uma linha quando um elemento "modificado". As mudanas para o Conjunto
funcionam sempre atravs do comando INSERT e DELETE de linhas individuais. Novamente, esta
considerao no se aplica s associaes um para muitos.
Aps observar que as matrizes no podem ser preguiosas, ns concluimos que as listas, mapas
e bags de id so tipos de colees com maior desempenho (no inverso), com conjuntos que no
ficam atrs. Espera-se que os conjuntos sejam um tipo mais comum de coleo nas aplicaes
Hibernate. Isto porque as semnticas "conjunto" so mais naturais em modelos relacionais.
284
Deletar uma vez
Vamos supor que tenha adicionado um elemento nico uma coleo de tamanho vinte e ento
remove dois elementos. O Hibernate ir editar uma instruo INSERT e duas instrues DELETE,
a no ser que a coleo seja uma bag. Isto certamente desejvel.
No entanto, suponha que removamos dezoito elementos, deixando dois e ento adicionando trs
novos elementos. Existem duas formas possveis de se proceder:
delete dezoito linhas uma por uma e ento insira trs linhas
remova toda a coleo em um SQL DELETE e insira todos os cinco elementos atuais, um por um
O Hibernate no sabe que a segunda opo provavelmente mais rpida neste caso. O Hibernate
no deseha saber a opo, uma vez que tal comportamento deve confundir os triggers do banco
de dados, etc.
Felizmente, voc pode forar este comportamento (ou seja, uma segunda estratgia) a qualquer
momento, descartando (ou seja, desreferenciando) a coleo original e retornando uma coleo
recentemente instanciada com todos os elementos atuais.
claro que, deletar somente uma vez, no se aplica s colees mapeadas inverse="true".
O Hibernate tambm usa o JMX para publicar mtricas se voc habilitar o MBean de
StatisticsService. Voc deve habiliar um MBean nico para todas as suas SessionFactory
ou uma por factory. Veja o seguinte cdigo para exemplos de configuraes minimalsticos:
285
Captulo 20. Aumentando o des...
20.6.2. Mtricas
O Hibernate oferece um nmero de mtricas, desde informaes bem bsicas at especializadas,
somente relevantes a certos cenrios. Todos os contadores disponveis esto descritos na API
da interface Statistics, em trs categorias:
Por exemplo, voc pode verificar a coincidncia de um cache, perder e colocar a relao entre
as entidades, colaes e consultas e tempo mdio que uma consulta precisa. Esteja ciente de
que o nmero de milisegundos sujeito a aproximao em Java. O Hibernate preso preciso
do JVM, em algumas plataformas a preciso chega a ser de 10 segundos.
286
Mtricas
Os Getters simples so usados para acessar mtricas globais (ou seja, no presos uma
entidade em particular, coleo, regio de cache, etc.) Voc pode acessar as mtricas de
uma entidade em particular, coleo ou regio de cache atravs de seu nome e atravs
de sua representao de HQL ou SQL para consultas. Por favor consulte a Javadoc API
Statistics, EntityStatistics, CollectionStatistics, SecondLevelCacheStatistics, e
QueryStatistics para maiores informaes. O seguinte cdigo mostra um exemplo simples:
EntityStatistics entityStats =
stats.getEntityStatistics( Cat.class.getName() );
long changes =
entityStats.getInsertCount()
+ entityStats.getUpdateCount()
+ entityStats.getDeleteCount();
log.info(Cat.class.getName() + " changed " + changes + "times" );
Para trabalhar em todas as entidades, colees, consultas e caches regionais, voc poder
recuperar os nomes de lista de entidades, colees, consultas e caches regionais com
os seguintes mtodos: getQueries(), getEntityNames(), getCollectionRoleNames(), e
getSecondLevelCacheRegionNames().
287
288
Guia de Toolset
possvel realizar uma engenharia de roundtrip com o Hibernate, usando um conjunto de plug-
ins de Eclipse, ferramentas de linha de comando, assim como tarefas Ant.
As Ferramentas do Hibernate atualmente incluem os plug-ins para o IDE de Eclipse assim como
as tarefas para reverter a engenharia dos bancos de dados existentes:
Console: o console uma nova viso em Eclipse. Alm disso, para uma viso geral de rvore de
suas configuraes de console, voc tambm pode obter uma viso interativa de suas classes
persistentes e seus relacionamentos. O console permite que voc execute as consultas HQL
junto ao banco de dados e navegue o resultado diretamente em Eclipse.
Por favor, consulte o pacote Ferramentas do Hibernate e suas documentaes para maiores
informaes.
No entanto, o pacote principal do Hibernate vem em lote com uma ferramenta integrada:
SchemaExport aka hbm2ddl. Ele pode tambm ser usado dentro do Hibernate.
Primeiro, padronize seus arquivos de mapeamento para melhorar o esquema gerado. A prxima
seo cobrir a personalizao do esquema.
289
Captulo 21. Guia de Toolset
Algumas tags aceitam uma funo not-null para gerar uma restrio NOT NULLnas colunas de
tabela e uma funo unique para gerar uma restrio UNIQUE em colunas de tabela.
Uma funo unique-key pode ser usada para agrupar colunas em uma restrio de chave nica.
Atualmente, o valor especfico da funo unique-key no usada para nomear a restrio no
DDL gerado, somente para agrupar as colunas no arquivo de mapeamento.
Uma funo index especifica o nome de um indexe que ser criado, usando a coluna ou colunas
mapeada(s). As colunas mltiplas podem ser agrupadas no mesmo indexe, simplesmente
especificando o mesmo nome de ndice.
Uma funo foreign-key pode ser usada para sobrescrever o nome de qualquer restrio de
chave exterior gerada.
290
Padronizando o esquema
A funo default deixa voc especificar um valor padro para uma coluna. Voc deve atribuir o
mesmo valor propriedade mapeada antes de salvar uma nova instncia da classe mapeada.
291
Captulo 21. Guia de Toolset
O elemento <comment> permite que voc especifique comentrios para esquema gerado.
<property name="balance">
<column name="bal">
<comment
>Balance in USD</comment>
</column>
</property
>
292
Executando a ferramenta
Isto resulta em uma instruo comment on table ou comment on column no DDL gerado, onde
suportado.
Opo Descrio
--quiet no saia do script para stdout
--drop somente suspenda as tabelas
--create somente crie tabelas
--text no exporte para o banco de dados
--output=my_schema.ddl saia do script ddl para um arquivo
--naming=eg.MyNamingStrategy seleciona um NamingStrategy
--config=hibernate.cfg.xml leia a configurao do Hibernate a partir do arquivo
XML
-- leia propriedades de banco de dados a partir dos
properties=hibernate.properties arquivos
--format formatar bem o SQL gerado no script
--delimiter=; ajustar e finalizar o delimitador de linha para o script
21.1.3. Propriedades
As Propriedades do Banco de Daods podem ser especificadas:
293
Captulo 21. Guia de Toolset
<target name="schemaexport">
<taskdef name="schemaexport"
classname="org.hibernate.tool.hbm2ddl.SchemaExportTask"
classpathref="class.path"/>
<schemaexport
properties="hibernate.properties"
quiet="no"
text="no"
drop="no"
delimiter=";"
output="schema-export.sql">
<fileset dir="src">
<include name="**/*.hbm.xml"/>
</fileset>
</schemaexport>
</target
>
Opo Descrio
--quiet no saia do script para stdout
--text no exporte o script ao banco de dados
--naming=eg.MyNamingStrategy seleciona um NamingStrategy
294
Utilizando Ant para atualizaes de esquema incremental
Opo Descrio
-- leia propriedades de banco de dados a partir dos
properties=hibernate.properties arquivos
--config=hibernate.cfg.xml especifique um arquivo .cfg.xml
<target name="schemaupdate">
<taskdef name="schemaupdate"
classname="org.hibernate.tool.hbm2ddl.SchemaUpdateTask"
classpathref="class.path"/>
<schemaupdate
properties="hibernate.properties"
quiet="no">
<fileset dir="src">
<include name="**/*.hbm.xml"/>
</fileset>
</schemaupdate>
</target
>
Opo Descrio
--naming=eg.MyNamingStrategy seleciona um NamingStrategy
295
Captulo 21. Guia de Toolset
Opo Descrio
-- leia propriedades de banco de dados a partir dos
properties=hibernate.properties arquivos
--config=hibernate.cfg.xml especifique um arquivo .cfg.xml
<target name="schemavalidate">
<taskdef name="schemavalidator"
classname="org.hibernate.tool.hbm2ddl.SchemaValidatorTask"
classpathref="class.path"/>
<schemavalidator
properties="hibernate.properties">
<fileset dir="src">
<include name="**/*.hbm.xml"/>
</fileset>
</schemavalidator>
</target
>
296
Exemplo: Pai/Filho
Uma das primeiras coisas que um usurio tenta fazer com o Hibernate modelar um tipo de
relacionamento Pai/Filho. Existem duas abordagens diferentes para isto. Por diversas razes
diferentes, a abordagem mais conveniente, especialmente para novos usurios, modelar ambos
os Parent e Child como classes de entidade com uma associao <one-to-many> a partir
do Parent para o Child. A abordagem alternativa declarar o Child como um <composite-
element>. As semnticas padres da associao um para muitos (no Hibernate), so muito
menos parecidas com as semnticas comuns de um relacionamento pai/filho do que aqueles
de um mapeamento de elemento de composio. Explicaremos como utilizar uma associao
bidirecional um para muitos com cascatas para modelar um relacionamento pai/filho de forma
eficiente e elegante.
Se um objeto removido de uma coleo for uma instncia de um tipo de valor (ex.: um elemento
de composio), este objeto ir parar de ser persistente e seu estado ser completamente
removido do banco de dados. Da mesma forma, ao adicionar uma instncia de tipo de valor
coleo, causar ao estado uma persistncia imediata.
Por outro lado, se uma entidade removida de uma coleo (uma associao um-para-
muitos ou muitos-para-muitos), ela no ser deletada por padro. Este comportamento
completamente consistente, uma mudana para o estado interno de uma outra entidade no
deve fazer com que a entidade associada desaparea. Da mesma forma, ao adicionar uma
entidade coleo, no faz com que a entidade se torne persistente, por padro.
A adio de uma entidade coleo, por padro, meramente cria um link entre as duas entidades.
A remoo da entidade, remover o link. Isto muito apropriado para alguns tipos de casos. No
entanto, no apropriado o caso de um relacionamento pai/filho. Neste caso, a vida do filho est
vinculada ao ciclo de vida do pai.
<set name="children">
<key column="parent_id"/>
297
Captulo 22. Exemplo: Pai/Filho
<one-to-many class="Child"/>
</set
>
Parent p = .....;
Child c = new Child();
p.getChildren().add(c);
session.save(c);
session.flush();
Isto no somente ineficiente como tambm viola qualquer restrio NOT NULL na coluna
parent_id. Ns podemos concertar a violao da restrio de nulabilidade, especificando um
not-null="true" no mapeamento da coleo:
<set name="children">
<key column="parent_id" not-null="true"/>
<one-to-many class="Child"/>
</set
>
As causas subjacentes deste comportamento que o link (a chave exterior parent_id) de p para
c no considerada parte do estado do objeto Child e por isso no criada no INSERT. Ento
a soluo fazer uma parte de link do mapeamento do Child.
Agora que a entidade Child est gerenciando o estado do link, informaremos coleo para no
atualizar o link. Utilizamos o atributo inverse para isto:
298
Ciclo de vida em Cascata
</set
>
299
Captulo 22. Exemplo: Pai/Filho
session.flush();
Da mesma forma, no precisamos repetir este comando com os filhos ao salvar ou deletar um
Parent. O comando seguinte ir remover o p e todos os seus filhos do banco de dados.
no ir remover c do banco de dados. Neste caso, ele somente remover o link para p e causar
uma violao de restrio NOT NULL). Voc precisar delete() de forma explcita o Child.
Agora, no seu caso, um Child no pode existir sem seu pai. Ento, se removermos um Child
da coleo, no iremos mais querer que ele seja deletado. Devido a isto, devemos utilizar um
cascade="all-delete-orphan".
300
Cascatas e unsaved-value
Bem, isto cabe bem no caso de um identificador gerado, mas e os identificadores atribudos e os
identificadores de composio? Isto mais difcil, pois uma vez que o Hibernate no pode utilizar
a propriedade do identificador para distinguir entre um objeto instanciado recentemente, com um
identificador atribudo pelo usurio, e um objeto carregado em uma sesso anterior. Neste caso,
o Hibernate usar tanto um carimbo de data e hora (timestamp) ou uma propriedade de verso,
ou ir na verdade consultar um cache de segundo nvel, ou no pior dos casos, o banco de dados,
para ver se a linha existe.
22.5. Concluso
H muito o que digerir aqui e pode parecer confuso na primeira vez. No entanto, na prtica,
funciona muito bem. A maioria dos aplicativos do Hibernate utiliza o modelo pai/filho em muitos
lugares.
Ns mencionamos uma alternativa neste primeiro pargrafo. Nenhum dos casos acima existem
no caso de mapeamentos <composite-element>, que possuem exatamente a semntica
do relacionamento pai/filho. Infelizmente, existem duas grandes limitaes para elementos
compostos: elementos compostos podem no possuir colees e assim sendo podem no ser
filhos de nenhuma outra entidade a no ser do pai nico.
301
302
Exemplo: Aplicativo Weblog
23.1. Classes Persistentes
As classes persistentes representam um weblog, e um item postado em um weblog. Eles no
devem ser modelados como um relacionamento padro pai/filho, mas usaremos uma bolsa
ordenada ao invs de um conjunto:
package eg;
import java.util.List;
package eg;
import java.text.DateFormat;
import java.util.Calendar;
303
Captulo 23. Exemplo: Aplicat...
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="eg">
<class
name="Blog"
table="BLOGS">
<id
name="id"
column="BLOG_ID">
<generator class="native"/>
</id>
<property
name="name"
column="NAME"
not-null="true"
304
Mapeamentos Hibernate
unique="true"/>
<bag
name="items"
inverse="true"
order-by="DATE_TIME"
cascade="all">
<key column="BLOG_ID"/>
<one-to-many class="BlogItem"/>
</bag>
</class>
</hibernate-mapping
>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="eg">
<class
name="BlogItem"
table="BLOG_ITEMS"
dynamic-update="true">
<id
name="id"
column="BLOG_ITEM_ID">
<generator class="native"/>
</id>
<property
name="title"
column="TITLE"
not-null="true"/>
<property
name="text"
column="TEXT"
not-null="true"/>
<property
name="datetime"
column="DATE_TIME"
not-null="true"/>
<many-to-one
name="blog"
column="BLOG_ID"
not-null="true"/>
305
Captulo 23. Exemplo: Aplicat...
</class>
</hibernate-mapping
>
package eg;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
306
Cdigo Hibernate
tx.commit();
}
catch (HibernateException he) {
if (tx!=null) tx.rollback();
throw he;
}
finally {
session.close();
}
return blog;
}
307
Captulo 23. Exemplo: Aplicat...
}
finally {
session.close();
}
return item;
}
item.setText(text);
308
Cdigo Hibernate
309
Captulo 23. Exemplo: Aplicat...
result = q.list();
tx.commit();
}
catch (HibernateException he) {
if (tx!=null) tx.rollback();
throw he;
}
finally {
session.close();
}
return result;
}
}
310
Exemplo: Vrios Mapeamentos
Este captulo mostra algums mapeamentos de associaes mais complexos.
24.1. Empregador/Empregado
O modelo a seguir, do relacionamento entre Employer e Employee utiliza uma entidade de classe
atual (Employment) para representar a associao. Isto feito porque pode-se ter mais do que
um perodo de trabalho para as duas partes envolvidas. Outros Componentes so usados para
modelar valores monetrios e os nomes do empregado.
<hibernate-mapping>
<id name="id">
<generator class="sequence">
<param name="sequence"
>employment_id_seq</param>
</generator>
</id>
<property name="startDate" column="start_date"/>
<property name="endDate" column="end_date"/>
311
Captulo 24. Exemplo: Vrios ...
</class>
</hibernate-mapping
>
312
Autor/Trabalho
24.2. Autor/Trabalho
Considere o seguinte modelo de relacionamento entre Work, Author e Person. Ns
representamos o relacionamento entre Work e Author como uma associao muitos-para-muitos.
Ns escolhemos representar o relacionamento entre Author e Person como uma associao
um-para-um. Outra possibilidade seria ter Author estendendo Person.
<hibernate-mapping>
<property name="title"/>
<set name="authors" table="author_work">
<key column name="work_id"/>
<many-to-many class="Author" column name="author_id"/>
</set>
313
Captulo 24. Exemplo: Vrios ...
</class>
<property name="alias"/>
<one-to-one name="person" constrained="true"/>
</class>
</hibernate-mapping
>
Existem quatro tabelas neste mapeamento: works, authors e persons matm os dados de
trabalho, autor e pessoa, respectivamente. O author_work uma tabela de associao que liga
autores trabalhos. Abaixo, segue o esquema das tabelas, gerados pelo SchemaExport:
314
Cliente/Ordem/Produto
24.3. Cliente/Ordem/Produto
Agora considere um modelo de relacionamento entre Customer, Order e LineItem e Product.
Existe uma associao um-para-muitos entre Customer e Order, mas como devemos representar
Order / LineItem / Product? Neste exemplo, o LineItem mapeado como uma classe
de associao representando a associao muitos-para-muitos entre Order e Product. No
Hibernate, isto conhecido como um elemento composto.
<hibernate-mapping>
315
Captulo 24. Exemplo: Vrios ...
</hibernate-mapping
>
316
Exemplos variados de mapeamento
<class name="Person">
<id name="name"/>
<one-to-one name="address"
cascade="all">
<formula
>name</formula>
<formula
>'HOME'</formula>
</one-to-one>
<one-to-one name="mailingAddress"
cascade="all">
<formula
>name</formula>
<formula
>'MAILING'</formula>
</one-to-one>
</class>
317
Captulo 24. Exemplo: Vrios ...
<class name="Customer">
<id name="customerId"
length="10">
<generator class="assigned"/>
</id>
<list name="orders"
inverse="true"
cascade="save-update">
<key column="customerId"/>
<index column="orderNumber"/>
<one-to-many class="Order"/>
</list>
</class>
<composite-id name="id"
class="Order$Id">
<key-property name="customerId" length="10"/>
<key-property name="orderNumber"/>
</composite-id>
<property name="orderDate"
type="calendar_date"
not-null="true"/>
<property name="total">
<formula>
( select sum(li.quantity*p.price)
from LineItem li, Product p
where li.productId = p.productId
and li.customerId = customerId
and li.orderNumber = orderNumber )
</formula>
</property>
<many-to-one name="customer"
column="customerId"
insert="false"
update="false"
not-null="true"/>
<bag name="lineItems"
fetch="join"
inverse="true"
cascade="save-update">
<key>
318
Exemplo de chave composta
<column name="customerId"/>
<column name="orderNumber"/>
</key>
<one-to-many class="LineItem"/>
</bag>
</class>
<class name="LineItem">
<composite-id name="id"
class="LineItem$Id">
<key-property name="customerId" length="10"/>
<key-property name="orderNumber"/>
<key-property name="productId" length="10"/>
</composite-id>
<property name="quantity"/>
<many-to-one name="order"
insert="false"
update="false"
not-null="true">
<column name="customerId"/>
<column name="orderNumber"/>
</many-to-one>
<many-to-one name="product"
insert="false"
update="false"
not-null="true"
column="productId"/>
</class>
<class name="Product">
<synchronize table="LineItem"/>
<id name="productId"
length="10">
<generator class="assigned"/>
</id>
<property name="description"
not-null="true"
length="200"/>
<property name="price" length="3"/>
<property name="numberAvailable"/>
<property name="numberOrdered">
<formula>
( select sum(li.quantity)
from LineItem li
where li.productId = productId )
</formula>
</property>
</class
319
Captulo 24. Exemplo: Vrios ...
>
<class name="Person"
discriminator-value="P">
<id name="id"
column="person_id"
unsaved-value="0">
<generator class="native"/>
</id>
320
Associaes em chaves alternativas
<discriminator
type="character">
<formula>
case
when title is not null then 'E'
when salesperson is not null then 'C'
else 'P'
end
</formula>
</discriminator>
<property name="name"
not-null="true"
length="80"/>
<property name="sex"
not-null="true"
update="false"/>
<component name="address">
<property name="address"/>
<property name="zip"/>
<property name="country"/>
</component>
<subclass name="Employee"
discriminator-value="E">
<property name="title"
length="20"/>
<property name="salary"/>
<many-to-one name="manager"/>
</subclass>
<subclass name="Customer"
discriminator-value="C">
<property name="comments"/>
<many-to-one name="salesperson"/>
</subclass>
</class
>
<class name="Person">
<id name="id">
<generator class="hilo"/>
</id>
<one-to-one name="address"
property-ref="person"
321
Captulo 24. Exemplo: Vrios ...
cascade="all"
fetch="join"/>
<set name="accounts"
inverse="true">
<key column="userId"
property-ref="userId"/>
<one-to-many class="Account"/>
</set>
</class>
<class name="Address">
<id name="id">
<generator class="hilo"/>
</id>
</class>
<class name="Account">
<id name="accountId" length="32">
<generator class="uuid"/>
</id>
<many-to-one name="user"
column="userId"
property-ref="userId"/>
</class
>
322
Melhores prticas
Escreva classes compactas e mapeie-as usando <component>:
Use uma classe Endereo para encapsular rua, bairro, estado, CEP. Isto promove a
reutilizao de cdigo e simplifica o refactoring.
323
Captulo 25. Melhores prticas
suponha que o uso direto do JDBC necessariamente mais rpido. Se voc precisar usar
diretamente o JDBC, vale a pena abrir uma Session do Hibernate, embrulhar a sua operao
JDBC como um objeto org.hibernate.jdbc.Work e usar uma conexo JDBC. De modo que
voc possa ainda usar a mesma estratgia de transao e ocultar o provedor a conexo.
324
Use o modelo sesso aberta na visualizao, ou uma fase de construo para evitar problemas
com dados no encontrados.
O Hibernate libera o desenvolvedor de escrever Objetos de Transferncia de Dados (DTO).
Em uma arquitetura tradicional EJB, os DTOs servem dois propsitos: primeiro, eles se
deparam com o problema de que os beans de entidade no so serializveis, depois, eles
implicitamente definem uma fase de construo onde todos os dados a serem utilizados pelo
view so buscados e conduzidos aos DTOs antes mesmo de retornar o controle camada
de apresentao. O Hibernate elimina o primeiro propsito. No entanto, voc ainda precisar
de uma fase de construo (pense em seus mtodos de negcios como tendo um contrato
estrito com a camada de apresentao sobre o quais dados esto disponveis nos objetos
desanexados) a no ser que voc esteja preparado para manter o contexto de persistncia
(sesso) aberto no processo de renderizao da visualizao. Isto no uma limitao do
Hibernate. uma solicitao fundamental para acesso a dados transacionais seguros.
325
326
Consideraes da Portabilidade do
Banco de Dados
26.1. Fundamentos da Portabilidade
Um dos pontos de venda do Hibernate (e realmente Mapeamento do Objeto/Relacional como um
conjunto) a noo da portabilidade do banco de dados. Isto pode significar um usurio de TI
interno migrando a partir de um fornecedor de banco de dados a outro, ou isto pode significar que
um framework ou aplicativo implementvel consumindo o Hibernate para produtos de banco de
dados mltiplos de destinao simultaneamente pelos usurios. Independente do cenrio exato,
a idia bsica que voc queira que o Hibernate o ajude a rodar em referncia a qualquer nmero
de banco de dados sem as alteraes a seu cdigo e preferencialmente sem quaisquer alteraes
ao metadados de mapeamento.
26.2. Dialeto
A primeira linha de portabilidade para o Hibernate o dialeto, que trata-se de uma especializao
de um contrato org.hibernate.dialect.Dialect. Um dialeto encapsula todas as diferenas em
como o Hibernate deve comunicar-se com um banco de dados particular para completar algumas
tarefas como obter um valor de seqncia ou estruturar uma consulta SELECT. O Hibernate
vincula uma variedade de dialetos para muitos dos bancos de dados mais populares. Se voc
achar que seu banco de dados particular no est seguindo os mesmos, no ser difcil escrever
o seu prprio.
Inicializando com a verso 3.2, o Hibernate introduziu a noo de deteco automtica do dialeto
para uso baseado no java.sql.DatabaseMetaData obtido a partir de um java.sql.Connection
para aquele banco de dados. Era muito melhor, esperar que esta resoluo limitada aos bancos
de dados Hibernate soubesse com antecedncia e que em ocasio alguma era configurvel ou
substituvel.
Starting with version 3.3, Hibernate has a fare more powerful way to automatically determine
which dialect to should be used by relying on a series of delegates which implement the
org.hibernate.dialect.resolver.DialectResolver which defines only a single method:
327
Captulo 26. Consideraes da...
. The basic contract here is that if the resolver 'understands' the given database metadata then
it returns the corresponding Dialect; if not it returns null and the process continues to the next
resolver. The signature also identifies org.hibernate.exception.JDBCConnectionException
as possibly being thrown. A JDBCConnectionException here is interpreted to imply a "non
transient" (aka non-recoverable) connection problem and is used to indicate an immediate stop to
resolution attempts. All other exceptions result in a warning and continuing on to the next resolver.
Nota
Hibernate was changed slightly once the implication of this was better understood
so that the insert is delayed in cases where that is feasible.
The underlying issue is that the actual semanctics of the application itself changes in these cases.
Starting with version 3.2.3, Hibernate comes with a set of enhanced [http://in.relation.to/2082.lace]
identifier generators targetting portability in a much different way.
328
Funes do banco de dados
Nota
There are specifically 2 bundled enhancedgenerators:
org.hibernate.id.enhanced.SequenceStyleGenerator
org.hibernate.id.enhanced.TableGenerator
Ateno
Esta uma rea do Hibernate com necessidade de melhoramentos. Este
manuseio de funo funciona atualmente muito bem com o HQL, quando falamos
das preocupaes de portabilidade. No entanto, bastante precria em outros
aspectos.
As funes SQL podem ser referenciadas em diversas maneiras pelos usurios. No entanto,
nem todos os bancos de dados suportam o mesmo conjunto de funo. O Hibernate fornece
um significado de mapeamento do nome da funo lgica para uma delegao que sabe como
manusear aquela funo em particular, mesmo quando usando uma chamada de funo fsica
totalmente diferente.
Importante
Technically this function registration is handled through the
org.hibernate.dialect.function.SQLFunctionRegistry class which is
intended to allow users to provide custom function definitions without having to
provide a custom dialect. This specific behavior is not fully completed as of yet.
It is sort of implemented such that users can programatically register functions with
the org.hibernate.cfg.Configuration and those functions will be recognized
for HQL.
329
330
Referncias
[PoEAA] Padres da Arquitetura do Aplicativo Enterprise . 0-321-12742-0. por Martin Fowler.
Copyright 2003 Pearson Education, Inc.. Addison-Wesley Publishing Company.
[JPwH] Persitncia Java com Hibernate. Segunda Edio do Hibernate em Ao. 1-932394-88-5.
http://www.manning.com/bauer2 . por Christian Bauer e Gavin King. Copyright 2007
Manning Publications Co.. Manning Publications Co..
331
332