Author: xhuang(a)jboss.com
Date: 2007-10-25 20:48:48 -0400 (Thu, 25 Oct 2007)
New Revision: 14136
Modified:
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/association_mapping.xml
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/basic_mapping.xml
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/batch.xml
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/best_practices.xml
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/collection_mapping.xml
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/component_mapping.xml
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/configuration.xml
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/events.xml
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/example_mappings.xml
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/example_parentchild.xml
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/example_weblog.xml
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/filters.xml
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/inheritance_mapping.xml
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/performance.xml
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/persistent_classes.xml
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/preface.xml
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/query_criteria.xml
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/query_hql.xml
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/query_sql.xml
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/session_api.xml
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/toolset_guide.xml
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/transactions.xml
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/tutorial.xml
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/xml.xml
Log:
Remove ^M characters, match with latest English XML
Modified:
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/association_mapping.xml
===================================================================
---
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/association_mapping.xml 2007-10-26
00:46:38 UTC (rev 14135)
+++
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/association_mapping.xml 2007-10-26
00:48:48 UTC (rev 14136)
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="associations">
+<chapter id="associations">
<title>Mapeamento de Associações</title>
Modified:
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/basic_mapping.xml
===================================================================
---
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/basic_mapping.xml 2007-10-26
00:46:38 UTC (rev 14135)
+++
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/basic_mapping.xml 2007-10-26
00:48:48 UTC (rev 14136)
@@ -1,3494 +1,3660 @@
<?xml version='1.0' encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="mapping">
- <title>Mapeamento O/R Bassico</title>
-
- <sect1 id="mapping-declaration" revision="1">
- <title>Declaração de mapeamento</title>
-
- <para>
- Object/relational mappings are usually defined in an XML document. The
mapping
- document is designed to be readable and hand-editable. The mapping language
is
- Java-centric, meaning that mappings are constructed around persistent class
- declarations, not table declarations.
- </para>
-
- <para>
- Note that, even though many Hibernate users choose to write the XML by hand,
- a number of tools exist to generate the mapping document, including XDoclet,
- Middlegen and AndroMDA.
- </para>
-
- <para>
- Lets kick off with an example mapping:
- </para>
-
- <programlisting id="mapping-declaration-ex1"
revision="1"><![CDATA[<?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"/>
-
- <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>]]></programlisting>
-
- <para>
- Discutir agora o conteúdo deste documento de mapeamento. Iremos apenas
descrever
- os elementos do documento e atributos que são utilizados pelo Hibernate em
tempo
- de execução. O documento de mapeamento também contém alguns atributos
adicionais
- e opcionais além de elementos que afetam os esquemas de banco de dados
exportados
- pela ferramenta de exportação de esquemas. (Por exemplo, o atributo
- <literal>not-null</literal>).
- </para>
-
-
-
- <sect2 id="mapping-declaration-doctype" revision="3">
- <title>Doctype</title>
-
- <para>
- Todos os mapeamentos de XML devem declarar o doctype exibido. O DTD atual
pode
- ser encontrado na URL abaixo, no diretório
<literal>hibernate-x.x.x/src/org/
- hibernate </literal> ou no
<literal>hibernate3.jar</literal>. O Hibernate sempre
- irá procurar pelo DTD inicialmente no seu classpath. Se você tentar
localizar
- o DTD usando uma conexão de internet, compare a declaração do seu DTD com
o
- conteúdo do seu classpath
- </para>
-
- <sect3 id="mapping-declaration-entity-resolution">
- <title>EntityResolver</title>
- <para>
- As mentioned previously, Hibernate will first attempt to resolve DTDs
in its classpath. The
- manner in which it does this is by registering a custom
<literal>org.xml.sax.EntityResolver</literal>
- implementation with the SAXReader it uses to read in the xml files.
This custom
- <literal>EntityResolver</literal> recognizes two
different systemId namespaces.
- </para>
- <itemizedlist>
- <listitem>
- <para>
- a <literal>hibernate namespace</literal> is
recognized whenever the
- resolver encounteres a systemId starting with
-
<
literal>http://hibernate.sourceforge.net/</literal>; the resolver
- attempts to resolve these entities via the classlaoder which
loaded
- the Hibernate classes.
- </para>
- </listitem>
- <listitem>
- <para>
- a <literal>user namespace</literal> is recognized
whenever the
- resolver encounteres a systemId using a
<literal>classpath://</literal>
- URL protocol; the resolver will attempt to resolve these
entities
- via (1) the current thread context classloader and (2) the
- classloader which loaded the Hibernate classes.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- An example of utilizing user namespacing:
- </para>
- <programlisting><![CDATA[<?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 types SYSTEM "classpath://your/domain/types.xml">
-]>
-
-<hibernate-mapping package="your.domain">
- <class name="MyEntity">
- <id name="id" type="my-custom-id-type">
- ...
- </id>
- <class>
- &types;
-</hibernate-mapping>]]></programlisting>
- <para>
- Where <literal>types.xml</literal> is a resource in the
<literal>your.domain</literal>
- package and contains a custom <xref
linkend="mapping-types-custom">typedef</xref>.
- </para>
- </sect3>
- </sect2>
-
- <sect2 id="mapping-declaration-mapping" revision="3">
- <title>hibernate-mapping</title>
-
- <para>
- Este elemento tem diversos atributos opcionais. Os atributos
- <literal>schema</literal> e
<literal>catalog</literal> especificam que tabelas
- referenciadas neste mapeamento pertencem ao esquema e/ou ao catalogo
nomeado.
- Se especificados, os nomes das tabelas irão ser qualificados no schema ou
catalog dado.
- Se não, os nomes das tabelas não serão qualificados. O atributo
<literal>default-cascade
- </literal> especifica qual estilo de cascata será assumido pelas
propriedades e
- coleções que não especificarm um atributo
<literal>cascade</literal>. O atributo
- <literal>auto-import</literal> nos deixa utilizar nomes de
classes não qualificados
- na linguagem de consulta, por default.
- </para>
-
- <programlistingco>
- <areaspec>
- <area id="hm1" coords="2 55"/>
- <area id="hm2" coords="3 55"/>
- <area id="hm3" coords="4 55"/>
- <area id="hm4" coords="5 55"/>
- <area id="hm5" coords="6 55"/>
- <area id="hm6" coords="7 55"/>
- <area id="hm7" coords="8 55"/>
- </areaspec>
- <programlisting><![CDATA[<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"
- />]]></programlisting>
- <calloutlist>
- <callout arearefs="hm1">
- <para>
- <literal>schema</literal> (opcional): O nome do
esquema do banco de dados.
- </para>
- </callout>
- <callout arearefs="hm2">
- <para>
- <literal>catalog</literal> (opcional): O nome
do catálogo do banco de dados.
- </para>
- </callout>
- <callout arearefs="hm3">
- <para>
- <literal>default-cascade</literal> (opcional –
default é <literal>nenhum
- </literal>): Um estilo cascata default.
- </para>
- </callout>
- <callout arearefs="hm4">
- <para>
- <literal>default-access</literal> (opcional –
default é <literal>property</literal>):
- A estratégia que o Hibernate deve utilizar para acessar
todas as propridades. Pode
- ser uma implementação própria de
<literal>PropertyAccessor</literal>.
- </para>
- </callout>
- <callout arearefs="hm5">
- <para>
- <literal>default-lazy</literal> (opcional -
default é <literal>true</literal>):
- O valor default para atributos
<literal>lazy</literal> da classe e dos
- mapeamentos de coleções.
- </para>
- </callout>
- <callout arearefs="hm6">
- <para>
- <literal>auto-import</literal> ((opcional -
default é <literal>true</literal>):
- Especifica se nós podemos usar nomes de classess não
qualificados
- (das classes deste mapeamento) na linguagem de consulta.
- </para>
- </callout>
- <callout arearefs="hm7">
- <para>
- <literal>package</literal> (opcional):
Especifica um prefixo da package para
- assumir para nomes de classes não qualificadas no documento
de mapeamento.
- </para>
- </callout>
- </calloutlist>
- </programlistingco>
-
- <para>
- Se voce tem duas classes persistentes com o mesmo nome (não
qualificadas), você deve
- setar <literal>auto-import="false"</literal>. O
Hibernate irá gerar uma exceção se
- você tentar setar duas classes para o mesmo nome "importado".
- </para>
-
- <para>
- Observe que o elemento <literal>hibernate-mapping</literal>
permite a você
- aninhar diversos mapeamentos de
<literal><class></literal> persistentes,
- como mostrado abaixo. Entretanto, é uma boa prática (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 nomea-la
após
- a superclasse persistente, por exemplo:
<literal>Cat.hbm.xml</literal>,
- <literal>Dog.hbm.xml</literal>, ou se estiver usando
herança,
- <literal>Animal.hbm.xml</literal>.
- </para>
-
- </sect2>
-
- <sect2 id="mapping-declaration-class" revision="3">
- <title>class</title>
-
- <para>
- Você pode declarar uma classe persistente utilizando o elemento
- <literal>class</literal>:
- </para>
-
- <programlistingco>
- <areaspec>
- <area id="class1" coords="2 55"/>
- <area id="class2" coords="3 55" />
- <area id="class3" coords="4 55"/>
- <area id="class4" coords="5 55" />
- <area id="class5" coords="6 55"/>
- <area id="class6" coords="7 55" />
- <area id="class7" coords="8 55"/>
- <area id="class8" coords="9 55" />
- <area id="class9" coords="10 55" />
- <area id="class10" coords="11 55"/>
- <area id="class11" coords="12 55"/>
- <area id="class12" coords="13 55"/>
- <area id="class13" coords="14 55"/>
- <area id="class14" coords="15 55"/>
- <area id="class15" coords="16 55"/>
- <area id="class16" coords="17 55"/>
- <area id="class17" coords="18 55"/>
- <area id="class18" coords="19 55"/>
- <area id="class19" coords="20 55"/>
- <area id="class20" coords="21 55"/>
- <area id="class21" coords="22 55"/>
- </areaspec>
- <programlisting><![CDATA[<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"
- where="arbitrary sql where condition"
- persister="PersisterClass"
- batch-size="N"
- optimistic-lock="none|version|dirty|all"
- lazy="true|false"
- entity-name="EntityName"
- check="arbitrary sql check condition"
- rowid="rowid"
- subselect="SQL expression"
- abstract="true|false"
- node="element-name"
-/>]]></programlisting>
- <calloutlist>
- <callout arearefs="class1">
- <para>
- <literal>name</literal> (opcional): O nome da
classe Java inteiramente qualificado
- da classe persistente (ou interface); Se o atributo é
ausente, assume-se que o
- mapeamento é para intidades não-POJO.
- </para>
- </callout>
- <callout arearefs="class2">
- <para>
- <literal>table</literal> (opcional – default para
nomes de classes não
- qualificadas) O nome da sua tabela do banco de dados.
- </para>
- </callout>
- <callout arearefs="class3">
- <para>
- <literal>discriminator-value</literal> (opcional
– default para o nome da classe):
- Um valor que distingue subclasses individuais, usadas para o
comportamento polimorfico.
- Valores aceitos incluem <literal>null</literal> e
<literal>not null</literal>
- </para>
- </callout>
- <callout arearefs="class4">
- <para>
- <literal>mutable</literal> (opcional - valor
default <literal>true</literal>):
- Especifica que instancias da classe são (ou não) mutáveis
- </para>
- </callout>
- <callout arearefs="class5">
- <para>
- <literal>schema</literal> (opcional): Sobrepõe o
nome do esquema especificado
- pelo elemento root
<literal><hibernate-mapping></literal>.
- </para>
- </callout>
- <callout arearefs="class6">
- <para>
- <literal>catalog</literal> (opcional): Sobrepõe o
nome do catálogo especificado
- pelo elemento root
<literal><hibernate-mapping></literal>.
- </para>
- </callout>
- <callout arearefs="class7">
- <para>
- <literal>proxy</literal> (opcional): Especifica
um interface para ser
- utilizada pelos proxies de inicialização tardia. Você pode
especificar o
- nome da própria classe.
- </para>
- </callout>
- <callout arearefs="class8">
- <para>
- <literal>dynamic-update</literal> (opcional,
valor default <literal>false</literal>):
- Especifica que o SQL de <literal>UPDATE</literal>
deve ser gerado em tempo de
- execução e conter apenas aquelas colunas cujos valores foram
alterados.
- </para>
- </callout>
- <callout arearefs="class9">
- <para>
- <literal>dynamic-insert</literal> (opcional,
valor default <literal>false</literal>):
- Especifica que o SQL de
<literal>INSERT</literal> deve ser gerado em tempo de
- execução e conter apenas aquelas colunas cujos valores não
estão nulos.
- </para>
- </callout>
- <callout arearefs="class10">
- <para>
- <literal>select-before-update</literal>
(opcional, valor default <literal>false</literal>):
- Especifica que o Hibernate
<emphasis>never</emphasis> deve executar um SQL de
- <literal>UPDATE</literal> a não ser que com
certeza um objeto está atualmente modificado.
- Em certos casos (atualmente, apenas quando um objeto
transiente foi associado com uma nova
- sessão utilizando <literal>update()</literal>),
isto significa que o Hibernate ira executar
- uma instrução SQL de <literal>SELECT</literal>
adicional para determinar se um
- <literal>UPDATE</literal> é necessário nesse
momento.
- </para>
- </callout>
- <callout arearefs="class11">
- <para>
- <literal>polymorphism</literal> (opcional,
default para <literal>implicit</literal>):
- Determina se deve ser utilizado a query polimorfica implicita
ou explicitamente.
- </para>
- </callout>
- <callout arearefs="class12">
- <para>
- <literal>where</literal> (opicional) especifica
um comando SQL <literal>WHERE</literal>
- arbitrário para ser usado quando da recuperação de objetos
desta classe.
- </para>
- </callout>
- <callout arearefs="class13">
- <para>
- <literal>persister</literal> (opcional):
Espeicifca uma <literal>ClassPersister</literal>
- customizada.
- </para>
- </callout>
- <callout arearefs="class14">
- <para>
- <literal>batch-size</literal> (opcional, valor
default <literal>1</literal>) especifica um
- "tamanho de lote" para a recuperação de instancias
desta classe pelo identificador.
- </para>
- </callout>
- <callout arearefs="class15">
- <para>
- <literal>optimistic-lock</literal> (octional,
valor default <literal>version</literal>):
- Determina a estratégia de bloqueio.
- </para>
- </callout>
- <callout arearefs="class16">
- <para>
- <literal>lazy</literal> (opcional): A recuperação
tardia pode ser completamente
- desabilitada, setando
<literal>lazy="false"</literal>.
- </para>
- </callout>
- <callout arearefs="class17">
- <para>
- <literal>entity-name</literal> (opcional, default
para o nome da classe): O
- Hibernate3 permite uma classe ser mapeada multiplas vezes,
(potencialmente,para
- diferentes tabelas), e permite mapeamentos de entidades que
são representadas
- por Maps ou XML no nível Java. Nestes casos, você deve
especificar um nome
- arbitrário explicitamente para a entidade. Veja <xref
linkend="persistent-classes-dynamicmodels"/>
- e <xref linkend="xml"/> para maiores
informações.
- </para>
- </callout>
- <callout arearefs="class18">
- <para>
- <literal>check</literal> (opcional): Uma
expressão SQL utilizada para gerar uma
- constraint de <emphasis>verificação</emphasis> de
múltiplas linhas para a geração
- automática do esquema.
- </para>
- </callout>
- <callout arearefs="class19">
- <para>
- <literal>rowid</literal> (opcional): O Hibernate
poder usar as assim chamadas
- ROWIDs em bancos de dados que a suportam. Por exemplo, no
Oracle, o Hibernate
- pode utilizar a coluna extra rowid para atualizações mais
rápidas se você
- configurar esta opção para
<literal>rowid</literal>. Um ROWID é uma implementação
- que representa de maneira detalhada a localização física de
uma determinada
- tupla armazenado.
- </para>
- </callout>
- <callout arearefs="class20">
- <para>
- <literal>subselect</literal> (optional): Maps an
immutable and read-only entity
- to a database subselect. Useful if you want to have a view
instead of a base table,
- but don't. See below for more information.
- <literal>subselect</literal> (opcional): Mapeia
uma entidade imutavel e somente
- de leitura para um subconjunto do banco de dados. Útil se
você quiser ter uma
- view em vez de uma tabela. Veja abaixo para mais
informações.
- </para>
- </callout>
- <callout arearefs="class21">
- <para>
- <literal>abstract</literal> (opcional): Utilizada
para marcar superclasses
- abstratas em hierarquias
<literal><union-subclass></literal>.
- </para>
- </callout>
- </calloutlist>
- </programlistingco>
-
- <para>
- É perfeitamente aceitável para uma classe persitente nomeada ser uma
interface. Você deverá
- então declarar as classes implementadas desta interface utilizando o
elemento
- <literal><subclass></literal>. Você pode
persistir qualquer classe de aninhada
- <emphasis>estatica</emphasis>. Você deverá especificar o nome
da classe usando a forma
- padrão, por exemplo: <literal>eg.Foo$Bar</literal>.
- </para>
-
- <para>
- Classes imutáveis,
<literal>mutable="false"</literal>, não podem ser modificadas ou
excluídas
- pela aplicação. Isso permite ao Hibernate fazer alguns aperfeiçoamentos
de performance.
- </para>
-
- <para>
- O atributo opcional <literal>proxy</literal> habilita a
inicialização tardia das
- instâncias persistentes da classe. O Hibernate irá retornar CGLIB proxies
como implementado
- na interface nomeada. O objeto persistente atual será carregado quando
um método do proxy
- for invocado. Veja "Inicializando coleções e proxies" abaixo.
- </para>
-
- <para>Polimorfismo <emphasis>implícito</emphasis> significa
que instâncias de uma classe
- serão retornada por uma query que dá nome a qualquer superclasse ou
interface implementada,
- ou a classe e as instancias de qualquer subclasse da classe será
retornada por umq query
- que nomeia a classe por si. Polimorfismo
<emphasis>explícito</emphasis> significa que
- instancias da classe serão retornadas apenas por queries que
explicitamente nomeiam a
- classe e que queries que nomeiam as classes irão retornar apenas
instancias de subclasses
- mapeadas dentro da declaração
<literal><class></literal> como uma
- <literal><subclass></literal> ou
<literal><joined-subclass></literal>.
- Para a maioria dos casos, o valor default
<literal>polymorphism="implicit"</literal>,
- é apropriado. Polimorfismo explicito é útil quando duas classes distintas
estão mapeadas
- para a mesma tabela (isso permite um classe "peso leve" que
contem um subconjunto
- de colunas da tabela).
- </para>
-
- <para>
- O atributo <literal>persister</literal> deixa você customizar
a estratégia de persistência
- utilizada para a classe. Você pode, por exemplo, especificar sua prórpia
subclasse do
- <literal>org.hibernate.persister.EntityPersister</literal> ou
você pode criar
- uma implementação completamente nova da interface
- <literal>org.hibernate.persister.ClassPersister</literal> que
implementa a persistência
- através de, por exemplo, chamadas a stored procedeures, serialização de
arquivos flat ou
- LDAP. Veja
<literal>org.hibernate.test.CustomPersister</literal> para um exemplo
- simples (de "persistencia" para uma
<literal>Hashtable</literal>).
- </para>
-
- <para>
- Observe que as configurações
<literal>dynamic-update</literal> e
- <literal>dynamic-insert</literal> não sao herdadas pelas
subclasses e assim podem tambem
- ser especificadas em elementos
<literal><subclass></literal> or
- <literal><joined-subclass></literal>. Estas
configurações podem incrementar a
- performance em alguns casos, mas pode realmente diminuir a performance em
outras.
- Use-as de forma bastante criteriosa.
- </para>
-
- <para>
- O uso de <literal>select-before-update</literal> geralmente
irá diminuir a performance. Ela é
- muito útil para prevenir que uma trigger de atualização no banco de dados
seja ativada
- desnecessariamente, se você reconectar um nó de uma instancia
desconectada em uma
- <literal>Session</literal>.
- </para>
-
- <para>
- Se você ativar <literal>dynamic-update</literal>, você terá
de escolher
- a estratégia de bloqueio otimista:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <literal>version</literal> verifica a versão e a hora
das colunas
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>all</literal> cverifica todas as colunas
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>dirty</literal> verifica as colunas
modificadas, permitindo
- alguns updates concorrentes
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>none</literal> não utiliza o bloqueio
otimista
- </para>
- </listitem>
- </itemizedlist>
- <para>
- Nós <emphasis>recomendamos</emphasis> com muita enfase que
você utilize a
- versão e a hora das colunas para o bloqueio otimista com o Hibernate.
- Esta é a melhor estratégia com respeito a performance e é a única
estratégia
- que trata corretamente as modificações efetuadas em instancias
desconectadas
- (por exemplo, quando <literal>Session.merge()</literal> é
utilizado).
-
- </para>
-
- <para>
- Não ha diferença entre uma view e uma tabela para o mapeamento do
Hibernate, e como
- esperado isto é transparente no nível do banco de dados (observe que
alguns bancos de
- dados não suportam views apropriadamente, especialmente com updates).
Algumas vezes,
- você quer utilizar uma view, ma snão pode cria-la no banco de dados (por
exemplo,
- com um esquema legado). Neste caso, você pode mapear uma entidade
imutável e de
- somente leitura, para uma dada expressão SQL, que representa um
subselect:
- </para>
-
- <programlisting><![CDATA[<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"/>
- <synchronize table="bid"/>
- <id name="name"/>
- ...
-</class>]]></programlisting>
-
- <para>
- Declare as tabelas para sincronizar com esta entidade, garantindo que o
auto-flush
- ocorra corretamente, e que as queries para esta entidade derivada não
retornem dados
- desatualizados. O
<literal><subselect></literal> está disponível tanto como um
- atributo como um elemento mapeado nested.
- </para>
-
- </sect2>
-
- <sect2 id="mapping-declaration-id" revision="4">
- <title>id</title>
-
- <para>
- Classes mapeadas <emphasis>precisam</emphasis> declarar a
coluna de chave primaria da
- tabela do banco de dados. Muitas classes irão tambem ter uma propriedade
ao estilo
- Java-Beans declarando o identificador unico de uma instancia. O elemento
- <literal><id></literal> define o mapeamento
desta propriedade para a chave primária.
- </para>
-
- <programlistingco>
- <areaspec>
- <area id="id1" coords="2 70"/>
- <area id="id2" coords="3 70" />
- <area id="id3" coords="4 70"/>
- <area id="id4" coords="5 70" />
- <area id="id5" coords="6 70" />
- </areaspec>
- <programlisting><![CDATA[<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/(a)attribute|."
-
- <generator class="generatorClass"/>
-</id>]]></programlisting>
- <calloutlist>
- <callout arearefs="id1">
- <para>
- <literal>name</literal> (opcional): O nome do
identificador.
- </para>
- </callout>
- <callout arearefs="id2">
- <para>
- <literal>type</literal> (opcional): Um nome que
indica o tipo no Hibernate.
- </para>
- </callout>
- <callout arearefs="id3">
- <para>
- <literal>column</literal> (opcional – default
para o a propridade name): O
- nome coluna chave primaria.
- </para>
- </callout>
- <callout arearefs="id4">
- <para>
- <literal>unsaved-value</literal> (opcional -
default para um valor "sensível"):
- Uma propriedade de identificação que indica que a instancia
foi novamente
- instanciada (unsaved), diferenciando de instancias
desconectadas que foram
- salvas ou carregadas em uma sessão anterior.
- </para>
- </callout>
- <callout arearefs="id5">
- <para>
- <literal>access</literal> (opcional - valor
default <literal>property</literal>): A
- estratégia que o Hiberante deve utilizar para acessar o valor
da propriedade
- </para>
- </callout>
- </calloutlist>
- </programlistingco>
-
- <para>
- Se o atributo <literal>name</literal> não for declarado,
assume-se que a classe não tem
- a propriedade de identificação.
- </para>
-
- <para>
- O atributo <literal>unsaved-value</literal> não é mais
necessário no Hibernate 3.
- </para>
-
- <para>
- Há declaração alternativa
<literal><composite-id></literal> permite o acesso a
- dados legados com chaves compostas. Nós desencorajamos fortemente o seu
uso por
- qualquer pessoa.
- </para>
-
- <sect3 id="mapping-declaration-id-generator"
revision="2">
- <title>Generator</title>
-
- <para>
- O elemento filho opcional
<literal><generator></literal> nomeia uma classe Java
- usada para gerar identificadores unicos para instancias de uma classe
persistente.
- Se algum parâmetro é requerido para configurar ou inicializar a
instancia geradora,
- eles são passados utilizando o elemento
<literal><param></literal>.
- </para>
-
- <programlisting><![CDATA[<id name="id"
type="long" column="cat_id">
- <generator class="org.hibernate.id.TableHiLoGenerator">
- <param name="table">uid_table</param>
- <param name="column">next_hi_value_column</param>
- </generator>
-</id>]]></programlisting>
-
- <para>
- Todos os generators implementam a interface
<literal>org.hibernate.id.IdentifierGenerator</literal>.
- Esta é uma interface bem simples; algumas aplicações podem prover sua
própria implementação
- esepecializada. Entretanto, o Hibernate disponibiliza um conjunto de
implementações internamente.
- Há nomes de atalhos para estes generators próprios:
- <variablelist>
- <varlistentry>
-
<term><literal>increment</literal></term>
- <listitem>
- <para>
- gera identificadores dos tipos
<literal>long</literal>, <literal>short</literal> ou
- <literal>int</literal> que são unicos apenas
quando nenhum outro processo está
- inserindo dados na mesma tabela. <emphasis>Não
utilize em ambientes
- de cluster.</emphasis>
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>identity</literal></term>
- <listitem>
- <para>
- suporta colunas de identidade em DB2, MySQL, MS SQL
Server, Sybase e
- HypersonicSQL. O identificador retornado é do tipo
<literal>long</literal>,
- <literal>short</literal> ou
<literal>int</literal>.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>sequence</literal></term>
- <listitem>
- <para>
- utiliza uma sequence em DB2, PostgreSQL, Oracle, SAP DB,
McKoi ou um
- generator no Interbase. O identificador de retorno é do
tipo <literal>
- long</literal>,
<literal>short</literal> ou <literal>int</literal>.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>hilo</literal></term>
- <listitem>
- <para
id="mapping-declaration-id-hilodescription" revision="1">
- utiliza um algoritmo hi/lo para gerar de forma eficiente
identificadores do tipo
- <literal>long</literal>,
<literal>short</literal> ou <literal>int</literal>,
- a partir de uma tabela e coluna fornecida (por default
- <literal>hibernate_unique_key</literal> e
<literal>next_hi</literal>)
- como fonte para os valores hi. O algoritmo hi/lo gera
identificadores que são
- únicos apenas para um banco de dados particular.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>seqhilo</literal></term>
- <listitem>
- <para>
- utiliza um algoritmo hi/lo para gerar de forma eficinete
identificadores do tipo
- <literal>long</literal>,
<literal>short</literal> ou <literal>int</literal>,
- a partir de uma sequence de banco de dados fornecida.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>uuid</literal></term>
- <listitem>
- <para>
- utiliza um algortimo UUID de 128-bits para gerar
identificadores do
- tipo string, unicos em uma rede(o endereço IP é
utilizado). O UUID é
- codificado como um string de digitos hexadecimais de
tamanho 32.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>guid</literal></term>
- <listitem>
- <para>
- utiliza um string GUID gerado pelo banco de dados no MS
SQL Server
- e MySQL.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>native</literal></term>
- <listitem>
- <para>
- seleciona entre <literal>identity</literal>,
<literal>sequence</literal>
- ou <literal>hilo</literal> dependendo das
capacidades do banco de dados
- utilizado.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>assigned</literal></term>
- <listitem>
- <para>
- deixa a aplicação definir um identificador para o objeto
antes que o
- <literal>save()</literal> seja chamado. Esta
é a estratégia default
- se nenhum elemento
<literal><generator></literal> é especificado.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>select</literal></term>
- <listitem>
- <para>
- retorna a chave primaria recuperada por uma trigger do
banco de
- dados, selecionado uma linha pela chave única e
recuperando o valor
- da chave primária.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>foreign</literal></term>
- <listitem>
- <para>
- utiliza o identificador de um outro objeto associado.
Normalmente utilizado
- em conjunto com uma associaçõa de chave primária do tipo
-
<literal><one-to-one></literal>.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
-
<term><literal>sequence-identity</literal></term>
- <listitem>
- <para>
- a specialized sequence generation strategy which utilizes
a
- database sequence for the actual value generation, but
combines
- this with JDBC3 getGeneratedKeys to actually return the
generated
- identifier value as part of the insert statement
execution. This
- strategy is only known to be supported on Oracle 10g
drivers
- targetted for JDK 1.4. Note comments on these insert
statements
- are disabled due to a bug in the Oracle drivers.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
-
- </para>
- </sect3>
-
- <sect3 id="mapping-declaration-id-hilo"
revision="1">
- <title>Algoritmo Hi/lo</title>
- <para>
- Os geradores <literal>hilo</literal> e
<literal>seqhilo</literal> fornecem duas
- implementações alternativas do algoritmo hi/lo, uma solução
preferencial para a geração
- de identificadores. A primeira implementação requer uma tabela
especial do banco de
- dados para manter o proximo valor "hi" disponível. A
segunda utiliza uma seqüência
- do estilo Oracle (quando suportado).
- </para>
-
- <programlisting><![CDATA[<id name="id"
type="long" column="cat_id">
- <generator class="hilo">
- <param name="table">hi_value</param>
- <param name="column">next_value</param>
- <param name="max_lo">100</param>
- </generator>
-</id>]]></programlisting>
-
- <programlisting><![CDATA[<id name="id"
type="long" column="cat_id">
- <generator class="seqhilo">
- <param name="sequence">hi_value</param>
- <param name="max_lo">100</param>
- </generator>
-</id>]]></programlisting>
-
- <para>
- Infelizemente, voce não pode utilizar
<literal>hilo</literal> quando estiver
- fornecendo sia propria <literal>Connection</literal>
para o Hibernate. Quando o
- Hibernate está usando um datasource do servidor de aplicações para
obter conexões
- suportadas com JTA, você precisa configurar adequadamente o
-
<literal>hibernate.transaction.manager_lookup_class</literal>.
- </para>
- </sect3>
-
- <sect3 id="mapping-declaration-id-uuid">
- <title>UUID algorithm</title>
- <para>
- O UUID contem: o endereço IP, hora de inicio da JVM (com precisão de
um quarto
- de segundo), a hora do sistema e um valor contador (unico dentro da
JVM).
- Não é possivel obter o endereço MAC ou um endereço de memória do
código Java,
- assim este é o melhor que pode ser feito sem utilizar JNI.
- </para>
- </sect3>
-
- <sect3 id="mapping-declaration-id-sequences">
- <title>Colunas de identidade e sequencias</title>
- <para>
- Para bancos de dados que suportam colunas de identidade (DB2, MySQL,
Sybase,
- MS SQL), você pode utilizar uma geração de chave
<literal>identity</literal>.
- Para bancos de dados que suportam sequencias (DB2, Oracle,
PostgreSQL, Interbase,
- McKoi, SAP DB) voce pode utilizar a geração de chaves no estilo
- <literal>sequence</literal>. As duas estratégias requerem
duas consultas SQL
- para inserir um novo objeto.
- </para>
-
- <programlisting><![CDATA[<id name="id"
type="long" column="person_id">
- <generator class="sequence">
- <param name="sequence">person_id_sequence</param>
- </generator>
-</id>]]></programlisting>
-
- <programlisting><![CDATA[<id name="id"
type="long" column="person_id" unsaved-value="0">
- <generator class="identity"/>
-</id>]]></programlisting>
-
- <para>
- Para desenvolvimento multi-plataforma, a estratégia
<literal>native</literal>
- irá escolher entre as estratégias i
<literal>identity</literal>,
- <literal>sequence</literal> e
<literal>hilo</literal>, dependendo das
- capacidades do banco de dados utilizado.
- </para>
- </sect3>
-
- <sect3 id="mapping-declaration-id-assigned">
- <title>Identificadores especificados</title>
- <para>
- Se você quer que a aplicação especifique os identificadores
- (em vez do Hibernate gerá-los) você deve utilizar o gerador
- <literal>assigned</literal>. Este gerador especial irá
utilizar o valor
- do identificador especificado para a propriedade de identificação do
objeto.
- Este gerador é usado quando a chave primaria é a chave natural em vez
de uma
- surrogate key. Este é o comportamento padrão se você não especificar
- um elemento
<literal><generator></literal>.
- </para>
-
- <para>
- Escolher o gerador <literal>assigned</literal> faz com
que o Hibernate
- utilize
<literal>unsaved-value="undefined"</literal>, forçando o Hibernate
- ir até o banco de dados para determinar se uma instância está
transiente ou
- desasociada, a menos que haja uma versão ou uma propriedade
timestamp,
- ou você pode definir
<literal>Interceptor.isUnsaved()</literal>.
- </para>
- </sect3>
-
- <sect3 id="mapping-declaration-id-select">
- <title>Chaves primárias geradas por triggers</title>
- <para>
- Apenas para sistemas legados (o Hibernate nao gera DDL com
triggers).
- </para>
-
- <programlisting><![CDATA[<id name="id"
type="long" column="person_id">
- <generator class="select">
- <param name="key">socialSecurityNumber</param>
- </generator>
-</id>]]></programlisting>
-
- <para>
- No exemplo acima, há uma única propriedade com valor nomeada
- <literal>socialSecurityNumber</literal> definida pela
classe,
- uma chave natural, e uma surrogate key nomeada
- <literal>person_id</literal> cujo valor é gerado pro uma
trigger.
- </para>
-
- </sect3>
-
- </sect2>
-
- <sect2 id="mapping-declaration-compositeid"
revision="3">
- <title>composite-id</title>
-
- <programlisting><![CDATA[<composite-id
- name="propertyName"
- class="ClassName"
- mapped="true|false"
- access="field|property|ClassName">
- node="element-name|."
-
- <key-property name="propertyName" type="typename"
column="column_name"/>
- <key-many-to-one name="propertyName class="ClassName"
column="column_name"/>
- ......
-</composite-id>]]></programlisting>
-
- <para>
- Para tabelas com uma chave composta, você pode mapear múltiplas
propriedades
- da classe como propriedades de identificação. O elemento
- <literal><composite-id></literal> aceita o
mapeamento da propriedade
- <literal><key-property></literal> e mapeamentos
- <literal><key-many-to-one></literal>como
elements filhos.
- </para>
-
- <programlisting><![CDATA[<composite-id>
- <key-property name="medicareNumber"/>
- <key-property name="dependent"/>
-</composite-id>]]></programlisting>
-
- <para>
- Sua classe persistente <emphasis>precisa</emphasis> sobre
escrever
- <literal>equals()</literal> e
<literal>hashCode()</literal> para implementar
- identificadores compostos igualmente. E precisa também implementar
- <literal>Serializable</literal>.
- </para>
-
- <para>
- Infelizmente, esta solução para um identificador composto significa que
um objeto
- persistente é seu próprio identificador. Não há outro "handle"
que o próprio objeto.
- Você mesmo precisa instanciar uma instância de outra classe persistente e
preencher
- suas propriedades de identificação antes que você possa dar um
<literal>load()</literal>
- para o estado persistente associado com uma chave composta. Nos chamamos
esta
- solução de identificador composto
<emphasis>embedded</emphasis> e não aconselhamos
- para aplicações sérias.
- </para>
-
- <para>
- Uma segunda solução é o que podemos chamar de identificador composto
- <emphasis>mapped</emphasis> quando a propriedades de
identificação nomeadas dentro do
- elemento <literal><composite-id></literal>
estão duplicadas tando na classe
- persistente como em uma classe de identificação separada.
- </para>
-
- <programlisting><![CDATA[<composite-id
class="MedicareId" mapped="true">
- <key-property name="medicareNumber"/>
- <key-property name="dependent"/>
-</composite-id>]]></programlisting>
-
- <para>
- No exemplo, ambas as classes de identificação compostas,
<literal>MedicareId</literal>,
- e a própria classe entidade tem propriedades nomeadas
<literal>medicareNumber</literal>
- e <literal>dependent</literal>. A classe identificadora
precisa sobrepor
- <literal>equals()</literal> e
<literal>hashCode()</literal> e implementar
- <literal>Serializable</literal>. A desvantagem desta solução
é obvia –
- duplicação de código.
- </para>
-
- <para>
- Os seguintes atributos ão utilizados para especificar o mapeamento de
- um identificador composto:
- </para>
-
- <itemizedlist spacing="compact">
- <listitem>
- <para>
- <literal>mapped</literal> mapped (opcional, valor
default <literal>false
- </literal>): indica que um identificar composto mapeado é
usado, e que as
- propriedades de mapeamento contidas refere-se tanto a classe
entidade e
- a classe de identificação composta.
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>class</literal> (opcional, mas requerida
para um identificar composto
- mapeado): A classe usada como um identificador composto.
- </para>
- </listitem>
- </itemizedlist>
-
- <para>
- Nós iremos descrever uma terceira e as vezes mais conveniente solução,
onde o
- identificador composto é implementado como uma classe componente na
- <xref linkend="components-compositeid"/>. Os atributos
descritos abaixo aplicam-se
- apenas para esta solução:
- </para>
-
- <itemizedlist spacing="compact">
- <listitem>
- <para>
- <literal>name</literal> (opcional, requerida para
esta solução): Uma
- propriedade do tipo componente que armazena o identificador
composto
- (veja capítulo 9)
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>access</literal> (opcional - valor default
<literal>property</literal>):
- A estartégia Hibernate que deve ser utilizada para acessar o
valor da propriedade.
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>class</literal> (opcional - valor default
para o tipo de propriedade
- determiando por reflexão) : A classe componente utilizada como um
identificador
- composto (veja a próxima sessão).
- </para>
- </listitem>
- </itemizedlist>
-
- <para>
- Esta terceira solução, um <emphasis>componente de
identificação</emphasis>, é o que nós
- recomendamos para a maioria das aplicações.
- </para>
-
- </sect2>
-
- <sect2 id="mapping-declaration-discriminator"
revision="3">
- <title>discriminator</title>
-
- <para>
- O elemento <literal><discriminator></literal>
é necessário para persistência
- polimórfica utilizando a estratégia de mapeamento
table-per-class-hierarchy e declara
- uma coluna discriminadora da tabela. A coluna discriminadora contem
valores de marcação
- que dizem a camada de persistência qual subclasse instanciar para uma
linha particular.
- Um restrito conjunto de tipos que podem ser utilizados:
<literal>string</literal>,
- <literal>character</literal>,
<literal>integer</literal>, <literal>byte</literal>,
- <literal>short</literal>,
<literal>boolean</literal>,
- <literal>yes_no</literal>,
<literal>true_false</literal>.
- </para>
-
- <programlistingco>
- <areaspec>
- <area id="discriminator1" coords="2 60"/>
- <area id="discriminator2" coords="3 60" />
- <area id="discriminator3" coords="4 60" />
- <area id="discriminator4" coords="5 60" />
- <area id="discriminator5" coords="6 60" />
- </areaspec>
- <programlisting><![CDATA[<discriminator
- column="discriminator_column"
- type="discriminator_type"
- force="true|false"
- insert="true|false"
- formula="arbitrary sql expression"
-/>]]></programlisting>
- <calloutlist>
- <callout arearefs="discriminator1">
- <para>
- <literal>column</literal> (opcional - valor
default <literal>class</literal>)
- o nome da coluna discriminadora
- </para>
- </callout>
- <callout arearefs="discriminator2">
- <para>
- <literal>type</literal> (opcional - valor default
<literal>string</literal>)
- o nome que indica o tipo Hibernate
- </para>
- </callout>
- <callout arearefs="discriminator3">
- <para>
- <literal>force</literal> (opcional - valor
default <literal>false</literal>)
- "força" o Hibernate a especificar valores
discriminadores permitidos mesmo
- quando recuperando todas as instancias da classe root.
- </para>
- </callout>
- <callout arearefs="discriminator4">
- <para>
- <literal>insert</literal> (opcional - valor
default para <literal>true</literal>)
- sete isto para <literal>false</literal> se sua
coluna discriminadora é também
- parte do identificador composto mapeado. (Diz ao Hibernate
para não incluir a
- coluna em comandos SQL
<literal>INSERT</literal>s).
- </para>
- </callout>
- <callout arearefs="discriminator5">
- <para>
- <literal>formula</literal> (opcional) uma
expressão SQL arbitraria que é e
- xecutada quando um tipo tem que ser avaliado. Permite
discriminação baseada
- em conteúdo.
- </para>
- </callout>
- </calloutlist>
- </programlistingco>
-
- <para>
- Valores atuais de uma coluna discriminada são especificados pelo atributo
- <literal>discriminator-value</literal> da
<literal><class></literal>
- e elementos da <literal><subclass></literal>.
- </para>
-
- <para>
- O atributo <literal>force</literal> é util (apenas) em
tabelas contendo linhas com
- valores discriminadores "extras" que não estão mapeados para
uma classe persistente.
- Este não é geralmente o caso.
- </para>
-
- <para>
- Usando o atributo <literal>formula</literal> voce pode
declarar uma expressão SQL
- arbitrária que sera utilizada para avaliar o tipo de uma linha :
- </para>
-
- <programlisting><![CDATA[<discriminator
- formula="case when CLASS_TYPE in ('a', 'b', 'c') then 0
else 1 end"
- type="integer"/>]]></programlisting>
-
- </sect2>
-
- <sect2 id="mapping-declaration-version" revision="4">
- <title>version (optional)</title>
-
- <para>
- O elemento <literal><version></literal> é
opcional e indica que a tabela
- possui dados versionados. Isto é particularmente útil se você planeja
utilizar
- <emphasis>transações longas</emphasis> (veja abaixo):
- </para>
-
- <programlistingco>
- <areaspec>
- <area id="version1" coords="2 70"/>
- <area id="version2" coords="3 70"/>
- <area id="version3" coords="4 70"/>
- <area id="version4" coords="5 70"/>
- <area id="version5" coords="6 70"/>
- <area id="version6" coords="7 70"/>
- <area id="version7" coords="8 70"/>
- </areaspec>
- <programlisting><![CDATA[<version
- column="version_column"
- name="propertyName"
- type="typename"
- access="field|property|ClassName"
- unsaved-value="null|negative|undefined"
- generated="never|always"
- insert="true|false"
- node="element-name|@attribute-name|element/(a)attribute|."
-/>]]></programlisting>
- <calloutlist>
- <callout arearefs="version1">
- <para>
- <literal>column</literal> (opcional - default a a
propriedade name): O nome da
- coluna mantendo o numero da versão
- </para>
- </callout>
- <callout arearefs="version2">
- <para>
- <literal>name</literal>: O nome da propriedade da
classe persistente.
- </para>
- </callout>
- <callout arearefs="version3">
- <para>
- <literal>type</literal> (opcional - valor default
para <literal>integer</literal>):
- O tipo do numero da versão
- </para>
- </callout>
- <callout arearefs="version4">
- <para>
- <literal>access</literal> (opcional - valor
default <literal>property</literal>):
- A estratégia Hibernate que deve ser usada para acessar o
valor da propriedade.
- </para>
- </callout>
- <callout arearefs="version5">
- <para>
- <literal>unsaved-value</literal> (opcional –
valor default para <literal>undefined
- </literal>): Um valor para a propriedade versão que
indica que uma instancia é
- uma nova instanciada (unsaved), distinguindo de instancias
desconectadas que foram
- salvas ou carregadas em sessões anteriores.
((<literal>undefined</literal> especifica
- que o valor da propriedade de identificação deve ser
utilizado).
- </para>
- </callout>
- <callout arearefs="version6">
- <para>
- <literal>generated</literal> (optional - defaults
to <literal>never</literal>):
- Specifies that this version property value is actually
generated by the database.
- See the discussion of <xref
linkend="mapping-generated">generated properties</xref>.
- <literal>generated</literal> (opcional - valor
default <literal>never</literal>):
- Especifica que valor para a propriedade versão é na verdade
gerado pelo banco de
- dados. Veja a discussão da Seção
- <xref linkend="mapping-generated">generated
properties</xref>.
- </para>
- </callout>
- <callout arearefs="version7">
- <para>
- <literal>insert</literal> (opcional - valor
default para <literal>true</literal>):
- Especifica se a coluna de versão deve ser incluída no comando
SQL de insert.
- Pode ser configurado como
<literal>false</literal> se a coluna do banco de dados
- está definida com um valor default de
<literal>0</literal>.
- </para>
- </callout>
- </calloutlist>
- </programlistingco>
-
- <para>
- Números de versão podem ser dos tipos Hibernate
<literal>long</literal>,
- <literal>integer</literal>,
<literal>short</literal>, <literal>timestamp</literal> ou
- <literal>calendar</literal>.
- </para>
-
- <para>
- A versão de uma propriedade timestamp nunca deve ser nula para uma
instancia
- desconectada, assim o Hibernate irá identificar qualquer instância com
uma versão
- nula ou timestamp como transiente, não importando qual estratégia para
foi
- especificada para <literal>unsaved-value</literal>.
<emphasis>Declarando uma versão
- nula ou a propriedade timestamp é um caminho fácil para tratar problemas
com
- reconexões transitivas no Hibernate, especialmente úteis para pessoas
utilizando
- identificadores assinaldados ou chaves compostas!</emphasis>
- </para>
- </sect2>
-
- <sect2 id="mapping-declaration-timestamp" revision="4"
>
- <title>timestamp (optional)</title>
-
- <para>
- O elemento opcional
<literal><timestamp></literal> indica que uma tabela contém
- dados timestamped. Isso tem por objetivo dar uma alternativa para
versionamento. Timestamps
- são por natureza uma implementação menos segura do locking otimista.
Entretanto, algumas
- vezes a aplicação pode usar timestamps em outros caminhos.
- </para>
-
- <programlistingco>
- <areaspec>
- <area id="timestamp1" coords="2 70"/>
- <area id="timestamp2" coords="3 70" />
- <area id="timestamp3" coords="4 70" />
- <area id="timestamp4" coords="5 70" />
- <area id="timestamp5" coords="6 70" />
- <area id="timestamp6" coords="7 70" />
- </areaspec>
- <programlisting><![CDATA[<timestamp
- column="timestamp_column"
- name="propertyName"
- access="field|property|ClassName"
- unsaved-value="null|undefined"
- source="vm|db"
- generated="never|always"
- node="element-name|@attribute-name|element/(a)attribute|."
-/>]]></programlisting>
- <calloutlist>
- <callout arearefs="timestamp1">
- <para>
- <literal>column</literal> (opcional - valor
default para a propriedade name):
- O nome da coluna que mantem o timestamp.
- </para>
- </callout>
- <callout arearefs="timestamp2">
- <para>
- <literal>name</literal>: O nome da propriedade no
estilo JavaBeans do
- tipo <literal>Date</literal> ou
<literal>Timestamp</literal> da classe
- persistente Java.
- </para>
- </callout>
- <callout arearefs="timestamp3">
- <para>
- <literal>access</literal> (opcional - valor
default para <literal>property</literal>):
- A estretagia Hibernate que deve ser utilizada para acessar o
valor da propriedade.
- </para>
- </callout>
- <callout arearefs="timestamp4">
- <para>
- <literal>unsaved-value</literal> (opcional -
valor default <literal>null</literal>):
- Uma propriedade para a versão de que indica que uma instância
é uma nova instanciada
- (unsaved), distinguindo-a de instancias desconectadas que
foram salvas ou carregadas
- em sessões previas. (<literal>undefined</literal>
especifica que um valor de
- propriedade de identificação deve ser utilizado)
- </para>
- </callout>
- <callout arearefs="timestamp5">
- <para>
- <literal>source</literal> (opcional - valor
default para <literal>vm</literal>):
- De onde o Hibernate deve recuperar o valor timestamp? Do
banco de dados ou da JVM
- corrente? Timestamps baseados em banco de dados levam a um
overhead porque o
- Hibernate precisa acessar o banco de dados para determinar o
"próximo valor", mas é
- mais seguro para uso em ambientes de "cluster".
Observe também, que nem todos
- <literal>Dialect</literal>s suportam a
recuperação do timestamp corrente do banco
- de dados, enquando outros podem não ser seguros para
utilização em bloqueios
- pela falta de precisão (Oracle 8 por exemplo)
- </para>
- </callout>
- <callout arearefs="timestamp6">
- <para>
- <literal>generated</literal> (opcional - valor
default <literal>never</literal>):
- Especifica que o valor da propriedade timestamp é gerado pelo
banco de dados.
- Veja a discussão <xref
linkend="mapping-generated">generated properties</xref>.
- </para>
- </callout>
- </calloutlist>
- </programlistingco>
-
- <para>
- Observe que <literal><timestamp></literal> é
equivalente a
- <literal><version
type="timestamp"></literal>. E
- <literal><timestamp
source="db"></literal> é equivalente a
- <literal><version
type="dbtimestamp"></literal>.
- </para>
- </sect2>
-
-
- <sect2 id="mapping-declaration-property" revision="4">
- <title>property</title>
-
- <para>
- O elemento <literal><property></literal>
declara uma propriedade
- persistente de uma classe, no estilo JavaBean.
- </para>
-
- <programlistingco>
- <areaspec>
- <area id="property1" coords="2 70"/>
- <area id="property2" coords="3 70"/>
- <area id="property3" coords="4 70"/>
- <areaset id="property4-5" coords="">
- <area id="property4" coords='5 70'/>
- <area id="property5" coords='6 70'/>
- </areaset>
- <area id="property6" coords="7 70"/>
- <area id="property7" coords="8 70"/>
- <area id="property8" coords="9 70"/>
- <area id="property9" coords="10 70"/>
- <area id="property10" coords="11 70"/>
- <area id="property11" coords="12 70"/>
- <area id="property12" coords="13 70"/>
- </areaspec>
- <programlisting><![CDATA[<property
- name="propertyName"
- column="column_name"
- type="typename"
- update="true|false"
- insert="true|false"
- formula="arbitrary SQL expression"
- 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/(a)attribute|."
- index="index_name"
- unique_key="unique_key_id"
- length="L"
- precision="P"
- scale="S"
-/>]]></programlisting>
- <calloutlist>
- <callout arearefs="property1">
- <para>
- <literal>name</literal>: o nome da propriedade,
iniciando com letra minúscula.
- </para>
- </callout>
- <callout arearefs="property2">
- <para>
- <literal>column</literal> (opcional - default
para a propriedade name): o nome
- da coluna mapeada do banco de dados, Isto pode também ser
especificado pelo(s)
- elemento(s)
<literal><column></literal> aninhados.
-
- </para>
- </callout>
- <callout arearefs="property3">
- <para>
- <literal>type</literal> (opcional): um nome que
indica o tipo Hibernate.
- </para>
- </callout>
- <callout arearefs="property4-5">
- <para>
- <literal>update, insert</literal> (opcional -
valor default <literal>true</literal>):
- especifica que as colunas mapeadas devem ser incluidas nas
instruções SQL de
- <literal>UPDATE</literal> e/ou
<literal>INSERT</literal> . Setar ambas para to
- <literal>false</literal> permite uma propridade
"derivada" pura cujo valor é
- inicializado de outra propriedade que mapeie a mesma
coluna(s) ou por uma trigger
- ou outra aplicação.
- </para>
- </callout>
- <callout arearefs="property6">
- <para>
- <literal>formula</literal> (opcional): uma
expressão SQL que definie o valor para
- uma propriedade <emphasis>calculada</emphasis>.
Propriedades calculadas nao tem
- uma coluna de mapeamento para elas.
- </para>
- </callout>
- <callout arearefs="property7">
- <para>
- <literal>access</literal> (opcional – valor
default <literal>property</literal>):
- A estratégia que o Hibernate deve utilizar para acessar o
valor da propriedade
- </para>
- </callout>
- <callout arearefs="property8">
- <para>
- <literal>lazy</literal> (opcional - valor default
para <literal>false</literal>):
- Especifica que esta propriedade deve ser trazida de forma
"lazy" quando a
- instancia da variável é acessada pela primeira vez (requer
instrumentação
- bytecode em tempo de criação).
- </para>
- </callout>
- <callout arearefs="property9">
- <para>
- <literal>unique</literal> (opcional): Habilita a
geração de DDL de uma
- unica constraint para as colunas. Assim, permite que isto
seja o
- alvo de uma <literal>property-ref</literal>.
- </para>
- </callout>
- <callout arearefs="property10">
- <para>
- <literal>not-null</literal> (opcional): Habilita
a geração de DDL de uma
- constraint de nulidade para as colunas.
- </para>
- </callout>
- <callout arearefs="property11">
- <para>
- <literal>optimistic-lock</literal> (opcional -
valor default <literal>true</literal>):
- Especifica se mudanças para esta propriedade requerem ou não
bloqueio otimista.
- Em outras palavras, determina se um incremento de versão deve
ocorrer quando
- esta propriedade está suja.
- </para>
- </callout>
- <callout arearefs="property12">
- <para>
- <literal>generated</literal> (opcional - valor
default <literal>never</literal>):
- Especifica que o valor da propriedade é na verdade gerado
pelo banco de dados.
- Veja a discussão da seção
- <xref linkend="mapping-generated">generated
properties</xref>.
- </para>
- </callout>
- </calloutlist>
- </programlistingco>
-
- <para>
- <emphasis>typename</emphasis> pode ser:
- </para>
-
- <orderedlist spacing="compact">
- <listitem>
- <para>
- The name of a Hibernate basic type (eg. <literal>integer,
string, character,
- date, timestamp, float, binary, serializable, object,
blob</literal>).
- O nome do tipo basico do Hibernate (ex., <literal>integer,
string, character,
- date, timestamp, float, binary, serializable, object,
blob</literal>).
- </para>
- </listitem>
- <listitem>
- <para>
- O nome da classe Java com um tipo básico default (ex.
<literal>int, float,
- char, java.lang.String, java.util.Date, java.lang.Integer,
java.sql.Clob</literal>).
- </para>
- </listitem>
- <listitem>
- <para>
- O nome da classe Java serializable
- </para>
- </listitem>
- <listitem>
- <para>
- O nome da classe de um tipo customizado (ex.
<literal>com.illflow.type.MyCustomType</literal>).
- </para>
- </listitem>
- </orderedlist>
-
- <para>
- Se você não especificar um tipo, o Hibernate ira utilizar reflexão sobre
a
- propriedade nomeada para ter uma idéia do tipo Hibernate correto. O
Hibernate ira
- tentar interpretar o nome da classe retornada, usando as regras 2, 3 e 4
nesta ordem.
- Entretanto, isto não é sempre suficiente Em certos casos, você ainda irá
necessitar
- do atributo <literal>type</literal>. (Por exemplo, para
distinguir entre
- <literal>Hibernate.DATE</literal> ou
<literal>Hibernate.TIMESTAMP</literal>,
- ou para espcificar uma tipo ciustomizado.)
- </para>
-
- <para>
- O atributo <literal>access</literal> permite voce controlar
como o Hibernate irá
- acessar a propriedade em tempo de execução. Por default, o Hibernate irá
chamar os
- métodos get/set da propriedades. Se voce especificar
<literal>access="field"</literal>,
- o Hibernate ira bipassar os metodos get/set, acessnado o campo
diretamente,
- usando reflexão. Voc epode especificar sua própria estratégia para acesso
da
- propriedade criando uma classe que implemente a interface
- <literal>org.hibernate.property.PropertyAccessor</literal>.
- </para>
-
- <para>
- Um recurso especialmente poderoso é o de propriedades derivadas. Estas
propriedades
- são por definição read-only, e o valor da propriedade é calculado em
tempo de execução.
- Você declara este calculo como uma expressão SQL, que traduz para
clausula
- <literal>SELECT</literal> de uma subquery daquery SQL que
carrega a instancia:
- </para>
-
- <programlisting><![CDATA[
-<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
)"/>]]></programlisting>
-
- <para>
- Observe que você pode referenciar as entidades da própria tabela,
- através da não declaração de um alias para uma coluna particular (
- <literal>customerId</literal> no exemplo dado). Observe
tambem que voce pode usar o
- mapeamento de elemento aninhado
<literal><formula></literal>, se você não
- gostar de usar o atributo.
- </para>
-
- </sect2>
-
- <sect2 id="mapping-declaration-manytoone"
revision="5">
- <title>many-to-one</title>
-
- <para>
- Uma associação ordinária para outra classe persistente é declarada usando
o
- elemento <literal>many-to-one</literal>. O modelo relacional
é uma
- associação many-to-one: a uma chave estrangeira de uma tabela
referenciando
- a chave primaria da tabela destino.
- </para>
-
- <programlistingco>
- <areaspec>
- <area id="manytoone1" coords="2 70"/>
- <area id="manytoone2" coords="3 70"/>
- <area id="manytoone3" coords="4 70"/>
- <area id="manytoone4" coords="5 70"/>
- <area id="manytoone5" coords="6 70"/>
- <areaset id="manytoone6-7" coords="">
- <area id="manytoone6" coords='7 70'/>
- <area id="manytoone7" coords='8 70'/>
- </areaset>
- <area id="manytoone8" coords="9 70"/>
- <area id="manytoone9" coords="10 70"/>
- <area id="manytoone10" coords="11 70"/>
- <area id="manytoone11" coords="12 70"/>
- <area id="manytoone12" coords="13 70"/>
- <area id="manytoone13" coords="14 70"/>
- <area id="manytoone14" coords="15 70"/>
- <area id="manytoone15" coords="16 70"/>
- <area id="manytoone16" coords="17 70"/>
- </areaspec>
- <programlisting><![CDATA[<many-to-one
- name="propertyName"
- column="column_name"
- 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"
- formula="arbitrary SQL expression"
- node="element-name|@attribute-name|element/(a)attribute|."
- embed-xml="true|false"
- index="index_name"
- unique_key="unique_key_id"
- foreign-key="foreign_key_name"
-/>]]></programlisting>
- <calloutlist>
- <callout arearefs="manytoone1">
- <para>
- <literal>name</literal>: O nome da propriedade.
- </para>
- </callout>
- <callout arearefs="manytoone2">
- <para>
- <literal>column</literal> (opcional): O nome da
coluna foreign key. Isto
- pode também ser especificado através de elementos aninhados
- <literal><column></literal>.
- </para>
- </callout>
- <callout arearefs="manytoone3">
- <para>
- <literal>class</literal> (opcional – default para
o tipo de propriedade
- determinado pela reflexão). O nome da classe associada.
- </para>
- </callout>
- <callout arearefs="manytoone4">
- <para>
- <literal>cascade</literal> (opcional): Especifica
quais operações dever
- ser em cascata do objeto pai para o objeto associado.
- </para>
- </callout>
- <callout arearefs="manytoone5">
- <para>
- <literal>fetch</literal> (opcional - default para
<literal>select</literal>):
- Escolhe entre recuperação outer-join ou recuperação
seqüencial.
- </para>
- </callout>
- <callout arearefs="manytoone6-7">
- <para>
- <literal>update, insert</literal> (opcional -
valor default <literal>true</literal>):
- especifica que as colunas mapeadas dever ser incluidas em
instruções SQL de
- <literal>UPDATE</literal> e/ou
<literal>INSERT</literal>. Setando ambas para
- <literal>false</literal> você permite uma
associação "derivada" pura cujos valores
- são inicializados de algumas outras propriedades que mapeiam
a mesma coluna ou
- por uma trigger ou outra aplicação.
- </para>
- </callout>
- <callout arearefs="manytoone8">
- <para>
- <literal>property-ref</literal>: (opcional) O
nome da propriedade da classe associada
- que faz a junção desta foreign key. Se não especificada, a
chave primaria da
- classe associada será utilizada.
- </para>
- </callout>
- <callout arearefs="manytoone9">
- <para>
- <literal>access</literal> (opcional - valor
default <literal>property</literal>): A
- estrategia que o Hibernate deve utilizar para acessar o valor
da propriedade.
- </para>
- </callout>
- <callout arearefs="manytoone10">
- <para>
- <literal>unique</literal> (opcional): Habilita a
geração DDL de uma constraint
- unique para a coluna foreign-key. Alem disso, permite ser o
alvo de uma
- <literal>property-ref</literal>. Isso torna a
associação multipla
- efetivamente um para um.
- </para>
- </callout>
- <callout arearefs="manytoone11">
- <para>
- <literal>not-null</literal> (opcional): Habilita
a geração DDL de uma constraint de
- nulidade para as foreign keys.
- </para>
- </callout>
- <callout arearefs="manytoone12">
- <para>
- <literal>optimistic-lock</literal> (opcional -
valor default <literal>true</literal>):
- Especifica se mudanças desta propriedade requerem ou não
travamento otimista.
- Em outras palavras, determina se um incremento de versão deve
ocorrer quando
- esta propriedade está suja.
- </para>
- </callout>
- <callout arearefs="manytoone13">
- <para>
- <literal>lazy</literal>(opcional – valor default
<literal>proxy</literal>):
- Por default, associações de ponto unico são envoltas em um
proxie.
- <literal>lazy="no-proxy"</literal>
especifica que a propriedade deve ser
- trazida de forma tardia quando a instancia da variável é
acessada pela
- primeira vez (requer instrumentação bytecode em tempo de
criação)
- <literal>lazy="false"</literal>
especifica que a associação será
- sempre recuperada fortemente.
- </para>
- </callout>
- <callout arearefs="manytoone14">
- <para>
- <literal>not-found</literal> (opcional - valor
default <literal>exception</literal>):
- Especifica como as foreign keys que referenciam linhas
ausentes serão tratadas:
- <literal>ignore</literal> irá tratar a linha
ausente como ama associaççao de null
- </para>
- </callout>
- <callout arearefs="manytoone15">
- <para>
- <literal>entity-name</literal> (opcional): O nome
da entidade da classe associada.
- </para>
- </callout>
- </calloutlist>
- <callout arearefs="manytoone16">
- <para>
- <literal>formula</literal> (optional): Uma
expressão SQL que define um valor
- para um foreign key
<emphasis>computed</emphasis>.
- </para>
- </callout>
- </programlistingco>
-
- <para>
- Setar o valor do atributo <literal>cascade</literal> para
qualquer valor
- significativo diferente de <literal>none</literal> irá
propagar certas operações
- ao objeto associado. Os valores significativos são os nomes das operações
básicas
- do Hibernate, <literal>persist, merge, delete, save-update, evict,
replicate, lock,
- refresh</literal>, assim como os valores especiais
<literal>delete-orphan</literal>
- e <literal>all</literal> e combinações de nomes de operações
separadas por vírgula,
- como por exemplo,
<literal>cascade="persist,merge,evict"</literal> ou
- <literal>cascade="all,delete-orphan"</literal>.
Veja a seção
- <xref linkend="objectstate-transitive"/> para uma
explicação completa. Note que
- associações valoradas simples (associações muitos-pra-um, e um-pra-um)
não suportam
- orphan delete.
- </para>
-
- <para>
- Uma típica declaração <literal>muitos-pra-um</literal> se
parece com esta:
- </para>
-
- <programlisting><![CDATA[<many-to-one name="product"
class="Product" column="PRODUCT_ID"/>]]></programlisting>
-
- <para>
- O atributo <literal>property-ref</literal> deve apenas ser
usado para mapear dados
- legados onde uma chave estrangeira se referencia a uma chave exclusiva da
tabela
- associada que não seja à chave primária. Este é um modelo relacional
desagradável.
- Por exemplo, suponha que a classe <literal>Product</literal>
tenha um número
- seqüencial exclusivo, que não é a chave primária. (O atributo
<literal>unique</literal>
- controla a geração de DDL do Hibernate com a ferramenta SchemaExport.)
- </para>
-
- <programlisting><![CDATA[<property name="serialNumber"
unique="true" type="string"
column="SERIAL_NUMBER"/>]]></programlisting>
-
- <para>
- Então o mapeamento para <literal>OrderItem</literal> poderia
usar:
- </para>
-
- <programlisting><![CDATA[<many-to-one name="product"
property-ref="serialNumber"
column="PRODUCT_SERIAL_NUMBER"/>]]></programlisting>
-
- <para>
- Porém, isto obviamente não é indicado, nunca.
- </para>
-
- <para>
- Se a chave exclusiva referenciada engloba múltiplas propriedades da
entidade associada,
- você deve mapear as propriedades referenciadas dentro de um elemento
chamado
- <literal><properties></literal>
-
- </para>
-
- <para>
- Se a chave exclusiva referenciada é a propriedade de um componente, você
pode especificar
- um caminho para a propriedade.
- </para>
-
- <programlisting><![CDATA[<many-to-one name="owner"
property-ref="identity.ssn"
column="OWNER_SSN"/>]]></programlisting>
-
- </sect2>
-
- <sect2 id="mapping-declaration-onetoone" revision="3">
- <title>one-to-one (um-pra-um)</title>
-
- <para>
- Uma associação um-pra-um para outra classe persistente é declarada usando
- um elemento <literal>one-to-one </literal>.
- </para>
-
- <programlistingco>
- <areaspec>
- <area id="onetoone1" coords="2 70"/>
- <area id="onetoone2" coords="3 70"/>
- <area id="onetoone3" coords="4 70"/>
- <area id="onetoone4" coords="5 70"/>
- <area id="onetoone5" coords="6 70"/>
- <area id="onetoone6" coords="7 70"/>
- <area id="onetoone7" coords="8 70"/>
- <area id="onetoone8" coords="9 70"/>
- <area id="onetoone9" coords="10 70"/>
- <area id="onetoone10" coords="11 70"/>
- </areaspec>
- <programlisting><![CDATA[<one-to-one
- name="propertyName"
- class="ClassName"
- cascade="cascade_style"
- constrained="true|false"
- fetch="join|select"
- property-ref="propertyNameFromAssociatedClass"
- access="field|property|ClassName"
- formula="any SQL expression"
- lazy="proxy|no-proxy|false"
- entity-name="EntityName"
- node="element-name|@attribute-name|element/(a)attribute|."
- embed-xml="true|false"
- foreign-key="foreign_key_name"
-/>]]></programlisting>
- <calloutlist>
- <callout arearefs="onetoone1">
- <para>
- <literal>name</literal>: O nome da propriedade.
- </para>
- </callout>
- <callout arearefs="onetoone2">
- <para>
- <literal>class</literal> (opcional – default para
o tipo da propriedade
- definido via reflection): O nome da classe associada.
- </para>
- </callout>
- <callout arearefs="onetoone3">
- <para>
- <literal>cascade</literal> (opcional): Especifica
qual operação deve
- ser cascateada do objeto pai para o objeto associado.
- </para>
- </callout>
- <callout arearefs="onetoone4">
- <para>
- <literal>constrained</literal> (opcional):
Especifica que uma chave estrangeira
- constraint na chave primária da tabela mapeada referencia a
tabela da classe
- associada, Esta opção afeta a ordem em queh
<literal>save()</literal> e
- <literal>delete()</literal> são cascateadas, e
determina se a associação
- pode ser substituída (isto também é usado pela ferramenta
schema export).
- </para>
- </callout>
- <callout arearefs="onetoone5">
- <para>
- <literal>fetch</literal> ((opcional – valor
default <literal>select</literal>):
- Escolhe entre outer-join fetching ou sequential select
fetching.
- </para>
- </callout>
- <callout arearefs="onetoone6">
- <para>
- <literal>property-ref</literal>(opcional): O nome
da propriedade da classe associada
- que é ligada a chave primária desta classe. Se não for
especificada, a chave primária
- da classe associada é utilizada.
- </para>
- </callout>
- <callout arearefs="onetoone7">
- <para>
- <literal>access</literal> (opcional - valor
default padrão <literal>property</literal>):
- A estratégia que o Hibernate pode usar para acessar o valor
da propriedade.
- </para>
- </callout>
- <callout arearefs="onetoone8">
- <para>
- <literal>formula</literal> (opcional): Quase
todas associações um-pra-um mapeiam
- para a chave primária da entidade dona. No caso raro, que não
é o caso, você
- pode especificar uma outra coluna, colunas ou expressões para
juntar utilizando
- uma formula SQL. (Veja
<literal>org.hibernate.test.onetooneformula</literal>
- para exemplo).
- </para>
- </callout>
- <callout arearefs="onetoone9">
- <para>
- <literal>lazy</literal> (opcional – valor default
<literal>proxy</literal>):
- Por default, associações single point são proxied.
<literal>lazy="no-proxy"</literal>
- especifica que a propriedade deve ser fetched lazily quando o
atributo é acessado
- pela primeira vez (requer build-time bytecode
instrumentation).
- <literal>lazy="false"</literal>
especifica que a associação vai sempre ser
- avidamente fetched. <emphasis>Note que se
<literal>constrained="false"</literal>,
- proxing é impossível e o Hibernate vai ávido fetch a
associação!</emphasis>
- </para>
- </callout>
- <callout arearefs="onetoone10">
- <para>
- <literal>entity-name</literal> (opcional): O nome
da entidade da classe associada.
- </para>
- </callout>
- </calloutlist>
- </programlistingco>
-
- <para>
- Existem duas variedades de associações um-pra-um:
- </para>
- <itemizedlist>
- <listitem><para>
- associações de chave primária
- </para></listitem>
- <listitem><para>
- associações de chave estrangeira exclusiva
- </para></listitem>
- </itemizedlist>
-
- <para>
- Associações de chave primária não necessitam de uma coluna extra de
tabela; se duas
- linhas são relacionadas pela associação então as duas linhas da tabela
dividem a mesmo
- valor da chave primária. Assim, se você quer que dois objetos sejam
relacionados por
- uma associação de chave primária, você deve ter certeza que eles são
assinados com o
- mesmo valor identificador!
- </para>
-
- <para>
- Para uma associação de chave primária, adicione os seguintes mapeamentos
em
- <literal>Employee</literal> e
<literal>Person</literal>, respectivamente.
- </para>
-
- <programlisting><![CDATA[<one-to-one name="person"
class="Person"/>]]></programlisting>
- <programlisting><![CDATA[<one-to-one name="employee"
class="Employee" constrained="true"/>]]></programlisting>
-
- <para>
- Agora nós devemos assegurar que as chaves primárias de linhas
relacionadas nas
- tabelas PERSON e EMPLOYEE são iguais. Nós usamos uma estratégia especial
de geração
- de identificador do Hibernate chamada
<literal>foreign</literal>:
- </para>
-
- <programlisting><![CDATA[<class name="person"
table="PERSON">
- <id name="id" column="PERSON_ID">
- <generator class="foreign">
- <param name="property">employee</param>
- </generator>
- </id>
- ...
- <one-to-one name="employee"
- class="Employee"
- constrained="true"/>
-</class>]]></programlisting>
-
- <para>
- Uma nova instância de <literal>Person</literal> salva
recentemente é então assinada
- com o mesmo valor da chave primária da instância de
<literal>employee</literal> referenciada
- com a propriedade <literal>employee</literal> daquela
<literal>Person</literal>.
- </para>
-
- <para>
- Alternativamente, uma chave estrangeira com uma unique constraint, de
- <literal>Employee</literal> para
<literal>Person</literal>, pode ser expressa como:
- </para>
-
- <programlisting><![CDATA[<many-to-one name="person"
class="Person" column="PERSON_ID"
unique="true"/>]]></programlisting>
-
- <para>
- E esta associação pode ser feita de forma bi-direcional adicionando o
seguinte
- no mapeamento de <literal>Person</literal>:
- </para>
-
- <programlisting><![CDATA[<one-to-one name="employee"
class="Employee"
property-ref="person"/>]]></programlisting>
-
- </sect2>
-
- <sect2 id="mapping-declaration-naturalid">
- <title>natural-id</title>
-
- <programlisting><![CDATA[<natural-id
mutable="true|false"/>
- <property ... />
- <many-to-one ... />
- ......
-</natural-id>]]></programlisting>
-
- <para>
- Embora nós recomendemos o uso de surrogate keys como chaves primárias,
você deve
- ainda identificar chaves naturais para todas as entidades. Uma chave
natural é
- uma propriedade ou combinação de propriedades que é exclusiva e não nula.
Se não
- pude ser modificada, melhor ainda. Mapeie as propriedades da chave
natural dentro do
- elemento <literal><natural-id></literal>. O
Hibernate irá gerar a chave
- exclusiva necessária e as constraints de nullability , e seu mapeamento
será
- apropriadamente auto documentado.
- </para>
-
- <para>
- Nós recomendamos com enfase que você implemente
<literal>equals()</literal> e
- <literal>hashCode()</literal> para comparar as propriedades
da chave natural da
- entidade.
- </para>
-
- <para>
- Este mapeamento não tem o objetivo de uso com entidades com natural
chaves primárias.
- </para>
-
- <itemizedlist spacing="compact">
- <listitem>
- <para>
- <literal>mutable</literal> mutable (opcional, valor
default<literal>false</literal>):
- Por default, propriedades naturais identificadoras são
consideradas imutáveis (constante).
- </para>
- </listitem>
- </itemizedlist>
-
- </sect2>
-
- <sect2 id="mapping-declaration-component"
revision="2">
- <title>componente, componente dinâmico</title>
-
- <para>
- O elemento<literal><component></literal> mapeia
propriedades de um
- objeto filho para colunas da tabela de uma classe pai. Componentes podem,
- um após o outro, declarar suas próprias propriedades, componentes ou
coleções.
- Veja "Components" abaixo.
- </para>
-
- <programlistingco>
- <areaspec>
- <area id="component1" coords="2 45"/>
- <area id="component2" coords="3 45"/>
- <area id="component3" coords="4 45"/>
- <area id="component4" coords="5 45"/>
- <area id="component5" coords="6 45"/>
- <area id="component6" coords="7 45"/>
- <area id="component7" coords="8 45"/>
- <area id="component8" coords="9 45"/>
- </areaspec>
- <programlisting><![CDATA[<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>]]></programlisting>
- <calloutlist>
- <callout arearefs="component1">
- <para>
- <literal>name</literal>: O nome da propriedade.
- </para>
- </callout>
- <callout arearefs="component2">
- <para>
- <literal>class</literal> (opcional – valor
default para o tipo de
- propriedade determinada por reflection): O nome da classe
(filha) do
- componente.
- </para>
- </callout>
- <callout arearefs="component3">
- <para>
- <literal>insert</literal>: As colunas mapeadas
aparecem nos
- SQL de <literal>INSERT</literal>s?
- </para>
- </callout>
- <callout arearefs="component4">
- <para>
- <literal>update</literal>: As colunas mapeadas
aparecem nos
- SQL de <literal>UPDATE</literal>s?
- </para>
- </callout>
- <callout arearefs="component5">
- <para>
- <literal>access</literal> (opcional – valor
default <literal>property</literal>):
- A estratégia que o Hibernate pode usar para acessar o valor
da propriedade.
- </para>
- </callout>
- <callout arearefs="component6">
- <para>
- <literal>lazy</literal> (opcional - valor default
<literal>false</literal>):
- Especifica que este componente deve ser fetched lazily quando
o atributo for
- acessado pela primeira vez (requer build-time bytecode
instrumentation).
- </para>
- </callout>
- <callout arearefs="component7">
- <para>
- <literal>optimistic-lock</literal> (opcional
– valor default <literal>true</literal>):
- Especifica que atualizações para este componente requerem
ou não aquisição
- de um lock otimista. Em outras palavras, determina se uma
versão de incremento deve
- ocorrer quando esta propriedade estiver modificada.
- </para>
- </callout>
- <callout arearefs="component8">
- <para>
- <literal>unique</literal> (opcional – valor
default <literal>false</literal>):
- Especifica que existe uma unique constraint em todas as
colunas mapeadas do
- componente.
- </para>
- </callout>
- </calloutlist>
- </programlistingco>
-
- <para>
- A tag filha <literal><property></literal>
acrescenta a propriedade
- de mapeamento da classe filha para colunas de uma tabela.
- </para>
-
- <para>
- O elemento <literal><component></literal>
permite um sub-elemento
- <literal><parent></literal> mapeie uma
propriedade da classe do componente
- como uma referencia de volta para a entidade que o contém.
- </para>
-
- <para>
- O elemento
<literal><dynamic-component></literal> permite que um
- <literal>Map</literal> possa ser mapeado como um componente
onde os nomes das
- propriedades referem-se para as chaves no mapa, veja
- <xref linkend="components-dynamic"/>.
- </para>
-
- </sect2>
-
- <sect2 id="mapping-declaration-properties"
revision="2">
- <title>propriedades</title>
-
- <para>
- O elemento <literal><properties></literal>
permite a definição de um grupo
- com nome, lógico de propriedades de uma classe. O uso mais importante do
construtor
- é que este permite uma combinação de propriedades para ser o objetivo de
uma
- <literal>property-ref</literal>. É também um modo
conveninente para definir uma
- unique constraint de múltiplas colunas.
- </para>
-
- <programlistingco>
- <areaspec>
- <area id="properties1" coords="2 45"/>
- <area id="properties2" coords="3 45"/>
- <area id="properties3" coords="4 45"/>
- <area id="properties4" coords="5 45"/>
- <area id="properties5" coords="6 45"/>
- </areaspec>
- <programlisting><![CDATA[<properties
- name="logicalName"
- insert="true|false"
- update="true|false"
- optimistic-lock="true|false"
- unique="true|false"
->
-
- <property ...../>
- <many-to-one .... />
- ........
-</properties>]]></programlisting>
- <calloutlist>
- <callout arearefs="properties1">
- <para>
- <literal>name</literal>:: O nome lógico do
agrupamento –
- <emphasis>não </emphasis> é o nome atual de
propriedade.
- </para>
- </callout>
- <callout arearefs="properties2">
- <para>
- <literal>insert</literal>: As colunas mapeadas
aparecem nos
- SQL de <literal>INSERT</literal>s?
- </para>
- </callout>
- <callout arearefs="properties3">
- <para>
- <literal>update</literal>: As colunas mapeadas
aparecem nos
- SQL de <literal>UPDATE</literal>s?
- </para>
- </callout>
- <callout arearefs="properties4">
- <para>
- <literal>optimistic-lock</literal> (opcional
– valor default <literal>true</literal>):
- Especifica que atualizações para estes componentes
requerem ou não aquisição de um
- lock otimista. Em outras palavras, determina se uma
versão de incremento deve ocorrer
- quando estas propriedades estiverem modificadas.
- </para>
- </callout>
- <callout arearefs="properties5">
- <para>
- <literal>unique</literal> (opcional – valor
defautl <literal>false</literal>):
- Especifica que uma unique constraint existe em todas as
colunas mapeadas do componente.
- </para>
- </callout>
- </calloutlist>
- </programlistingco>
-
- <para>
- Por exemplo, se nós temos o seguinte mapeamento de
<literal><properties></literal>:
- </para>
-
- <programlisting><![CDATA[<class name="Person">
- <id name="personNumber"/>
- ...
- <properties name="name"
- unique="true" update="false">
- <property name="firstName"/>
- <property name="initial"/>
- <property name="lastName"/>
- </properties>
-</class>]]></programlisting>
-
- <para>
- Então nós podemos ter uma associação de dados herdados que referem a
esta chave
- exclusiva da tabela <literal>Person</literal>, ao invés de se
referirem a chave
- primária:
- </para>
-
- <programlisting><![CDATA[<many-to-one name="person"
- class="Person" property-ref="name">
- <column name="firstName"/>
- <column name="initial"/>
- <column name="lastName"/>
-</many-to-one>]]></programlisting>
-
- <para>
- Nós não recomendamos o uso deste tipo de coisa fora do contexto de
mapeamento de
- dados herdados.
- </para>
-
- </sect2>
-
- <sect2 id="mapping-declaration-subclass" revision="4">
- <title>subclass (subclasse)</title>
-
- <para>
- Finalmente, a persistência polimórfica requer a declaração de cada
subclasse
- da classe de persistência raiz. Para a estratégia de mapeamento
- table-per-class-hierarchy, a declaração
<literal><subclass></literal>
- deve ser usada.
- </para>
-
- <programlistingco>
- <areaspec>
- <area id="subclass1" coords="2 55"/>
- <area id="subclass2" coords="3 55"/>
- <area id="subclass3" coords="4 55"/>
- <area id="subclass4" coords="5 55"/>
- </areaspec>
- <programlisting><![CDATA[<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">
-
- <property .... />
- .....
-</subclass>]]></programlisting>
- <calloutlist>
- <callout arearefs="subclass1">
- <para>
- <literal>name</literal>: O nome de classe
completamente qualificada da subclasse.
- </para>
- </callout>
- <callout arearefs="subclass2">
- <para>
- <literal>discriminator-value</literal> (opcional
– valor default o nome da classe):
- Um valor que distingue subclasses individuais.
- </para>
- </callout>
- <callout arearefs="subclass3">
- <para>
- <literal>proxy</literal> (opcional): Especifica a
classe ou interface que
- usará os proxies de inicialização atrasada.
- </para>
- </callout>
- <callout arearefs="subclass4">
- <para>
- <literal>lazy</literal> (opcional, valor default
<literal>true</literal>):
- Configurar
<literal>lazy="false"</literal> desabilitará o uso de
- inicialização atrasada.
- </para>
- </callout>
- </calloutlist>
- </programlistingco>
- <para>
- Cada subclasse deve declarar suas próprias propriedades persistentes e
subclasses.
- As propriedades <literal><version></literal> e
<literal><id></literal>
- são configuradas para serem herdades da classe raiz. Cada subclasse numa
hierarquia
- deve definir um único <literal>discriminator-value</literal>.
Se nenhum for
- especificado, o nome da classe Java completamente qualificada será
usada.
- </para>
-
- <para>
- Para informações sobre mapeamento de heranças, veja o <xref
linkend="inheritance"/>.
- </para>
-
- </sect2>
-
- <sect2 id="mapping-declaration-joinedsubclass"
revision="3">
- <title>joined-subclass</title>
-
- <para>
- Alternativamente, cada subclasse pode ser mapeada para sua própria tabela
- (Estratégia de mapeamento table-per-subclass). O estado herdado é
devolvido
- por associação com a tabela da superclasse. Nós usamos o elemento
- <literal><joined-subclass></literal>.
- </para>
-
- <programlistingco>
- <areaspec>
- <area id="joinedsubclass1" coords="2 45"/>
- <area id="joinedsubclass2" coords="3 45"/>
- <area id="joinedsubclass3" coords="4 45"/>
- <area id="joinedsubclass4" coords="5 45"/>
- </areaspec>
- <programlisting><![CDATA[<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">
-
- <key .... >
-
- <property .... />
- .....
-</joined-subclass>]]></programlisting>
- <calloutlist>
- <callout arearefs="joinedsubclass1">
- <para>
- <literal>name</literal>: O nome da classe
completamente qualificada da
- subclasse.
- </para>
- </callout>
- <callout arearefs="joinedsubclass2">
- <para>
- <literal>table</literal>: O nome da tabela da
subclasse.
- </para>
- </callout>
- <callout arearefs="joinedsubclass3">
- <para>
- <literal>proxy</literal> (opcional): Especifica a
classe ou interface
- para usar os proxies de recuperação atrasada.
- </para>
- </callout>
- <callout arearefs="joinedsubclass4">
- <para>
- <literal>lazy</literal> (opcional, valor default
<literal>true</literal>):
- Fixanr <literal>lazy="false"</literal>
desabilita o uso recuperação
- atrasada.
- </para>
- </callout>
- </calloutlist>
- </programlistingco>
-
- <para>
- A coluna discriminator requerida para esta estratégia de mapeamento.
Porém,
- cada subclasse deve declarar uma coluna de tabela com o identificador do
objeto
- usando o elemento <literal><key></literal>. O
mapeamento no início do
- capítulo poderia ser re-escrito assim:
- </para>
-
- <programlisting><![CDATA[<?xml version="1.0"?>
-<!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
-
-<hibernate-mapping package="eg">
-
- <class name="Cat" table="CATS">
- <id name="id" column="uid"
type="long">
- <generator class="hilo"/>
- </id>
- <property name="birthdate" type="date"/>
- <property name="color" not-null="true"/>
- <property name="sex" not-null="true"/>
- <property name="weight"/>
- <many-to-one name="mate"/>
- <set name="kittens">
- <key column="MOTHER"/>
- <one-to-many class="Cat"/>
- </set>
- <joined-subclass name="DomesticCat"
table="DOMESTIC_CATS">
- <key column="CAT"/>
- <property name="name" type="string"/>
- </joined-subclass>
- </class>
-
- <class name="eg.Dog">
- <!-- mapping for Dog could go here -->
- </class>
-
-</hibernate-mapping>]]></programlisting>
-
- <para>
- Para informações de mapeamentos de herança, veja <xref
linkend="inheritance"/>.
- </para>
-
- </sect2>
-
- <sect2 id="mapping-declaration-unionsubclass"
revision="2">
- <title>union-subclass</title>
-
- <para>
- Uma terceira opção é mapear para tabelas apenas as classes concretas de
uma
- hierarquia de heranças, (a estratégia table-per-concrete-class) onde cada
tabela
- define todos os estados persistentes da classe, incluindo estados
herdados.
- No Hibernate, não é absolutamente necessário mapear explicitamente como
hierarquia
- de heranças. Você pode simplesmente mapear cada classe com uma declaração
- <literal><class></literal> separada. Porém, se
você deseja usar associações
- polimórficas (por exemplo: uma associação para a superclasse de sua
hierarquia),
- você precisa usar o mapeamento
<literal><union-subclass></literal>.
-
- </para>
-
- <programlistingco>
- <areaspec>
- <area id="unionsubclass1" coords="2 45"/>
- <area id="unionsubclass2" coords="3 45"/>
- <area id="unionsubclass3" coords="4 45"/>
- <area id="unionsubclass4" coords="5 45"/>
- </areaspec>
- <programlisting><![CDATA[<union-subclass
- name="ClassName"
- table="tablename"
- proxy="ProxyInterface"
- lazy="true|false"
- dynamic-update="true|false"
- dynamic-insert="true|false"
- schema="schema"
- catalog="catalog"
- extends="SuperclassName"
- abstract="true|false"
- persister="ClassName"
- subselect="SQL expression"
- entity-name="EntityName"
- node="element-name">
-
- <property .... />
- .....
-</union-subclass>]]></programlisting>
- <calloutlist>
- <callout arearefs="unionsubclass1">
- <para>
- <literal>name</literal>: O nome da subclasse
completamente qualificada.
- </para>
- </callout>
- <callout arearefs="unionsubclass2">
- <para>
- <literal>table</literal>: O nome da tabela da
subclasse.
- </para>
- </callout>
- <callout arearefs="unionsubclass3">
- <para>
- <literal>proxy</literal> (optional): Specifies a
class or interface to use
- for lazy initializing proxies.
-
- <literal>proxy</literal> (opcional): Especifica a
classe ou interface para usar
- os proxies de recuperação atrasada.
- </para>
- </callout>
- <callout arearefs="unionsubclass4">
- <para>
- <literal>lazy</literal> (optional, defaults to
<literal>true</literal>): Setting
- <literal>lazy="false"</literal>
disables the use of lazy fetching.
- <literal>lazy</literal> (opcional, valor default
p<literal>true</literal>):
- Fixando <literal>lazy="false"</literal>
desabilita o uso da recuperação atrasada.
- </para>
- </callout>
- </calloutlist>
- </programlistingco>
-
- <para>
- A coluna discriminatõria não é requerida para esta estratégia de
mapeamento.
-
- </para>
-
- <para>
- Para informações sobre mapeamentos de herança, veja <xref
linkend="inheritance"/>.
- </para>
-
- </sect2>
-
- <sect2 id="mapping-declaration-join" revision="3">
- <title>join</title>
-
- <para>
- Usando o elemento
<literal><join></literal>>, é possível mapear
- propriedades de uma classe para várias tabelas.
- </para>
-
- <programlistingco>
- <areaspec>
- <area id="join1" coords="2 50"/>
- <area id="join2" coords="3 50"/>
- <area id="join3" coords="4 50"/>
- <area id="join4" coords="5 50"/>
- <area id="join5" coords="6 50"/>
- <area id="join6" coords="7 50"/>
- </areaspec>
- <programlisting><![CDATA[<join
- table="tablename"
- schema="owner"
- catalog="catalog"
- fetch="join|select"
- inverse="true|false"
- optional="true|false">
-
- <key ... />
-
- <property ... />
- ...
-</join>]]></programlisting>
-
- <calloutlist>
- <callout arearefs="join1">
- <para>
- <literal>table</literal>: O nome da tabela
associada.
- </para>
- </callout>
- <callout arearefs="join2">
- <para>
- <literal>schema</literal> (opcional): Sobrepõe o
nome do esquema
- especificado pelo elemento raiz
<literal><hibernate-mapping></literal>.
- </para>
- </callout>
- <callout arearefs="join3">
- <para>
- <literal>catalog</literal> (opcional): Sobrepõe o
nome do catálogo
- especificado pelo elemento
raiz<literal><hibernate-mapping></literal>.
- </para>
- </callout>
- <callout arearefs="join4">
- <para>
- <literal>fetch</literal>(opcional – valor default
<literal>join</literal>): Se setado
- para <literal>join</literal>, o padrão, o
Hibernate irá usar um inner join para
- restaurar um <literal>join</literal> definido por
uma classe ou suas subclasses e
- uma outer join para um <literal>join</literal>
definido por uma subclasse.
- Se setado para <literal>select</literal>, então o
Hibernate irá usar uma seleção
- seqüencial para um
<literal><join></literal> definida numa subclasse, que irá
- ser emitido apenas se uma linha se concentrar para
representar uma instância
- da subclasse. Inner joins irá ainda ser usado para restaurar
um
- <literal><join></literal> definido
pela classe e suas superclasses.
- </para>
- </callout>
- <callout arearefs="join5">
- <para>
- <literal>inverse</literal> (opcional – valor
default <literal>false</literal>):
- Se habilitado, o Hibernate não irá tentar inserir ou
atualizar as propriedades
- definidas por este join.
- </para>
- </callout>
- <callout arearefs="join6">
- <para>
- <literal>optional</literal> (opcional – valor
default <literal>false</literal>):
- Se habilitado, o Hibernate irá inserir uma linha apenas se as
propriedades definidas
- por esta junção não forem nulas e irá sempre usar uma outer
join para
- recuperar as propriedades.
- </para>
- </callout>
- </calloutlist>
- </programlistingco>
-
- <para>
- Por exemplo, a informação de endereço para uma pessoa pode ser mapeada
para uma
- tabela separada (enquanto preservando o valor da semântica de tipos para
- todas as propriedades):
- </para>
-
- <programlisting><![CDATA[<class name="Person"
- table="PERSON">
-
- <id name="id" column="PERSON_ID">...</id>
-
- <join table="ADDRESS">
- <key column="ADDRESS_ID"/>
- <property name="address"/>
- <property name="zip"/>
- <property name="country"/>
- </join>
- ...]]></programlisting>
-
- <para>
- Esta característica é útil apenas para modelos de dados legados, nós
recomendamos
- menos tabelas do que classes e um modelo de domínio bem granulado. Porém,
é
- útil para ficar trocando entre estratégias de mapeamento de herança
- numa hierarquia simples, como explicado mais a frente.
- </para>
-
- </sect2>
-
- <sect2 id="mapping-declaration-key">
- <title>key</title>
-
- <para>
- Nós vimos que o elemento
<literal><key></literal> surgiu algumas vezes
- até agora. Ele aparece em qualquer lugar que o elemento pai define uma
junção
- para a nova tabela, e define a chave estrangeira para a tabela associada,
que
- referencia a chave primária da tabela original.
- </para>
-
- <programlistingco>
- <areaspec>
- <area id="key1" coords="2 50"/>
- <area id="key2" coords="3 50"/>
- <area id="key3" coords="4 50"/>
- <area id="key4" coords="5 50"/>
- <area id="key5" coords="6 50"/>
- <area id="key6" coords="7 50"/>
- </areaspec>
- <programlisting><![CDATA[<key
- column="columnname"
- on-delete="noaction|cascade"
- property-ref="propertyName"
- not-null="true|false"
- update="true|false"
- unique="true|false"
-/>]]></programlisting>
-
- <calloutlist>
- <callout arearefs="key1">
- <para>.
- <literal>column</literal> (opcional): O nome da
coluna da chave estrangeira.
- Isto também pode ser especificado por aninhamento de
elemento(s)
- <literal><column></literal>.
- </para>
- </callout>
- <callout arearefs="key2">
- <para>
- <literal>on-delete</literal> (opcional, valor
default <literal>noaction</literal>):
- Especifica se a constraint da chave estrangeira no banco de
dados esta
- habilitada para cascade delete .
- </para>
- </callout>
- <callout arearefs="key3">
- <para>
- <literal>property-ref</literal> (opcional):
Especifica que a chave estrangeira
- se refere a colunas que não são chave primária da tabela
original.
- (Util para base de dados legadas.)
- </para>
- </callout>
- <callout arearefs="key4">
- <para>
- <literal>not-null</literal> (opcional):
Especifica que a coluna da chave
- estrangeira não aceita valores nulos (isto é implícito em
qualquer momento
- que a chave estrangeira também fizer parte da chave
primária).
- </para>
- </callout>
- <callout arearefs="key5">
- <para>
- <literal>update</literal> (optional): Specifies
that the foreign key should never
- be updated (this is implied whenever the foreign key is also
part of the primary
- key).
- <literal>update</literal> (opcional): Especifica
que a chave estrangeira nunca
- deve ser atualizada (isto é implícito em qualquer momento que
a chave estrangeira
- também fizer parte da chave primária).
- </para>
- </callout>
- <callout arearefs="key6">
- <para>
- <literal>unique</literal> (opcional): Especifica
que a chave estrangeira deve ter
- uma constraint unique (sto é implícito em qualquer momento
que a chave estrangeira
- também fizer parte da chave primária).
- </para>
- </callout>
- </calloutlist>
- </programlistingco>
-
- <para>
- Nós recomendamos que para sistemas que a performance de delete seja
importante, todas as
- chaves deve ser definida
<literal>on-delete="cascade"</literal>, e o Hibernate irá usar
- uma constraint a nível de banco de dados <literal>ON CASCADE
DELETE</literal>, ao invés
- de muitas instruções <literal>DELETE</literal>. Esteja ciente
que esta característica é
- um atalho da estratégia usual de optimistic locking do Hibernate para
dados versionados.
- </para>
-
- <para>
- Os atributos <literal>not-null</literal> e
<literal>update</literal> são úteis quando
- estamos mapeamos uma associação unidirecional um para muitos. Se você
mapear uma
- asociação unidirecional um para muitos para uma chave estrangeira
non-nullable, você
- <emphasis>deve</emphasis> declarar a coluna chave usando
- <literal><key
not-null="true"></literal>.
- </para>
-
- </sect2>
-
- <sect2 id="mapping-column" revision="4">
- <title>elementos column e formula</title>
- <para>
- Qualquer elemento de mapeamente que aceita um atributo
<literal>column</literal> irá
- aceitar alternativamente um subelemento
<literal><column></literal>. Da mesma forma,
- <literal>formula</literal> é uma alternativa para o atributo
<literal>formula</literal>.
- </para>
-
- <programlisting><![CDATA[<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"/>]]></programlisting>
-
- <programlisting><![CDATA[<formula>SQL
expression</formula>]]></programlisting>
-
- <para>
- O atributo <literal>column</literal> e
<literal>formula</literal> podem até ser combinados
- dentro da mesma propriedade ou associação mapeando para expressar,
- por exemplo, associações exóticas.
- </para>
-
- <programlisting><![CDATA[<many-to-one
name="homeAddress" class="Address"
- insert="false" update="false">
- <column name="person_id" not-null="true"
length="10"/>
- <formula>'MAILING'</formula>
-</many-to-one>]]></programlisting>
-
- </sect2>
-
- <sect2 id="mapping-declaration-import">
- <title>import</title>
-
- <para>
- Suponha que a sua aplicação tem duas classes persistentes com o mesmo
nome, e você não quer
- especificar o nome qualificado (do pacote) nas queries do Hibernate. As
Classes devem
- ser "importadas" explicitamente, de preferência contando com
<literal>auto-import="true"</literal>.
- Você pode até importar classes e interfaces que não estão explicitamente
mapeadas.
- </para>
-
- <programlisting><![CDATA[<import
class="java.lang.Object"
rename="Universe"/>]]></programlisting>
-
- <programlistingco>
- <areaspec>
- <area id="import1" coords="2 40"/>
- <area id="import2" coords="3 40"/>
- </areaspec>
- <programlisting><![CDATA[<import
- class="ClassName"
- rename="ShortName"
-/>]]></programlisting>
- <calloutlist>
- <callout arearefs="import1">
- <para>
- <literal>class</literal>: O nome qualificado (do
pacote) de qualquer classe Java.
- </para>
- </callout>
- <callout arearefs="import2">
- <para>
- <literal>rename</literal> (opcional – valor
default, o nome da classe não
- qualificada): Um nome que pode ser usado numa linguagem de
consulta.
- </para>
- </callout>
- </calloutlist>
- </programlistingco>
-
- </sect2>
-
- <sect2 id="mapping-types-anymapping" revision="2">
- <title>any</title>
-
- <para>
- Existe mais um tipo de propriedade de mapeamento. O elemento de
mapeamento
- <literal><any></literal> define uma associação
polimórfica para classes de múltiplas tabelas.
- Este tipo de mapeamento sempre requer mais de uma coluna. A primeira
coluna possui o tipo da entidade
- associada. A outra coluna que ficou possui o identificador. É impossível
especificar uma restrição
- de chave estrangeira para este tipo de associação, assim isto claramente
não é visto
- como um caminho usual para associações (polimórficas) de mapeamento. Você
deve usar este mapeamento
- apenas em casos muito especiais (exemplo: audit logs, dados de sessão do
usuário, etc).
-
- </para>
-
- <para>
- O atributo <literal>meta-type</literal> permite a aplicação
especificar um tipo adaptado
- que mapeia valores de colunas de banco de dados para classes
persistentes que tem propriedades
- identificadoras do tipo especificado através do
<literal>id-type</literal>. Você deve especificar
- o mapeamento de valores do meta-type para nome de classes.
- </para>
-
- <programlisting><![CDATA[<any name="being"
id-type="long" meta-type="string">
- <meta-value value="TBL_ANIMAL" class="Animal"/>
- <meta-value value="TBL_HUMAN" class="Human"/>
- <meta-value value="TBL_ALIEN" class="Alien"/>
- <column name="table_name"/>
- <column name="id"/>
-</any>]]></programlisting>
-
- <programlistingco>
- <areaspec>
- <area id="any1" coords="2 50"/>
- <area id="any2" coords="3 50"/>
- <area id="any3" coords="4 50"/>
- <area id="any4" coords="5 50"/>
- <area id="any5" coords="6 50"/>
- <area id="any6" coords="7 50"/>
- </areaspec>
- <programlisting><![CDATA[<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>]]></programlisting>
- <calloutlist>
- <callout arearefs="any1">
- <para>
- <literal>name</literal>: o nome da propriedade.
- </para>
- </callout>
- <callout arearefs="any2">
- <para>
- <literal>id-type</literal>: o tipo
identificador.
- </para>
- </callout>
- <callout arearefs="any3">
- <para>
- <literal>meta-type</literal> (opcional – valor
default <literal>string</literal>):
- Qualquer tipo que é permitido para um mapeamento
discriminador.
- </para>
- </callout>
- <callout arearefs="any4">
- <para>
- <literal>cascade</literal> (opcional – valor
default <literal>none</literal>):
- o estilo do cascade.
- </para>
- </callout>
- <callout arearefs="any5">
- <para>
- <literal>access</literal> (opcional – valor
default <literal>property</literal>):
- A estratégia que o hibernate deve usar para acessar o valor
da propriedade.
- </para>
- </callout>
- <callout arearefs="any6">
- <para>
- <literal>optimistic-lock</literal> (opcional -
valor default<literal>true</literal>):
- Especifica que as atualizações para esta propriedade requerem
ou não aquisição da
- trava otimista. Em outras palavras, define se uma versão de
incremento deve ocorrer
- se esta propriedade está modificada.
- </para>
- </callout>
- </calloutlist>
- </programlistingco>
-
- </sect2>
-
- </sect1>
-
- <sect1 id="mapping-types">
- <title>Tipos do Hibernate</title>
-
- <sect2 id="mapping-types-entitiesvalues" revision="1">
- <title>Entidades e valores</title>
-
- <para>
- Para entender o comportamento de vários objetos em nível de linguagem de
Java a
- respeito do serviço de persistência, nós precisamos classificá-los em
dois grupos.
- </para>
-
- <para>
- Uma <emphasis>entidade </emphasis> existe independentemente
de qualquer outro
- objeto guardando referências para a entidade. Em contraste com o modelo
usual de
- Java que um objeto não referenciado é coletado pelo garbage collector.
Entidades
- devem ser explicitamente salvas ou deletada (exceto em operações de
salvamento
- ou deleção que possam ser executada em
<emphasis>cascata</emphasis> de uma entidade
- pai para seus filhos). Isto é diferente do modelo ODMG de persistência do
objeto
- por acessibilidade – e corresponde quase a como objetos de aplicações são
- geralmente usados em grandes sistemas. Entidades suportam referências
circulares
- e comuns. Eles podem ser versionadas.
- </para>
-
- <para>
- Uma entidade em estado persistente consiste de referências para outras
entidades
- e instâncias de tipos de <emphasis>valor</emphasis>. Valores
são primitivos,
- coleções (não o que tem dentro de uma coleção), componentes e certos
objetos
- imutáveis. Entidades distintas, valores (em coleções e componentes
particulares)
- <emphasis>são </emphasis> persistidos e apagados por
acessibilidade. Visto que
- objetos value (e primitivos) são persistidos e apagados junto com as
entidades
- que os contém e não podem ser versionados independentemente. Valores têm
- identidade não independente, assim eles não podem ser comuns para duas
- entidades ou coleções.
-
- </para>
-
- <para>
- Até agora, nós estivemos usando o termo "classe persistente"
para referir
- a entidades. Nós iremos continuar a fazer isto. Falando a rigor, porém,
nem todas
- as classes definidas pelo usuário com estados persistentes são entidades.
Um
- <emphasis>componente</emphasis> é uma classe de usuário
definida com valores
- semânticos. Uma propriedade de Java de tipo
<literal>java.lang.String</literal>
- também tem um valor semêntico. Dada esta definição, nós podemos dizer que
- todos os tipos (classes) fornecida pelo JDK tem tipo de valor semântico
em Java,
- enquanto que tipos definidos pelo usuário pode ser mapeados com entidade
ou valor
- de tipo semântico. Esta decisão pertence ao desenvolvedor da aplicação.
Uma boa
- dica para uma classe entidade em um modelo de domínio são referências
comuns
- para uma instância simples daquela classe, enquanto a composição ou
agregação
- geralmente se traduz para um valor de tipo.
- </para>
-
- <para>
- Nós iremos rever ambos os conceitos durante toda a documentação.
-
- </para>
-
- <para>
- O desafio pe mapear o sistema de tipo de Java (e a definição do
desenvolvedor de
- entidades e tipos de valor) para o sistema de tipo SQL/banco de dados. A
ponte entre ambos
- os sistemas é fornecido pelo Hibernate: para entidades que usam
- <literal><class></literal>,
<literal><subclass></literal> e assim por diante.
- Para tipos de valores nós usamos
<literal><property></literal>,
- <literal><component></literal>, etc, geralmente
com um atributo
- <literal>type</literal>. O valor deste atributo é o nome de
um <emphasis>tipo de
- mapeamento</emphasis> do Hibernate. O Hibernate fornece muitos
mapeamentos
- (para tipos de valores do JDK padrão) ut of the box. Você pode escrever
os seus
- próprios tipos de mapeamentos e implementar sua estratégia de conversão
adaptada,
- como você verá adiante.
- </para>
-
- <para>
- Todos os tipos internos do hibernate exceto coleções suportam semânticas
nulas.
-
- </para>
-
- </sect2>
-
- <sect2 id="mapping-types-basictypes" revision="3">
- <title>Valores de tipos básicos</title>
-
- <para>
- O tipos internos de mapeamentos básicos podem ser a grosso modo
categorizado como:
- <variablelist>
- <varlistentry>
- <term><literal>integer, long, short, float, double,
character, byte,
- boolean, yes_no, true_false</literal></term>
- <listitem>
- <para>
- Tipos de mapeamentos de classes primitivas ou wrapper
Java especificos
- (vendor-specific) para tipos de coluna SQL. Boolean,
- <literal>boolean, yes_no</literal> são todas
codificações alternativas
- para um <literal>boolean</literal> ou
<literal>java.lang.Boolean</literal>
- do Java.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>string</literal></term>
- <listitem>
- <para>
- Um tipo de mapeamento de
<literal>java.lang.String</literal> para
- <literal>VARCHAR</literal> (ou
<literal>VARCHAR2</literal> no Oracle).
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>date, time,
timestamp</literal></term>
- <listitem>
- <para>
- Tipos de mapeamento de
<literal>java.util.Date</literal> e suas
- subclasses para os tipos SQL
<literal>DATE</literal>,
- <literal>TIME</literal> e
<literal>TIMESTAMP</literal>
- (ou equivalente).
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>calendar,
calendar_date</literal></term>
- <listitem>
- <para>
- Tipo de mapeamento de
<literal>java.util.Calendar</literal> para
- os tipos SQL <literal>TIMESTAMP</literal> e
- <literal>DATE</literal> (ou equivalente).
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>big_decimal,
big_integer</literal></term>
- <listitem>
- <para>
- Tipo de mapeamento de
<literal>java.math.BigDecimal</literal> and
- <literal>java.math.BigInteger</literal> para
<literal>NUMERIC</literal>
- (ou <literal>NUMBER</literal> no Oracle).
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>locale, timezone,
currency</literal></term>
- <listitem>
- <para>
- Tipos de mapeamentos de
<literal>java.util.Locale</literal>,
- <literal>java.util.TimeZone</literal> e
<literal>java.util.Currency</literal>
- para <literal>VARCHAR</literal> (ou
<literal>VARCHAR2</literal> no Oracle).
- Instâncias de f <literal>Locale</literal> e
<literal>Currency</literal>
- são mapeados para seus códigos ISO. Instâncias de
<literal>TimeZone</literal>
- são mapeados para seu <literal>ID</literal>.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>class</literal></term>
- <listitem>
- <para>
- um tipo de mapeamento de
<literal>java.lang.Class</literal> para
- <literal>VARCHAR</literal> (ou
<literal>VARCHAR2</literal> no
- Oracle). Uma <literal>Class</literal> é
mapeada pelo
- seu nome qualificado (completo).
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>binary</literal></term>
- <listitem>
- <para>
- Mapeia arrays de bytes para um tipo binário de SQL
apropriado.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>text</literal></term>
- <listitem>
- <para>
- Maps long Java strings to a SQL
<literal>CLOB</literal> or
- <literal>TEXT</literal> type.
- Mapeia strings longas de Java para um tipo SQL
- <literal>CLOB</literal> ou
<literal>TEXT</literal>.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
-
<term><literal>serializable</literal></term>
- <listitem>
- <para>
- Mapeia tipos Java serializáveis para um tipo binário SQL
apropriado.
- Você pode também indicar o tipo
<literal>serializable</literal> do
- Hibernate com o nome da classe ou interface Java
serializável que
- não é padrão para um tipo básico.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>clob,
blob</literal></term>
- <listitem>
- <para>
- Tipos de mapeamentos para as classes JDBC
<literal>java.sql.Clob</literal> and
- <literal>java.sql.Blob</literal>. Estes tipos
podem ser inconveniente para
- algumas aplicações, visto que o objeto blob ou clob pode
não ser reusado
- fora de uma transação. (Além disso, o suporte de driver é
imcompleto e
- inconsistente.)
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>
- <literal>imm_date, imm_time, imm_timestamp,
imm_calendar, imm_calendar_date,
- imm_serializable, imm_binary</literal>
- </term>
- <listitem>
- <para>
- Mapeando tipos para o que geralmente são consideradas
tipos mutáveis de
- Java, onde o Hibernate faz determinadas otimizações
apropriadas somente
- para tipos imutáveis de Java, e a aplicação trata o
objeto como imutável.
- Por exemplo, você não deve chamar
<literal>Date.setTime()</literal> para
- uma instância mapeada como
<literal>imm_timestamp</literal>. Para mudar
- o valor da propriedade, e ter a mudança feita
persistente, a aplicação
- deve atribuir um novo objeto (nonidentical) à
propriedade.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
-
- </para>
-
- <para>
- Identificadores únicos das entidades e coleções podem ser de qualquer
tipo
- básico exceto <literal>binary</literal>,
<literal>blob</literal> ou
- <literal>clob</literal>. (Identificadores compostos também
são permitidos,
- veja abaixo.)
- </para>
-
- <para>
- Os tipos de valores básicos têm suas constantes
<literal>Type</literal>
- correspondentes definidas em
<literal>org.hibernate.Hibernate</literal>. Por exemplo,
- <literal>Hibernate.STRING</literal> representa o tipo
<literal>string</literal>.
- </para>
-
- </sect2>
-
- <sect2 id="mapping-types-custom" revision="2">
- <title>Tipos de valores personalizados</title>
-
- <para>
- É relativamente fácil para desenvolvedores criar seus próprios tipos de
valor.
- Por exemplo, você pode querer persistir propriedades do tipo
- <literal>java.lang.BigInteger</literal> para colunas
<literal>VARCHAR</literal>. O
- Hibernate não fornece um tipo correspondente para isso. Mas os tipos
adaptados
- não são limitados a mapeamento de uma propriedade (ou elemento de
coleção) a uma
- única coluna da tabela. Assim, por exemplo, você pôde ter uma propriedade
Java
-
<literal>getName()</literal>/<literal>setName()</literal> do tipo
- <literal>java.lang.String</literal> que é persistido para
colunas
- <literal>FIRST_NAME</literal>,
<literal>INITIAL</literal>, <literal>SURNAME</literal>.
-
- </para>
-
- <para>
- Para implementar um tipo personalizado, implemente
<literal>org.hibernate.UserType</literal>
- or <literal>org.hibernate.CompositeUserType</literal> e
declare propriedades usando o nome
- qualificado da classe do tipo. Veja
<literal>org.hibernate.test.DoubleStringType</literal>
- para ver o tipo das coisas que são possíveis.
- </para>
-
- <programlisting><![CDATA[<property name="twoStrings"
type="org.hibernate.test.DoubleStringType">
- <column name="first_string"/>
- <column name="second_string"/>
-</property>]]></programlisting>
-
- <para>
- Observe o uso da tag
<literal><column></literal> para mapear uma propriedade
- para colunas múltiplas.
- </para>
-
- <para>
- As interfaces <literal>CompositeUserType</literal>,
<literal>EnhancedUserType</literal>,
- <literal>UserCollectionType</literal>, e
<literal>UserVersionType</literal>
- fornecem suporte para usos mais especializados.
- </para>
-
- <para>
- Você pode mesmo fornecer parâmetros a um
<literal>UserType</literal> no arquivo de mapeamento.
- Para isto, seu <literal>UserType</literal> deve implementar a
interface
- <literal>org.hibernate.usertype.ParameterizedType</literal>.
Para fornecer parâmetros a seu
- tipo personalizado, você pode usar o elemento
<literal><type></literal> em seus
- arquivos de mapeamento.
- </para>
-
- <programlisting><![CDATA[<property name="priority">
- <type name="com.mycompany.usertypes.DefaultValueIntegerType">
- <param name="default">0</param>
- </type>
-</property>]]></programlisting>
-
- <para>
- O <literal>UserType</literal> pode agora recuperar o valor
para o parâmetro chamado
- <literal>default</literal> da
<literal>Propriedade</literal> do passado a ele.
- </para>
-
- <para>
- Se você usar freqüentemente um determinado
<literal>UserType</literal>, pode ser útil definir
- um nome mais curto para ele. Você pode fazer isto usando o elemento
- <literal><typedef></literal>. Typedefs atribui
um nome a um tipo personalizado, e pode também
- conter uma lista de valores default de parâmetro se o tipo for
parametrizado.
- </para>
-
- <programlisting><![CDATA[<typedef
class="com.mycompany.usertypes.DefaultValueIntegerType"
name="default_zero">
- <param name="default">0</param>
-</typedef>]]></programlisting>
-
- <programlisting><![CDATA[<property name="priority"
type="default_zero"/>]]></programlisting>
-
- <para>
- It is also possible to override the parameters supplied in a typedef on a
case-by-case basis
- by using type parameters on the property mapping.
- </para>
-
- <para>
- Even though Hibernate's rich range of built-in types and support for
components means you
- will very rarely <emphasis>need</emphasis> to use a custom
type, it is nevertheless
- considered good form to use custom types for (non-entity) classes that
occur frequently
- in your application. For example, a
<literal>MonetaryAmount</literal> class is a good
- candidate for a <literal>CompositeUserType</literal>, even
though it could easily be mapped
- as a component. One motivation for this is abstraction. With a custom
type, your mapping
- documents would be future-proofed against possible changes in your way of
representing
- monetary values.
- </para>
-
- </sect2>
-
- </sect1>
-
- <sect1 id="mapping-entityname">
- <title>Mapping a class more than once</title>
- <para>
- It is possible to provide more than one mapping for a particular persistent
class. In this
- case you must specify an <emphasis>entity name</emphasis> do
disambiguate between instances
- of the two mapped entities. (By default, the entity name is the same as the
class name.)
- Hibernate lets you specify the entity name when working with persistent
objects, when writing
- queries, or when mapping associations to the named entity.
- </para>
-
- <programlisting><![CDATA[<class name="Contract"
table="Contracts"
- entity-name="CurrentContract">
- ...
- <set name="history" inverse="true"
- order-by="effectiveEndDate desc">
- <key column="currentContractId"/>
- <one-to-many entity-name="HistoricalContract"/>
- </set>
-</class>
-
-<class name="Contract" table="ContractHistory"
- entity-name="HistoricalContract">
- ...
- <many-to-one name="currentContract"
- column="currentContractId"
- entity-name="CurrentContract"/>
-</class>]]></programlisting>
-
- <para>
- Notice how associations are now specified using
<literal>entity-name</literal> instead of
- <literal>class</literal>.
- </para>
-
- </sect1>
-
- <sect1 id="mapping-quotedidentifiers">
- <title>SQL quoted identifiers</title>
- <para>
- You may force Hibernate to quote an identifier in the generated SQL by
enclosing the table or
- column name in backticks in the mapping document. Hibernate will use the
correct quotation
- style for the SQL <literal>Dialect</literal> (usually double
quotes, but brackets for SQL
- Server and backticks for MySQL).
- </para>
-
- <programlisting><![CDATA[<class name="LineItem"
table="`Line Item`">
- <id name="id" column="`Item Id`"/><generator
class="assigned"/></id>
- <property name="itemNumber" column="`Item #`"/>
- ...
-</class>]]></programlisting>
-
- </sect1>
-
-
- <sect1 id="mapping-alternatives">
- <title>Metadata alternatives</title>
-
- <para>
- XML isn't for everyone, and so there are some alternative ways to define O/R
mapping metadata in Hibernate.
- </para>
-
- <sect2 id="mapping-xdoclet">
- <title>Using XDoclet markup</title>
-
- <para>
- Many Hibernate users prefer to embed mapping information directly in
sourcecode using
- XDoclet <literal>(a)hibernate.tags</literal>. We will not cover
this approach in this
- document, since strictly it is considered part of XDoclet. However, we
include the
- following example of the <literal>Cat</literal> class with
XDoclet mappings.
- </para>
-
- <programlisting><![CDATA[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"
- */
- public float getWeight() {
- return weight;
- }
- void setWeight(float weight) {
- this.weight = weight;
- }
-
- /**
- * @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;
- }
-}]]></programlisting>
-
- <para>
- See the Hibernate web site for more examples of XDoclet and Hibernate.
- </para>
-
- </sect2>
-
- <sect2 id="mapping-annotations" revision="2">
- <title>Using JDK 5.0 Annotations</title>
-
- <para>
- JDK 5.0 introduced XDoclet-style annotations at the language level, type-safe
and
- checked at compile time. This mechnism is more powerful than XDoclet
annotations and
- better supported by tools and IDEs. IntelliJ IDEA, for example, supports
auto-completion
- and syntax highlighting of JDK 5.0 annotations. The new revision of the EJB
specification
- (JSR-220) uses JDK 5.0 annotations as the primary metadata mechanism for
entity beans.
- Hibernate3 implements the <literal>EntityManager</literal> of
JSR-220 (the persistence API),
- support for mapping metadata is available via the <emphasis>Hibernate
Annotations</emphasis>
- package, as a separate download. Both EJB3 (JSR-220) and Hibernate3 metadata
is supported.
- </para>
-
- <para>
- This is an example of a POJO class annotated as an EJB entity bean:
- </para>
-
- <programlisting><![CDATA[@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;
-
- // Getter/setter and business methods
-}]]></programlisting>
-
- <para>
- Note that support for JDK 5.0 Annotations (and JSR-220) is still work in
progress and
- not completed. Please refer to the Hibernate Annotations module for more
details.
- </para>
-
- </sect2>
- </sect1>
-
- <sect1 id="mapping-generated" revision="1">
- <title>Generated Properties</title>
- <para>
- Generated properties are properties which have their values generated by the
- database. Typically, Hibernate applications needed to
<literal>refresh</literal>
- objects which contain any properties for which the database was generating
values.
- Marking properties as generated, however, lets the application delegate this
- responsibility to Hibernate. Essentially, whenever Hibernate issues an SQL
INSERT
- or UPDATE for an entity which has defined generated properties, it
immediately
- issues a select afterwards to retrieve the generated values.
- </para>
- <para>
- Properties marked as generated must additionally be non-insertable and
non-updateable.
- Only <xref
linkend="mapping-declaration-version">versions</xref>,
- <xref
linkend="mapping-declaration-timestamp">timestamps</xref>, and
- <xref linkend="mapping-declaration-property">simple
properties</xref> can be marked as
- generated.
- </para>
- <para>
- <literal>never</literal> (the default) - means that the given property
value
- is not generated within the database.
- </para>
- <para>
- <literal>insert</literal> - states that the given property value is
generated on
- insert, but is not regenerated on subsequent updates. Things like created-date
would
- fall into this category. Note that even thought
- <xref linkend="mapping-declaration-version">version</xref>
and
- <xref
linkend="mapping-declaration-timestamp">timestamp</xref> properties
can
- be marked as generated, this option is not available there...
- </para>
- <para>
- <literal>always</literal> - states that the property value is generated
both
- on insert and on update.
- </para>
- </sect1>
-
- <sect1 id="mapping-database-object">
- <title>Auxiliary Database Objects</title>
- <para>
- Allows CREATE and DROP of arbitrary database objects, in conjunction with
- Hibernate's schema evolution tools, to provide the ability to fully
define
- a user schema within the Hibernate mapping files. Although designed
specifically
- for creating and dropping things like triggers or stored procedures, really
any
- SQL command that can be run via a
<literal>java.sql.Statement.execute()</literal>
- method is valid here (ALTERs, INSERTS, etc). There are essentially two modes
for
- defining auxiliary database objects...
- </para>
- <para>
- The first mode is to explicitly list the CREATE and DROP commands out in the
mapping
- file:
- </para>
- <programlisting><![CDATA[<hibernate-mapping>
- ...
- <database-object>
- <create>CREATE TRIGGER my_trigger ...</create>
- <drop>DROP TRIGGER my_trigger</drop>
- </database-object>
-</hibernate-mapping>]]></programlisting>
- <para>
- The second mode is to supply a custom class which knows how to construct the
- CREATE and DROP commands. This custom class must implement the
- <literal>org.hibernate.mapping.AuxiliaryDatabaseObject</literal>
interface.
- </para>
- <programlisting><![CDATA[<hibernate-mapping>
- ...
- <database-object>
- <definition class="MyTriggerDefinition"/>
- </database-object>
-</hibernate-mapping>]]></programlisting>
- <para>
- Additionally, these database objects can be optionally scoped such that they
only
- apply when certain dialects are used.
- </para>
- <programlisting><![CDATA[<hibernate-mapping>
- ...
- <database-object>
- <definition class="MyTriggerDefinition"/>
- <dialect-scope name="org.hibernate.dialect.Oracle9Dialect"/>
- <dialect-scope name="org.hibernate.dialect.OracleDialect"/>
- </database-object>
-</hibernate-mapping>]]></programlisting>
- </sect1>
-</chapter>
-
+<chapter id="mapping">
+ <title>Mapeamento O/R Bassico</title>
+
+ <sect1 id="mapping-declaration" revision="1">
+ <title>Declaração de mapeamento</title>
+
+ <para>
+ Object/relational mappings are usually defined in an XML document. The
mapping
+ document is designed to be readable and hand-editable. The mapping language
is
+ Java-centric, meaning that mappings are constructed around persistent class
+ declarations, not table declarations.
+ </para>
+
+ <para>
+ Note that, even though many Hibernate users choose to write the XML by hand,
+ a number of tools exist to generate the mapping document, including XDoclet,
+ Middlegen and AndroMDA.
+ </para>
+
+ <para>
+ Lets kick off with an example mapping:
+ </para>
+
+ <programlisting id="mapping-declaration-ex1"
revision="1"><![CDATA[<?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"/>
+
+ <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>]]></programlisting>
+
+ <para>
+ Discutir agora o conteúdo deste documento de mapeamento. Iremos apenas
descrever
+ os elementos do documento e atributos que são utilizados pelo Hibernate em
tempo
+ de execução. O documento de mapeamento também contém alguns atributos
adicionais
+ e opcionais além de elementos que afetam os esquemas de banco de dados
exportados
+ pela ferramenta de exportação de esquemas. (Por exemplo, o atributo
+ <literal>not-null</literal>).
+ </para>
+
+
+
+ <sect2 id="mapping-declaration-doctype" revision="3">
+ <title>Doctype</title>
+
+ <para>
+ Todos os mapeamentos de XML devem declarar o doctype exibido. O DTD atual
pode
+ ser encontrado na URL abaixo, no diretório
<literal>hibernate-x.x.x/src/org/
+ hibernate </literal> ou no
<literal>hibernate3.jar</literal>. O Hibernate sempre
+ irá procurar pelo DTD inicialmente no seu classpath. Se você tentar
localizar
+ o DTD usando uma conexão de internet, compare a declaração do seu DTD com
o
+ conteúdo do seu classpath
+ </para>
+
+ <sect3 id="mapping-declaration-entity-resolution">
+ <title>EntityResolver</title>
+ <para>
+ As mentioned previously, Hibernate will first attempt to resolve DTDs
in its classpath. The
+ manner in which it does this is by registering a custom
<literal>org.xml.sax.EntityResolver</literal>
+ implementation with the SAXReader it uses to read in the xml files.
This custom
+ <literal>EntityResolver</literal> recognizes two
different systemId namespaces.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ a <literal>hibernate namespace</literal> is
recognized whenever the
+ resolver encounteres a systemId starting with
+
<
literal>http://hibernate.sourceforge.net/</literal>; the resolver
+ attempts to resolve these entities via the classlaoder which
loaded
+ the Hibernate classes.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ a <literal>user namespace</literal> is recognized
whenever the
+ resolver encounteres a systemId using a
<literal>classpath://</literal>
+ URL protocol; the resolver will attempt to resolve these
entities
+ via (1) the current thread context classloader and (2) the
+ classloader which loaded the Hibernate classes.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ An example of utilizing user namespacing:
+ </para>
+ <programlisting><![CDATA[<?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 types SYSTEM "classpath://your/domain/types.xml">
+]>
+
+<hibernate-mapping package="your.domain">
+ <class name="MyEntity">
+ <id name="id" type="my-custom-id-type">
+ ...
+ </id>
+ <class>
+ &types;
+</hibernate-mapping>]]></programlisting>
+ <para>
+ Where <literal>types.xml</literal> is a resource in the
<literal>your.domain</literal>
+ package and contains a custom <xref
linkend="mapping-types-custom">typedef</xref>.
+ </para>
+ </sect3>
+ </sect2>
+
+ <sect2 id="mapping-declaration-mapping" revision="3">
+ <title>hibernate-mapping</title>
+
+ <para>
+ Este elemento tem diversos atributos opcionais. Os atributos
+ <literal>schema</literal> e
<literal>catalog</literal> especificam que tabelas
+ referenciadas neste mapeamento pertencem ao esquema e/ou ao catalogo
nomeado.
+ Se especificados, os nomes das tabelas irão ser qualificados no schema ou
catalog dado.
+ Se não, os nomes das tabelas não serão qualificados. O atributo
<literal>default-cascade
+ </literal> especifica qual estilo de cascata será assumido pelas
propriedades e
+ coleções que não especificarm um atributo
<literal>cascade</literal>. O atributo
+ <literal>auto-import</literal> nos deixa utilizar nomes de
classes não qualificados
+ na linguagem de consulta, por default.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="hm1" coords="2 55"/>
+ <area id="hm2" coords="3 55"/>
+ <area id="hm3" coords="4 55"/>
+ <area id="hm4" coords="5 55"/>
+ <area id="hm5" coords="6 55"/>
+ <area id="hm6" coords="7 55"/>
+ <area id="hm7" coords="8 55"/>
+ </areaspec>
+ <programlisting><![CDATA[<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"
+ />]]></programlisting>
+ <calloutlist>
+ <callout arearefs="hm1">
+ <para>
+ <literal>schema</literal> (opcional): O nome do
esquema do banco de dados.
+ </para>
+ </callout>
+ <callout arearefs="hm2">
+ <para>
+ <literal>catalog</literal> (opcional): O nome
do catálogo do banco de dados.
+ </para>
+ </callout>
+ <callout arearefs="hm3">
+ <para>
+ <literal>default-cascade</literal> (opcional –
default é <literal>nenhum
+ </literal>): Um estilo cascata default.
+ </para>
+ </callout>
+ <callout arearefs="hm4">
+ <para>
+ <literal>default-access</literal> (opcional –
default é <literal>property</literal>):
+ A estratégia que o Hibernate deve utilizar para acessar
todas as propridades. Pode
+ ser uma implementação própria de
<literal>PropertyAccessor</literal>.
+ </para>
+ </callout>
+ <callout arearefs="hm5">
+ <para>
+ <literal>default-lazy</literal> (opcional -
default é <literal>true</literal>):
+ O valor default para atributos
<literal>lazy</literal> da classe e dos
+ mapeamentos de coleções.
+ </para>
+ </callout>
+ <callout arearefs="hm6">
+ <para>
+ <literal>auto-import</literal> ((opcional -
default é <literal>true</literal>):
+ Especifica se nós podemos usar nomes de classess não
qualificados
+ (das classes deste mapeamento) na linguagem de consulta.
+ </para>
+ </callout>
+ <callout arearefs="hm7">
+ <para>
+ <literal>package</literal> (opcional):
Especifica um prefixo da package para
+ assumir para nomes de classes não qualificadas no documento
de mapeamento.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ Se voce tem duas classes persistentes com o mesmo nome (não
qualificadas), você deve
+ setar <literal>auto-import="false"</literal>. O
Hibernate irá gerar uma exceção se
+ você tentar setar duas classes para o mesmo nome "importado".
+ </para>
+
+ <para>
+ Observe que o elemento <literal>hibernate-mapping</literal>
permite a você
+ aninhar diversos mapeamentos de
<literal><class></literal> persistentes,
+ como mostrado abaixo. Entretanto, é uma boa prática (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 nomea-la
após
+ a superclasse persistente, por exemplo:
<literal>Cat.hbm.xml</literal>,
+ <literal>Dog.hbm.xml</literal>, ou se estiver usando
herança,
+ <literal>Animal.hbm.xml</literal>.
+ </para>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-class" revision="3">
+ <title>class</title>
+
+ <para>
+ Você pode declarar uma classe persistente utilizando o elemento
+ <literal>class</literal>:
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="class1" coords="2 55"/>
+ <area id="class2" coords="3 55" />
+ <area id="class3" coords="4 55"/>
+ <area id="class4" coords="5 55" />
+ <area id="class5" coords="6 55"/>
+ <area id="class6" coords="7 55" />
+ <area id="class7" coords="8 55"/>
+ <area id="class8" coords="9 55" />
+ <area id="class9" coords="10 55" />
+ <area id="class10" coords="11 55"/>
+ <area id="class11" coords="12 55"/>
+ <area id="class12" coords="13 55"/>
+ <area id="class13" coords="14 55"/>
+ <area id="class14" coords="15 55"/>
+ <area id="class15" coords="16 55"/>
+ <area id="class16" coords="17 55"/>
+ <area id="class17" coords="18 55"/>
+ <area id="class18" coords="19 55"/>
+ <area id="class19" coords="20 55"/>
+ <area id="class20" coords="21 55"/>
+ <area id="class21" coords="22 55"/>
+ </areaspec>
+ <programlisting><![CDATA[<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"
+ where="arbitrary sql where condition"
+ persister="PersisterClass"
+ batch-size="N"
+ optimistic-lock="none|version|dirty|all"
+ lazy="true|false"
+ entity-name="EntityName"
+ check="arbitrary sql check condition"
+ rowid="rowid"
+ subselect="SQL expression"
+ abstract="true|false"
+ node="element-name"
+/>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="class1">
+ <para>
+ <literal>name</literal> (opcional): O nome da
classe Java inteiramente qualificado
+ da classe persistente (ou interface); Se o atributo é
ausente, assume-se que o
+ mapeamento é para intidades não-POJO.
+ </para>
+ </callout>
+ <callout arearefs="class2">
+ <para>
+ <literal>table</literal> (opcional – default para
nomes de classes não
+ qualificadas) O nome da sua tabela do banco de dados.
+ </para>
+ </callout>
+ <callout arearefs="class3">
+ <para>
+ <literal>discriminator-value</literal> (opcional
– default para o nome da classe):
+ Um valor que distingue subclasses individuais, usadas para o
comportamento polimorfico.
+ Valores aceitos incluem <literal>null</literal> e
<literal>not null</literal>
+ </para>
+ </callout>
+ <callout arearefs="class4">
+ <para>
+ <literal>mutable</literal> (opcional - valor
default <literal>true</literal>):
+ Especifica que instancias da classe são (ou não) mutáveis
+ </para>
+ </callout>
+ <callout arearefs="class5">
+ <para>
+ <literal>schema</literal> (opcional): Sobrepõe o
nome do esquema especificado
+ pelo elemento root
<literal><hibernate-mapping></literal>.
+ </para>
+ </callout>
+ <callout arearefs="class6">
+ <para>
+ <literal>catalog</literal> (opcional): Sobrepõe o
nome do catálogo especificado
+ pelo elemento root
<literal><hibernate-mapping></literal>.
+ </para>
+ </callout>
+ <callout arearefs="class7">
+ <para>
+ <literal>proxy</literal> (opcional): Especifica
um interface para ser
+ utilizada pelos proxies de inicialização tardia. Você pode
especificar o
+ nome da própria classe.
+ </para>
+ </callout>
+ <callout arearefs="class8">
+ <para>
+ <literal>dynamic-update</literal> (opcional,
valor default <literal>false</literal>):
+ Especifica que o SQL de <literal>UPDATE</literal>
deve ser gerado em tempo de
+ execução e conter apenas aquelas colunas cujos valores foram
alterados.
+ </para>
+ </callout>
+ <callout arearefs="class9">
+ <para>
+ <literal>dynamic-insert</literal> (opcional,
valor default <literal>false</literal>):
+ Especifica que o SQL de
<literal>INSERT</literal> deve ser gerado em tempo de
+ execução e conter apenas aquelas colunas cujos valores não
estão nulos.
+ </para>
+ </callout>
+ <callout arearefs="class10">
+ <para>
+ <literal>select-before-update</literal>
(opcional, valor default <literal>false</literal>):
+ Especifica que o Hibernate
<emphasis>never</emphasis> deve executar um SQL de
+ <literal>UPDATE</literal> a não ser que com
certeza um objeto está atualmente modificado.
+ Em certos casos (atualmente, apenas quando um objeto
transiente foi associado com uma nova
+ sessão utilizando <literal>update()</literal>),
isto significa que o Hibernate ira executar
+ uma instrução SQL de <literal>SELECT</literal>
adicional para determinar se um
+ <literal>UPDATE</literal> é necessário nesse
momento.
+ </para>
+ </callout>
+ <callout arearefs="class11">
+ <para>
+ <literal>polymorphism</literal> (opcional,
default para <literal>implicit</literal>):
+ Determina se deve ser utilizado a query polimorfica implicita
ou explicitamente.
+ </para>
+ </callout>
+ <callout arearefs="class12">
+ <para>
+ <literal>where</literal> (opicional) especifica
um comando SQL <literal>WHERE</literal>
+ arbitrário para ser usado quando da recuperação de objetos
desta classe.
+ </para>
+ </callout>
+ <callout arearefs="class13">
+ <para>
+ <literal>persister</literal> (opcional):
Espeicifca uma <literal>ClassPersister</literal>
+ customizada.
+ </para>
+ </callout>
+ <callout arearefs="class14">
+ <para>
+ <literal>batch-size</literal> (opcional, valor
default <literal>1</literal>) especifica um
+ "tamanho de lote" para a recuperação de instancias
desta classe pelo identificador.
+ </para>
+ </callout>
+ <callout arearefs="class15">
+ <para>
+ <literal>optimistic-lock</literal> (octional,
valor default <literal>version</literal>):
+ Determina a estratégia de bloqueio.
+ </para>
+ </callout>
+ <callout arearefs="class16">
+ <para>
+ <literal>lazy</literal> (opcional): A recuperação
tardia pode ser completamente
+ desabilitada, setando
<literal>lazy="false"</literal>.
+ </para>
+ </callout>
+ <callout arearefs="class17">
+ <para>
+ <literal>entity-name</literal> (opcional, default
para o nome da classe): O
+ Hibernate3 permite uma classe ser mapeada multiplas vezes,
(potencialmente,para
+ diferentes tabelas), e permite mapeamentos de entidades que
são representadas
+ por Maps ou XML no nível Java. Nestes casos, você deve
especificar um nome
+ arbitrário explicitamente para a entidade. Veja <xref
linkend="persistent-classes-dynamicmodels"/>
+ e <xref linkend="xml"/> para maiores
informações.
+ </para>
+ </callout>
+ <callout arearefs="class18">
+ <para>
+ <literal>check</literal> (opcional): Uma
expressão SQL utilizada para gerar uma
+ constraint de <emphasis>verificação</emphasis> de
múltiplas linhas para a geração
+ automática do esquema.
+ </para>
+ </callout>
+ <callout arearefs="class19">
+ <para>
+ <literal>rowid</literal> (opcional): O Hibernate
poder usar as assim chamadas
+ ROWIDs em bancos de dados que a suportam. Por exemplo, no
Oracle, o Hibernate
+ pode utilizar a coluna extra rowid para atualizações mais
rápidas se você
+ configurar esta opção para
<literal>rowid</literal>. Um ROWID é uma implementação
+ que representa de maneira detalhada a localização física de
uma determinada
+ tupla armazenado.
+ </para>
+ </callout>
+ <callout arearefs="class20">
+ <para>
+ <literal>subselect</literal> (optional): Maps an
immutable and read-only entity
+ to a database subselect. Useful if you want to have a view
instead of a base table,
+ but don't. See below for more information.
+ <literal>subselect</literal> (opcional): Mapeia
uma entidade imutavel e somente
+ de leitura para um subconjunto do banco de dados. Útil se
você quiser ter uma
+ view em vez de uma tabela. Veja abaixo para mais
informações.
+ </para>
+ </callout>
+ <callout arearefs="class21">
+ <para>
+ <literal>abstract</literal> (opcional): Utilizada
para marcar superclasses
+ abstratas em hierarquias
<literal><union-subclass></literal>.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ É perfeitamente aceitável para uma classe persitente nomeada ser uma
interface. Você deverá
+ então declarar as classes implementadas desta interface utilizando o
elemento
+ <literal><subclass></literal>. Você pode
persistir qualquer classe de aninhada
+ <emphasis>estatica</emphasis>. Você deverá especificar o nome
da classe usando a forma
+ padrão, por exemplo: <literal>eg.Foo$Bar</literal>.
+ </para>
+
+ <para>
+ Classes imutáveis,
<literal>mutable="false"</literal>, não podem ser modificadas ou
excluídas
+ pela aplicação. Isso permite ao Hibernate fazer alguns aperfeiçoamentos
de performance.
+ </para>
+
+ <para>
+ O atributo opcional <literal>proxy</literal> habilita a
inicialização tardia das
+ instâncias persistentes da classe. O Hibernate irá retornar CGLIB proxies
como implementado
+ na interface nomeada. O objeto persistente atual será carregado quando
um método do proxy
+ for invocado. Veja "Inicializando coleções e proxies" abaixo.
+ </para>
+
+ <para>Polimorfismo <emphasis>implícito</emphasis> significa
que instâncias de uma classe
+ serão retornada por uma query que dá nome a qualquer superclasse ou
interface implementada,
+ ou a classe e as instancias de qualquer subclasse da classe será
retornada por umq query
+ que nomeia a classe por si. Polimorfismo
<emphasis>explícito</emphasis> significa que
+ instancias da classe serão retornadas apenas por queries que
explicitamente nomeiam a
+ classe e que queries que nomeiam as classes irão retornar apenas
instancias de subclasses
+ mapeadas dentro da declaração
<literal><class></literal> como uma
+ <literal><subclass></literal> ou
<literal><joined-subclass></literal>.
+ Para a maioria dos casos, o valor default
<literal>polymorphism="implicit"</literal>,
+ é apropriado. Polimorfismo explicito é útil quando duas classes distintas
estão mapeadas
+ para a mesma tabela (isso permite um classe "peso leve" que
contem um subconjunto
+ de colunas da tabela).
+ </para>
+
+ <para>
+ O atributo <literal>persister</literal> deixa você customizar
a estratégia de persistência
+ utilizada para a classe. Você pode, por exemplo, especificar sua prórpia
subclasse do
+ <literal>org.hibernate.persister.EntityPersister</literal> ou
você pode criar
+ uma implementação completamente nova da interface
+ <literal>org.hibernate.persister.ClassPersister</literal> que
implementa a persistência
+ através de, por exemplo, chamadas a stored procedeures, serialização de
arquivos flat ou
+ LDAP. Veja
<literal>org.hibernate.test.CustomPersister</literal> para um exemplo
+ simples (de "persistencia" para uma
<literal>Hashtable</literal>).
+ </para>
+
+ <para>
+ Observe que as configurações
<literal>dynamic-update</literal> e
+ <literal>dynamic-insert</literal> não sao herdadas pelas
subclasses e assim podem tambem
+ ser especificadas em elementos
<literal><subclass></literal> or
+ <literal><joined-subclass></literal>. Estas
configurações podem incrementar a
+ performance em alguns casos, mas pode realmente diminuir a performance em
outras.
+ Use-as de forma bastante criteriosa.
+ </para>
+
+ <para>
+ O uso de <literal>select-before-update</literal> geralmente
irá diminuir a performance. Ela é
+ muito útil para prevenir que uma trigger de atualização no banco de dados
seja ativada
+ desnecessariamente, se você reconectar um nó de uma instancia
desconectada em uma
+ <literal>Session</literal>.
+ </para>
+
+ <para>
+ Se você ativar <literal>dynamic-update</literal>, você terá
de escolher
+ a estratégia de bloqueio otimista:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>version</literal> verifica a versão e a hora
das colunas
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>all</literal> cverifica todas as colunas
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>dirty</literal> verifica as colunas
modificadas, permitindo
+ alguns updates concorrentes
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>none</literal> não utiliza o bloqueio
otimista
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Nós <emphasis>recomendamos</emphasis> com muita enfase que
você utilize a
+ versão e a hora das colunas para o bloqueio otimista com o Hibernate.
+ Esta é a melhor estratégia com respeito a performance e é a única
estratégia
+ que trata corretamente as modificações efetuadas em instancias
desconectadas
+ (por exemplo, quando <literal>Session.merge()</literal> é
utilizado).
+
+ </para>
+
+ <para>
+ Não ha diferença entre uma view e uma tabela para o mapeamento do
Hibernate, e como
+ esperado isto é transparente no nível do banco de dados (observe que
alguns bancos de
+ dados não suportam views apropriadamente, especialmente com updates).
Algumas vezes,
+ você quer utilizar uma view, ma snão pode cria-la no banco de dados (por
exemplo,
+ com um esquema legado). Neste caso, você pode mapear uma entidade
imutável e de
+ somente leitura, para uma dada expressão SQL, que representa um
subselect:
+ </para>
+
+ <programlisting><![CDATA[<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"/>
+ <synchronize table="bid"/>
+ <id name="name"/>
+ ...
+</class>]]></programlisting>
+
+ <para>
+ Declare as tabelas para sincronizar com esta entidade, garantindo que o
auto-flush
+ ocorra corretamente, e que as queries para esta entidade derivada não
retornem dados
+ desatualizados. O
<literal><subselect></literal> está disponível tanto como um
+ atributo como um elemento mapeado nested.
+ </para>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-id" revision="4">
+ <title>id</title>
+
+ <para>
+ Classes mapeadas <emphasis>precisam</emphasis> declarar a
coluna de chave primaria da
+ tabela do banco de dados. Muitas classes irão tambem ter uma propriedade
ao estilo
+ Java-Beans declarando o identificador unico de uma instancia. O elemento
+ <literal><id></literal> define o mapeamento
desta propriedade para a chave primária.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="id1" coords="2 70"/>
+ <area id="id2" coords="3 70" />
+ <area id="id3" coords="4 70"/>
+ <area id="id4" coords="5 70" />
+ <area id="id5" coords="6 70" />
+ </areaspec>
+ <programlisting><![CDATA[<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/(a)attribute|."
+
+ <generator class="generatorClass"/>
+</id>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="id1">
+ <para>
+ <literal>name</literal> (opcional): O nome do
identificador.
+ </para>
+ </callout>
+ <callout arearefs="id2">
+ <para>
+ <literal>type</literal> (opcional): Um nome que
indica o tipo no Hibernate.
+ </para>
+ </callout>
+ <callout arearefs="id3">
+ <para>
+ <literal>column</literal> (opcional – default
para o a propridade name): O
+ nome coluna chave primaria.
+ </para>
+ </callout>
+ <callout arearefs="id4">
+ <para>
+ <literal>unsaved-value</literal> (opcional -
default para um valor "sensível"):
+ Uma propriedade de identificação que indica que a instancia
foi novamente
+ instanciada (unsaved), diferenciando de instancias
desconectadas que foram
+ salvas ou carregadas em uma sessão anterior.
+ </para>
+ </callout>
+ <callout arearefs="id5">
+ <para>
+ <literal>access</literal> (opcional - valor
default <literal>property</literal>): A
+ estratégia que o Hiberante deve utilizar para acessar o valor
da propriedade
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ Se o atributo <literal>name</literal> não for declarado,
assume-se que a classe não tem
+ a propriedade de identificação.
+ </para>
+
+ <para>
+ O atributo <literal>unsaved-value</literal> não é mais
necessário no Hibernate 3.
+ </para>
+
+ <para>
+ Há declaração alternativa
<literal><composite-id></literal> permite o acesso a
+ dados legados com chaves compostas. Nós desencorajamos fortemente o seu
uso por
+ qualquer pessoa.
+ </para>
+
+ <sect3 id="mapping-declaration-id-generator"
revision="2">
+ <title>Generator</title>
+
+ <para>
+ O elemento filho opcional
<literal><generator></literal> nomeia uma classe Java
+ usada para gerar identificadores unicos para instancias de uma classe
persistente.
+ Se algum parâmetro é requerido para configurar ou inicializar a
instancia geradora,
+ eles são passados utilizando o elemento
<literal><param></literal>.
+ </para>
+
+ <programlisting><![CDATA[<id name="id"
type="long" column="cat_id">
+ <generator class="org.hibernate.id.TableHiLoGenerator">
+ <param name="table">uid_table</param>
+ <param name="column">next_hi_value_column</param>
+ </generator>
+</id>]]></programlisting>
+
+ <para>
+ Todos os generators implementam a interface
<literal>org.hibernate.id.IdentifierGenerator</literal>.
+ Esta é uma interface bem simples; algumas aplicações podem prover sua
própria implementação
+ esepecializada. Entretanto, o Hibernate disponibiliza um conjunto de
implementações internamente.
+ Há nomes de atalhos para estes generators próprios:
+ <variablelist>
+ <varlistentry>
+
<term><literal>increment</literal></term>
+ <listitem>
+ <para>
+ gera identificadores dos tipos
<literal>long</literal>, <literal>short</literal> ou
+ <literal>int</literal> que são unicos apenas
quando nenhum outro processo está
+ inserindo dados na mesma tabela. <emphasis>Não
utilize em ambientes
+ de cluster.</emphasis>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>identity</literal></term>
+ <listitem>
+ <para>
+ suporta colunas de identidade em DB2, MySQL, MS SQL
Server, Sybase e
+ HypersonicSQL. O identificador retornado é do tipo
<literal>long</literal>,
+ <literal>short</literal> ou
<literal>int</literal>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>sequence</literal></term>
+ <listitem>
+ <para>
+ utiliza uma sequence em DB2, PostgreSQL, Oracle, SAP DB,
McKoi ou um
+ generator no Interbase. O identificador de retorno é do
tipo <literal>
+ long</literal>,
<literal>short</literal> ou <literal>int</literal>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>hilo</literal></term>
+ <listitem>
+ <para
id="mapping-declaration-id-hilodescription" revision="1">
+ utiliza um algoritmo hi/lo para gerar de forma eficiente
identificadores do tipo
+ <literal>long</literal>,
<literal>short</literal> ou <literal>int</literal>,
+ a partir de uma tabela e coluna fornecida (por default
+ <literal>hibernate_unique_key</literal> e
<literal>next_hi</literal>)
+ como fonte para os valores hi. O algoritmo hi/lo gera
identificadores que são
+ únicos apenas para um banco de dados particular.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>seqhilo</literal></term>
+ <listitem>
+ <para>
+ utiliza um algoritmo hi/lo para gerar de forma eficinete
identificadores do tipo
+ <literal>long</literal>,
<literal>short</literal> ou <literal>int</literal>,
+ a partir de uma sequence de banco de dados fornecida.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>uuid</literal></term>
+ <listitem>
+ <para>
+ utiliza um algortimo UUID de 128-bits para gerar
identificadores do
+ tipo string, unicos em uma rede(o endereço IP é
utilizado). O UUID é
+ codificado como um string de digitos hexadecimais de
tamanho 32.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>guid</literal></term>
+ <listitem>
+ <para>
+ utiliza um string GUID gerado pelo banco de dados no MS
SQL Server
+ e MySQL.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>native</literal></term>
+ <listitem>
+ <para>
+ seleciona entre <literal>identity</literal>,
<literal>sequence</literal>
+ ou <literal>hilo</literal> dependendo das
capacidades do banco de dados
+ utilizado.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>assigned</literal></term>
+ <listitem>
+ <para>
+ deixa a aplicação definir um identificador para o objeto
antes que o
+ <literal>save()</literal> seja chamado. Esta
é a estratégia default
+ se nenhum elemento
<literal><generator></literal> é especificado.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>select</literal></term>
+ <listitem>
+ <para>
+ retorna a chave primaria recuperada por uma trigger do
banco de
+ dados, selecionado uma linha pela chave única e
recuperando o valor
+ da chave primária.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>foreign</literal></term>
+ <listitem>
+ <para>
+ utiliza o identificador de um outro objeto associado.
Normalmente utilizado
+ em conjunto com uma associaçõa de chave primária do tipo
+
<literal><one-to-one></literal>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+
<term><literal>sequence-identity</literal></term>
+ <listitem>
+ <para>
+ a specialized sequence generation strategy which utilizes
a
+ database sequence for the actual value generation, but
combines
+ this with JDBC3 getGeneratedKeys to actually return the
generated
+ identifier value as part of the insert statement
execution. This
+ strategy is only known to be supported on Oracle 10g
drivers
+ targetted for JDK 1.4. Note comments on these insert
statements
+ are disabled due to a bug in the Oracle drivers.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </para>
+ </sect3>
+
+ <sect3 id="mapping-declaration-id-hilo"
revision="1">
+ <title>Algoritmo Hi/lo</title>
+ <para>
+ Os geradores <literal>hilo</literal> e
<literal>seqhilo</literal> fornecem duas
+ implementações alternativas do algoritmo hi/lo, uma solução
preferencial para a geração
+ de identificadores. A primeira implementação requer uma tabela
especial do banco de
+ dados para manter o proximo valor "hi" disponível. A
segunda utiliza uma seqüência
+ do estilo Oracle (quando suportado).
+ </para>
+
+ <programlisting><![CDATA[<id name="id"
type="long" column="cat_id">
+ <generator class="hilo">
+ <param name="table">hi_value</param>
+ <param name="column">next_value</param>
+ <param name="max_lo">100</param>
+ </generator>
+</id>]]></programlisting>
+
+ <programlisting><![CDATA[<id name="id"
type="long" column="cat_id">
+ <generator class="seqhilo">
+ <param name="sequence">hi_value</param>
+ <param name="max_lo">100</param>
+ </generator>
+</id>]]></programlisting>
+
+ <para>
+ Infelizemente, voce não pode utilizar
<literal>hilo</literal> quando estiver
+ fornecendo sia propria <literal>Connection</literal>
para o Hibernate. Quando o
+ Hibernate está usando um datasource do servidor de aplicações para
obter conexões
+ suportadas com JTA, você precisa configurar adequadamente o
+
<literal>hibernate.transaction.manager_lookup_class</literal>.
+ </para>
+ </sect3>
+
+ <sect3 id="mapping-declaration-id-uuid">
+ <title>UUID algorithm</title>
+ <para>
+ O UUID contem: o endereço IP, hora de inicio da JVM (com precisão de
um quarto
+ de segundo), a hora do sistema e um valor contador (unico dentro da
JVM).
+ Não é possivel obter o endereço MAC ou um endereço de memória do
código Java,
+ assim este é o melhor que pode ser feito sem utilizar JNI.
+ </para>
+ </sect3>
+
+ <sect3 id="mapping-declaration-id-sequences">
+ <title>Colunas de identidade e sequencias</title>
+ <para>
+ Para bancos de dados que suportam colunas de identidade (DB2, MySQL,
Sybase,
+ MS SQL), você pode utilizar uma geração de chave
<literal>identity</literal>.
+ Para bancos de dados que suportam sequencias (DB2, Oracle,
PostgreSQL, Interbase,
+ McKoi, SAP DB) voce pode utilizar a geração de chaves no estilo
+ <literal>sequence</literal>. As duas estratégias requerem
duas consultas SQL
+ para inserir um novo objeto.
+ </para>
+
+ <programlisting><![CDATA[<id name="id"
type="long" column="person_id">
+ <generator class="sequence">
+ <param name="sequence">person_id_sequence</param>
+ </generator>
+</id>]]></programlisting>
+
+ <programlisting><![CDATA[<id name="id"
type="long" column="person_id" unsaved-value="0">
+ <generator class="identity"/>
+</id>]]></programlisting>
+
+ <para>
+ Para desenvolvimento multi-plataforma, a estratégia
<literal>native</literal>
+ irá escolher entre as estratégias i
<literal>identity</literal>,
+ <literal>sequence</literal> e
<literal>hilo</literal>, dependendo das
+ capacidades do banco de dados utilizado.
+ </para>
+ </sect3>
+
+ <sect3 id="mapping-declaration-id-assigned">
+ <title>Identificadores especificados</title>
+ <para>
+ Se você quer que a aplicação especifique os identificadores
+ (em vez do Hibernate gerá-los) você deve utilizar o gerador
+ <literal>assigned</literal>. Este gerador especial irá
utilizar o valor
+ do identificador especificado para a propriedade de identificação do
objeto.
+ Este gerador é usado quando a chave primaria é a chave natural em vez
de uma
+ surrogate key. Este é o comportamento padrão se você não especificar
+ um elemento
<literal><generator></literal>.
+ </para>
+
+ <para>
+ Escolher o gerador <literal>assigned</literal> faz com
que o Hibernate
+ utilize
<literal>unsaved-value="undefined"</literal>, forçando o Hibernate
+ ir até o banco de dados para determinar se uma instância está
transiente ou
+ desasociada, a menos que haja uma versão ou uma propriedade
timestamp,
+ ou você pode definir
<literal>Interceptor.isUnsaved()</literal>.
+ </para>
+ </sect3>
+
+ <sect3 id="mapping-declaration-id-select">
+ <title>Chaves primárias geradas por triggers</title>
+ <para>
+ Apenas para sistemas legados (o Hibernate nao gera DDL com
triggers).
+ </para>
+
+ <programlisting><![CDATA[<id name="id"
type="long" column="person_id">
+ <generator class="select">
+ <param name="key">socialSecurityNumber</param>
+ </generator>
+</id>]]></programlisting>
+
+ <para>
+ No exemplo acima, há uma única propriedade com valor nomeada
+ <literal>socialSecurityNumber</literal> definida pela
classe,
+ uma chave natural, e uma surrogate key nomeada
+ <literal>person_id</literal> cujo valor é gerado pro uma
trigger.
+ </para>
+
+ </sect3>
+
+ </sect2>
+ <sect2 id="mapping-declaration-id-enhanced">
+ <title>Enhanced identifier generators</title>
+
+ <para>
+ Starting with release 3.2.3, there are 2 new generators which represent a re-thinking
of 2 different
+ aspects of identifier generation. The first aspect is database portability; the
second is optimization
+ (not having to query the database for every request for a new identifier value).
These two new
+ generators are intended to take the place of some of the named generators described
above (starting
+ in 3.3.x); however, they are included in the current releases and can be referenced by
FQN.
+ </para>
+
+ <para>
+ The first of these new generators is
<literal>org.hibernate.id.enhanced.SequenceStyleGenerator</literal>
+ which is intended firstly as a replacement for the
<literal>sequence</literal> generator and secondly as
+ a better portability generator than <literal>native</literal> (because
<literal>native</literal>
+ (generally) chooses between <literal>identity</literal> and
<literal>sequence</literal> which have
+ largely different semantics which can cause subtle isssues in applications eyeing
portability).
+ <literal>org.hibernate.id.enhanced.SequenceStyleGenerator</literal>
however achieves portability in
+ a different manner. It chooses between using a table or a sequence in the database to
store its
+ incrementing values depending on the capabilities of the dialect being used. The
difference between this
+ and <literal>native</literal> is that table-based and sequence-based
storage have the same exact
+ semantic (in fact sequences are exactly what Hibernate tries to emmulate with its
table-based
+ generators). This generator has a number of configuration parameters:
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ <literal>sequence_name</literal> (optional, defaults to
<literal>hibernate_sequence</literal>):
+ The name of the sequence (or table) to be used.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>initial_value</literal> (optional, defaults to
<literal>1</literal>): The initial
+ value to be retrieved from the sequence/table. In sequence creation terms, this is
analogous
+ to the clause typical named "STARTS WITH".
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>increment_size</literal> (optional, defaults to
<literal>1</literal>): The value by
+ which subsequent calls to the sequence/table should differ. In sequence creation
terms, this
+ is analogous to the clause typical named "INCREMENT BY".
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>force_table_use</literal> (optional, defaults to
<literal>false</literal>): Should
+ we force the use of a table as the backing structure even though the dialect might
support
+ sequence?
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>value_column</literal> (optional, defaults to
<literal>next_val</literal>): Only
+ relevant for table structures! The name of the column on the table which is used
to
+ hold the value.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>optimizer</literal> (optional, defaults to
<literal>none</literal>):
+ See <xref linkend="mapping-declaration-id-enhanced-optimizers"/>
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ The second of these new generators is
<literal>org.hibernate.id.enhanced.TableGenerator</literal> which
+ is intended firstly as a replacement for the <literal>table</literal>
generator (although it actually
+ functions much more like
<literal>org.hibernate.id.MultipleHiLoPerTableGenerator</literal>) and
secondly
+ as a re-implementation of
<literal>org.hibernate.id.MultipleHiLoPerTableGenerator</literal> utilizing
the
+ notion of pluggable optimiziers. Essentially this generator defines a table capable
of holding
+ a number of different increment values simultaneously by using multiple distinctly
keyed rows. This
+ generator has a number of configuration parameters:
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ <literal>table_name</literal> (optional, defaults to
<literal>hibernate_sequences</literal>):
+ The name of the table to be used.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>value_column_name</literal> (optional, defaults to
<literal>next_val</literal>):
+ The name of the column on the table which is used to hold the value.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>segment_column_name</literal> (optional, defaults to
<literal>sequence_name</literal>):
+ The name of the column on the table which is used to hold the "segement
key". This is the
+ value which distinctly identifies which increment value to use.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>segment_value</literal> (optional, defaults to
<literal>default</literal>):
+ The "segment key" value for the segment from which we want to pull
increment values for
+ this generator.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>segment_value_length</literal> (optional, defaults to
<literal>255</literal>):
+ Used for schema generation; the column size to create this segment key column.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>initial_value</literal> (optional, defaults to
<literal>1</literal>):
+ The initial value to be retrieved from the table.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>increment_size</literal> (optional, defaults to
<literal>1</literal>):
+ The value by which subsequent calls to the table should differ.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>optimizer</literal> (optional, defaults to
<literal></literal>):
+ See <xref linkend="mapping-declaration-id-enhanced-optimizers"/>
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </sect2>
+
+ <sect2 id="mapping-declaration-id-enhanced-optimizers">
+ <title>Identifier generator optimization</title>
+ <para>
+ For identifier generators which store values in the database, it is inefficient for
them to hit the
+ database on each and every call to generate a new identifier value. Instead,
you'd ideally want to
+ group a bunch of them in memory and only hit the database when you have exhausted your
in-memory
+ value group. This is the role of the pluggable optimizers. Currently only the two
enhanced generators
+ (<xref linkend="mapping-declaration-id-enhanced"/> support this
notion.
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ <literal>none</literal> (generally this is the default if no optimizer
was specified): This
+ says to not perform any optimizations, and hit the database each and every
request.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>hilo</literal>: applies a hi/lo algorithm around the database
retrieved values. The
+ values from the database for this optimizer are expected to be sequential. The
values
+ retrieved from the database structure for this optimizer indicates the "group
number"; the
+ <literal>increment_size</literal> is multiplied by that value in memory
to define a group
+ "hi value".
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>pooled</literal>: like was discussed for
<literal>hilo</literal>, this optimizers
+ attempts to minimize the number of hits to the database. Here, however, we simply
store
+ the starting value for the "next group" into the database structure
rather than a sequential
+ value in combination with an in-memory grouping algorithm.
<literal>increment_size</literal>
+ here refers to the values coming from the database.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </sect2>
+
+
+ <sect2 id="mapping-declaration-compositeid"
revision="3">
+ <title>composite-id</title>
+
+ <programlisting><![CDATA[<composite-id
+ name="propertyName"
+ class="ClassName"
+ mapped="true|false"
+ access="field|property|ClassName">
+ node="element-name|."
+
+ <key-property name="propertyName" type="typename"
column="column_name"/>
+ <key-many-to-one name="propertyName class="ClassName"
column="column_name"/>
+ ......
+</composite-id>]]></programlisting>
+
+ <para>
+ Para tabelas com uma chave composta, você pode mapear múltiplas
propriedades
+ da classe como propriedades de identificação. O elemento
+ <literal><composite-id></literal> aceita o
mapeamento da propriedade
+ <literal><key-property></literal> e mapeamentos
+ <literal><key-many-to-one></literal>como
elements filhos.
+ </para>
+
+ <programlisting><![CDATA[<composite-id>
+ <key-property name="medicareNumber"/>
+ <key-property name="dependent"/>
+</composite-id>]]></programlisting>
+
+ <para>
+ Sua classe persistente <emphasis>precisa</emphasis> sobre
escrever
+ <literal>equals()</literal> e
<literal>hashCode()</literal> para implementar
+ identificadores compostos igualmente. E precisa também implementar
+ <literal>Serializable</literal>.
+ </para>
+
+ <para>
+ Infelizmente, esta solução para um identificador composto significa que
um objeto
+ persistente é seu próprio identificador. Não há outro "handle"
que o próprio objeto.
+ Você mesmo precisa instanciar uma instância de outra classe persistente e
preencher
+ suas propriedades de identificação antes que você possa dar um
<literal>load()</literal>
+ para o estado persistente associado com uma chave composta. Nos chamamos
esta
+ solução de identificador composto
<emphasis>embedded</emphasis> e não aconselhamos
+ para aplicações sérias.
+ </para>
+
+ <para>
+ Uma segunda solução é o que podemos chamar de identificador composto
+ <emphasis>mapped</emphasis> quando a propriedades de
identificação nomeadas dentro do
+ elemento <literal><composite-id></literal>
estão duplicadas tando na classe
+ persistente como em uma classe de identificação separada.
+ </para>
+
+ <programlisting><![CDATA[<composite-id
class="MedicareId" mapped="true">
+ <key-property name="medicareNumber"/>
+ <key-property name="dependent"/>
+</composite-id>]]></programlisting>
+
+ <para>
+ No exemplo, ambas as classes de identificação compostas,
<literal>MedicareId</literal>,
+ e a própria classe entidade tem propriedades nomeadas
<literal>medicareNumber</literal>
+ e <literal>dependent</literal>. A classe identificadora
precisa sobrepor
+ <literal>equals()</literal> e
<literal>hashCode()</literal> e implementar
+ <literal>Serializable</literal>. A desvantagem desta solução
é obvia –
+ duplicação de código.
+ </para>
+
+ <para>
+ Os seguintes atributos ão utilizados para especificar o mapeamento de
+ um identificador composto:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ <literal>mapped</literal> mapped (opcional, valor
default <literal>false
+ </literal>): indica que um identificar composto mapeado é
usado, e que as
+ propriedades de mapeamento contidas refere-se tanto a classe
entidade e
+ a classe de identificação composta.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>class</literal> (opcional, mas requerida
para um identificar composto
+ mapeado): A classe usada como um identificador composto.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Nós iremos descrever uma terceira e as vezes mais conveniente solução,
onde o
+ identificador composto é implementado como uma classe componente na
+ <xref linkend="components-compositeid"/>. Os atributos
descritos abaixo aplicam-se
+ apenas para esta solução:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ <literal>name</literal> (opcional, requerida para
esta solução): Uma
+ propriedade do tipo componente que armazena o identificador
composto
+ (veja capítulo 9)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>access</literal> (opcional - valor default
<literal>property</literal>):
+ A estartégia Hibernate que deve ser utilizada para acessar o
valor da propriedade.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>class</literal> (opcional - valor default
para o tipo de propriedade
+ determiando por reflexão) : A classe componente utilizada como um
identificador
+ composto (veja a próxima sessão).
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Esta terceira solução, um <emphasis>componente de
identificação</emphasis>, é o que nós
+ recomendamos para a maioria das aplicações.
+ </para>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-discriminator"
revision="3">
+ <title>discriminator</title>
+
+ <para>
+ O elemento <literal><discriminator></literal>
é necessário para persistência
+ polimórfica utilizando a estratégia de mapeamento
table-per-class-hierarchy e declara
+ uma coluna discriminadora da tabela. A coluna discriminadora contem
valores de marcação
+ que dizem a camada de persistência qual subclasse instanciar para uma
linha particular.
+ Um restrito conjunto de tipos que podem ser utilizados:
<literal>string</literal>,
+ <literal>character</literal>,
<literal>integer</literal>, <literal>byte</literal>,
+ <literal>short</literal>,
<literal>boolean</literal>,
+ <literal>yes_no</literal>,
<literal>true_false</literal>.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="discriminator1" coords="2 60"/>
+ <area id="discriminator2" coords="3 60" />
+ <area id="discriminator3" coords="4 60" />
+ <area id="discriminator4" coords="5 60" />
+ <area id="discriminator5" coords="6 60" />
+ </areaspec>
+ <programlisting><![CDATA[<discriminator
+ column="discriminator_column"
+ type="discriminator_type"
+ force="true|false"
+ insert="true|false"
+ formula="arbitrary sql expression"
+/>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="discriminator1">
+ <para>
+ <literal>column</literal> (opcional - valor
default <literal>class</literal>)
+ o nome da coluna discriminadora
+ </para>
+ </callout>
+ <callout arearefs="discriminator2">
+ <para>
+ <literal>type</literal> (opcional - valor default
<literal>string</literal>)
+ o nome que indica o tipo Hibernate
+ </para>
+ </callout>
+ <callout arearefs="discriminator3">
+ <para>
+ <literal>force</literal> (opcional - valor
default <literal>false</literal>)
+ "força" o Hibernate a especificar valores
discriminadores permitidos mesmo
+ quando recuperando todas as instancias da classe root.
+ </para>
+ </callout>
+ <callout arearefs="discriminator4">
+ <para>
+ <literal>insert</literal> (opcional - valor
default para <literal>true</literal>)
+ sete isto para <literal>false</literal> se sua
coluna discriminadora é também
+ parte do identificador composto mapeado. (Diz ao Hibernate
para não incluir a
+ coluna em comandos SQL
<literal>INSERT</literal>s).
+ </para>
+ </callout>
+ <callout arearefs="discriminator5">
+ <para>
+ <literal>formula</literal> (opcional) uma
expressão SQL arbitraria que é e
+ xecutada quando um tipo tem que ser avaliado. Permite
discriminação baseada
+ em conteúdo.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ Valores atuais de uma coluna discriminada são especificados pelo atributo
+ <literal>discriminator-value</literal> da
<literal><class></literal>
+ e elementos da <literal><subclass></literal>.
+ </para>
+
+ <para>
+ O atributo <literal>force</literal> é util (apenas) em
tabelas contendo linhas com
+ valores discriminadores "extras" que não estão mapeados para
uma classe persistente.
+ Este não é geralmente o caso.
+ </para>
+
+ <para>
+ Usando o atributo <literal>formula</literal> voce pode
declarar uma expressão SQL
+ arbitrária que sera utilizada para avaliar o tipo de uma linha :
+ </para>
+
+ <programlisting><![CDATA[<discriminator
+ formula="case when CLASS_TYPE in ('a', 'b', 'c') then 0
else 1 end"
+ type="integer"/>]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-version" revision="4">
+ <title>version (optional)</title>
+
+ <para>
+ O elemento <literal><version></literal> é
opcional e indica que a tabela
+ possui dados versionados. Isto é particularmente útil se você planeja
utilizar
+ <emphasis>transações longas</emphasis> (veja abaixo):
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="version1" coords="2 70"/>
+ <area id="version2" coords="3 70"/>
+ <area id="version3" coords="4 70"/>
+ <area id="version4" coords="5 70"/>
+ <area id="version5" coords="6 70"/>
+ <area id="version6" coords="7 70"/>
+ <area id="version7" coords="8 70"/>
+ </areaspec>
+ <programlisting><![CDATA[<version
+ column="version_column"
+ name="propertyName"
+ type="typename"
+ access="field|property|ClassName"
+ unsaved-value="null|negative|undefined"
+ generated="never|always"
+ insert="true|false"
+ node="element-name|@attribute-name|element/(a)attribute|."
+/>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="version1">
+ <para>
+ <literal>column</literal> (opcional - default a a
propriedade name): O nome da
+ coluna mantendo o numero da versão
+ </para>
+ </callout>
+ <callout arearefs="version2">
+ <para>
+ <literal>name</literal>: O nome da propriedade da
classe persistente.
+ </para>
+ </callout>
+ <callout arearefs="version3">
+ <para>
+ <literal>type</literal> (opcional - valor default
para <literal>integer</literal>):
+ O tipo do numero da versão
+ </para>
+ </callout>
+ <callout arearefs="version4">
+ <para>
+ <literal>access</literal> (opcional - valor
default <literal>property</literal>):
+ A estratégia Hibernate que deve ser usada para acessar o
valor da propriedade.
+ </para>
+ </callout>
+ <callout arearefs="version5">
+ <para>
+ <literal>unsaved-value</literal> (opcional –
valor default para <literal>undefined
+ </literal>): Um valor para a propriedade versão que
indica que uma instancia é
+ uma nova instanciada (unsaved), distinguindo de instancias
desconectadas que foram
+ salvas ou carregadas em sessões anteriores.
((<literal>undefined</literal> especifica
+ que o valor da propriedade de identificação deve ser
utilizado).
+ </para>
+ </callout>
+ <callout arearefs="version6">
+ <para>
+ <literal>generated</literal> (optional - defaults
to <literal>never</literal>):
+ Specifies that this version property value is actually
generated by the database.
+ See the discussion of <xref
linkend="mapping-generated">generated properties</xref>.
+ <literal>generated</literal> (opcional - valor
default <literal>never</literal>):
+ Especifica que valor para a propriedade versão é na verdade
gerado pelo banco de
+ dados. Veja a discussão da Seção
+ <xref linkend="mapping-generated">generated
properties</xref>.
+ </para>
+ </callout>
+ <callout arearefs="version7">
+ <para>
+ <literal>insert</literal> (opcional - valor
default para <literal>true</literal>):
+ Especifica se a coluna de versão deve ser incluída no comando
SQL de insert.
+ Pode ser configurado como
<literal>false</literal> se a coluna do banco de dados
+ está definida com um valor default de
<literal>0</literal>.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ Números de versão podem ser dos tipos Hibernate
<literal>long</literal>,
+ <literal>integer</literal>,
<literal>short</literal>, <literal>timestamp</literal> ou
+ <literal>calendar</literal>.
+ </para>
+
+ <para>
+ A versão de uma propriedade timestamp nunca deve ser nula para uma
instancia
+ desconectada, assim o Hibernate irá identificar qualquer instância com
uma versão
+ nula ou timestamp como transiente, não importando qual estratégia para
foi
+ especificada para <literal>unsaved-value</literal>.
<emphasis>Declarando uma versão
+ nula ou a propriedade timestamp é um caminho fácil para tratar problemas
com
+ reconexões transitivas no Hibernate, especialmente úteis para pessoas
utilizando
+ identificadores assinaldados ou chaves compostas!</emphasis>
+ </para>
+ </sect2>
+
+ <sect2 id="mapping-declaration-timestamp" revision="4"
>
+ <title>timestamp (optional)</title>
+
+ <para>
+ O elemento opcional
<literal><timestamp></literal> indica que uma tabela contém
+ dados timestamped. Isso tem por objetivo dar uma alternativa para
versionamento. Timestamps
+ são por natureza uma implementação menos segura do locking otimista.
Entretanto, algumas
+ vezes a aplicação pode usar timestamps em outros caminhos.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="timestamp1" coords="2 70"/>
+ <area id="timestamp2" coords="3 70" />
+ <area id="timestamp3" coords="4 70" />
+ <area id="timestamp4" coords="5 70" />
+ <area id="timestamp5" coords="6 70" />
+ <area id="timestamp6" coords="7 70" />
+ </areaspec>
+ <programlisting><![CDATA[<timestamp
+ column="timestamp_column"
+ name="propertyName"
+ access="field|property|ClassName"
+ unsaved-value="null|undefined"
+ source="vm|db"
+ generated="never|always"
+ node="element-name|@attribute-name|element/(a)attribute|."
+/>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="timestamp1">
+ <para>
+ <literal>column</literal> (opcional - valor
default para a propriedade name):
+ O nome da coluna que mantem o timestamp.
+ </para>
+ </callout>
+ <callout arearefs="timestamp2">
+ <para>
+ <literal>name</literal>: O nome da propriedade no
estilo JavaBeans do
+ tipo <literal>Date</literal> ou
<literal>Timestamp</literal> da classe
+ persistente Java.
+ </para>
+ </callout>
+ <callout arearefs="timestamp3">
+ <para>
+ <literal>access</literal> (opcional - valor
default para <literal>property</literal>):
+ A estretagia Hibernate que deve ser utilizada para acessar o
valor da propriedade.
+ </para>
+ </callout>
+ <callout arearefs="timestamp4">
+ <para>
+ <literal>unsaved-value</literal> (opcional -
valor default <literal>null</literal>):
+ Uma propriedade para a versão de que indica que uma instância
é uma nova instanciada
+ (unsaved), distinguindo-a de instancias desconectadas que
foram salvas ou carregadas
+ em sessões previas. (<literal>undefined</literal>
especifica que um valor de
+ propriedade de identificação deve ser utilizado)
+ </para>
+ </callout>
+ <callout arearefs="timestamp5">
+ <para>
+ <literal>source</literal> (opcional - valor
default para <literal>vm</literal>):
+ De onde o Hibernate deve recuperar o valor timestamp? Do
banco de dados ou da JVM
+ corrente? Timestamps baseados em banco de dados levam a um
overhead porque o
+ Hibernate precisa acessar o banco de dados para determinar o
"próximo valor", mas é
+ mais seguro para uso em ambientes de "cluster".
Observe também, que nem todos
+ <literal>Dialect</literal>s suportam a
recuperação do timestamp corrente do banco
+ de dados, enquando outros podem não ser seguros para
utilização em bloqueios
+ pela falta de precisão (Oracle 8 por exemplo)
+ </para>
+ </callout>
+ <callout arearefs="timestamp6">
+ <para>
+ <literal>generated</literal> (opcional - valor
default <literal>never</literal>):
+ Especifica que o valor da propriedade timestamp é gerado pelo
banco de dados.
+ Veja a discussão <xref
linkend="mapping-generated">generated properties</xref>.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ Observe que <literal><timestamp></literal> é
equivalente a
+ <literal><version
type="timestamp"></literal>. E
+ <literal><timestamp
source="db"></literal> é equivalente a
+ <literal><version
type="dbtimestamp"></literal>.
+ </para>
+ </sect2>
+
+
+ <sect2 id="mapping-declaration-property" revision="4">
+ <title>property</title>
+
+ <para>
+ O elemento <literal><property></literal>
declara uma propriedade
+ persistente de uma classe, no estilo JavaBean.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="property1" coords="2 70"/>
+ <area id="property2" coords="3 70"/>
+ <area id="property3" coords="4 70"/>
+ <areaset id="property4-5" coords="">
+ <area id="property4" coords='5 70'/>
+ <area id="property5" coords='6 70'/>
+ </areaset>
+ <area id="property6" coords="7 70"/>
+ <area id="property7" coords="8 70"/>
+ <area id="property8" coords="9 70"/>
+ <area id="property9" coords="10 70"/>
+ <area id="property10" coords="11 70"/>
+ <area id="property11" coords="12 70"/>
+ <area id="property12" coords="13 70"/>
+ </areaspec>
+ <programlisting><![CDATA[<property
+ name="propertyName"
+ column="column_name"
+ type="typename"
+ update="true|false"
+ insert="true|false"
+ formula="arbitrary SQL expression"
+ 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/(a)attribute|."
+ index="index_name"
+ unique_key="unique_key_id"
+ length="L"
+ precision="P"
+ scale="S"
+/>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="property1">
+ <para>
+ <literal>name</literal>: o nome da propriedade,
iniciando com letra minúscula.
+ </para>
+ </callout>
+ <callout arearefs="property2">
+ <para>
+ <literal>column</literal> (opcional - default
para a propriedade name): o nome
+ da coluna mapeada do banco de dados, Isto pode também ser
especificado pelo(s)
+ elemento(s)
<literal><column></literal> aninhados.
+
+ </para>
+ </callout>
+ <callout arearefs="property3">
+ <para>
+ <literal>type</literal> (opcional): um nome que
indica o tipo Hibernate.
+ </para>
+ </callout>
+ <callout arearefs="property4-5">
+ <para>
+ <literal>update, insert</literal> (opcional -
valor default <literal>true</literal>):
+ especifica que as colunas mapeadas devem ser incluidas nas
instruções SQL de
+ <literal>UPDATE</literal> e/ou
<literal>INSERT</literal> . Setar ambas para to
+ <literal>false</literal> permite uma propridade
"derivada" pura cujo valor é
+ inicializado de outra propriedade que mapeie a mesma
coluna(s) ou por uma trigger
+ ou outra aplicação.
+ </para>
+ </callout>
+ <callout arearefs="property6">
+ <para>
+ <literal>formula</literal> (opcional): uma
expressão SQL que definie o valor para
+ uma propriedade <emphasis>calculada</emphasis>.
Propriedades calculadas nao tem
+ uma coluna de mapeamento para elas.
+ </para>
+ </callout>
+ <callout arearefs="property7">
+ <para>
+ <literal>access</literal> (opcional – valor
default <literal>property</literal>):
+ A estratégia que o Hibernate deve utilizar para acessar o
valor da propriedade
+ </para>
+ </callout>
+ <callout arearefs="property8">
+ <para>
+ <literal>lazy</literal> (opcional - valor default
para <literal>false</literal>):
+ Especifica que esta propriedade deve ser trazida de forma
"lazy" quando a
+ instancia da variável é acessada pela primeira vez (requer
instrumentação
+ bytecode em tempo de criação).
+ </para>
+ </callout>
+ <callout arearefs="property9">
+ <para>
+ <literal>unique</literal> (opcional): Habilita a
geração de DDL de uma
+ unica constraint para as colunas. Assim, permite que isto
seja o
+ alvo de uma <literal>property-ref</literal>.
+ </para>
+ </callout>
+ <callout arearefs="property10">
+ <para>
+ <literal>not-null</literal> (opcional): Habilita
a geração de DDL de uma
+ constraint de nulidade para as colunas.
+ </para>
+ </callout>
+ <callout arearefs="property11">
+ <para>
+ <literal>optimistic-lock</literal> (opcional -
valor default <literal>true</literal>):
+ Especifica se mudanças para esta propriedade requerem ou não
bloqueio otimista.
+ Em outras palavras, determina se um incremento de versão deve
ocorrer quando
+ esta propriedade está suja.
+ </para>
+ </callout>
+ <callout arearefs="property12">
+ <para>
+ <literal>generated</literal> (opcional - valor
default <literal>never</literal>):
+ Especifica que o valor da propriedade é na verdade gerado
pelo banco de dados.
+ Veja a discussão da seção
+ <xref linkend="mapping-generated">generated
properties</xref>.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ <emphasis>typename</emphasis> pode ser:
+ </para>
+
+ <orderedlist spacing="compact">
+ <listitem>
+ <para>
+ The name of a Hibernate basic type (eg. <literal>integer,
string, character,
+ date, timestamp, float, binary, serializable, object,
blob</literal>).
+ O nome do tipo basico do Hibernate (ex., <literal>integer,
string, character,
+ date, timestamp, float, binary, serializable, object,
blob</literal>).
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ O nome da classe Java com um tipo básico default (ex.
<literal>int, float,
+ char, java.lang.String, java.util.Date, java.lang.Integer,
java.sql.Clob</literal>).
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ O nome da classe Java serializable
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ O nome da classe de um tipo customizado (ex.
<literal>com.illflow.type.MyCustomType</literal>).
+ </para>
+ </listitem>
+ </orderedlist>
+
+ <para>
+ Se você não especificar um tipo, o Hibernate ira utilizar reflexão sobre
a
+ propriedade nomeada para ter uma idéia do tipo Hibernate correto. O
Hibernate ira
+ tentar interpretar o nome da classe retornada, usando as regras 2, 3 e 4
nesta ordem.
+ Entretanto, isto não é sempre suficiente Em certos casos, você ainda irá
necessitar
+ do atributo <literal>type</literal>. (Por exemplo, para
distinguir entre
+ <literal>Hibernate.DATE</literal> ou
<literal>Hibernate.TIMESTAMP</literal>,
+ ou para espcificar uma tipo ciustomizado.)
+ </para>
+
+ <para>
+ O atributo <literal>access</literal> permite voce controlar
como o Hibernate irá
+ acessar a propriedade em tempo de execução. Por default, o Hibernate irá
chamar os
+ métodos get/set da propriedades. Se voce especificar
<literal>access="field"</literal>,
+ o Hibernate ira bipassar os metodos get/set, acessnado o campo
diretamente,
+ usando reflexão. Voc epode especificar sua própria estratégia para acesso
da
+ propriedade criando uma classe que implemente a interface
+ <literal>org.hibernate.property.PropertyAccessor</literal>.
+ </para>
+
+ <para>
+ Um recurso especialmente poderoso é o de propriedades derivadas. Estas
propriedades
+ são por definição read-only, e o valor da propriedade é calculado em
tempo de execução.
+ Você declara este calculo como uma expressão SQL, que traduz para
clausula
+ <literal>SELECT</literal> de uma subquery daquery SQL que
carrega a instancia:
+ </para>
+
+ <programlisting><![CDATA[
+<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
)"/>]]></programlisting>
+
+ <para>
+ Observe que você pode referenciar as entidades da própria tabela,
+ através da não declaração de um alias para uma coluna particular (
+ <literal>customerId</literal> no exemplo dado). Observe
tambem que voce pode usar o
+ mapeamento de elemento aninhado
<literal><formula></literal>, se você não
+ gostar de usar o atributo.
+ </para>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-manytoone"
revision="5">
+ <title>many-to-one</title>
+
+ <para>
+ Uma associação ordinária para outra classe persistente é declarada usando
o
+ elemento <literal>many-to-one</literal>. O modelo relacional
é uma
+ associação many-to-one: a uma chave estrangeira de uma tabela
referenciando
+ a chave primaria da tabela destino.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="manytoone1" coords="2 70"/>
+ <area id="manytoone2" coords="3 70"/>
+ <area id="manytoone3" coords="4 70"/>
+ <area id="manytoone4" coords="5 70"/>
+ <area id="manytoone5" coords="6 70"/>
+ <areaset id="manytoone6-7" coords="">
+ <area id="manytoone6" coords='7 70'/>
+ <area id="manytoone7" coords='8 70'/>
+ </areaset>
+ <area id="manytoone8" coords="9 70"/>
+ <area id="manytoone9" coords="10 70"/>
+ <area id="manytoone10" coords="11 70"/>
+ <area id="manytoone11" coords="12 70"/>
+ <area id="manytoone12" coords="13 70"/>
+ <area id="manytoone13" coords="14 70"/>
+ <area id="manytoone14" coords="15 70"/>
+ <area id="manytoone15" coords="16 70"/>
+ <area id="manytoone16" coords="17 70"/>
+ </areaspec>
+ <programlisting><![CDATA[<many-to-one
+ name="propertyName"
+ column="column_name"
+ 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"
+ formula="arbitrary SQL expression"
+ node="element-name|@attribute-name|element/(a)attribute|."
+ embed-xml="true|false"
+ index="index_name"
+ unique_key="unique_key_id"
+ foreign-key="foreign_key_name"
+/>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="manytoone1">
+ <para>
+ <literal>name</literal>: O nome da propriedade.
+ </para>
+ </callout>
+ <callout arearefs="manytoone2">
+ <para>
+ <literal>column</literal> (opcional): O nome da
coluna foreign key. Isto
+ pode também ser especificado através de elementos aninhados
+ <literal><column></literal>.
+ </para>
+ </callout>
+ <callout arearefs="manytoone3">
+ <para>
+ <literal>class</literal> (opcional – default para
o tipo de propriedade
+ determinado pela reflexão). O nome da classe associada.
+ </para>
+ </callout>
+ <callout arearefs="manytoone4">
+ <para>
+ <literal>cascade</literal> (opcional): Especifica
quais operações dever
+ ser em cascata do objeto pai para o objeto associado.
+ </para>
+ </callout>
+ <callout arearefs="manytoone5">
+ <para>
+ <literal>fetch</literal> (opcional - default para
<literal>select</literal>):
+ Escolhe entre recuperação outer-join ou recuperação
seqüencial.
+ </para>
+ </callout>
+ <callout arearefs="manytoone6-7">
+ <para>
+ <literal>update, insert</literal> (opcional -
valor default <literal>true</literal>):
+ especifica que as colunas mapeadas dever ser incluidas em
instruções SQL de
+ <literal>UPDATE</literal> e/ou
<literal>INSERT</literal>. Setando ambas para
+ <literal>false</literal> você permite uma
associação "derivada" pura cujos valores
+ são inicializados de algumas outras propriedades que mapeiam
a mesma coluna ou
+ por uma trigger ou outra aplicação.
+ </para>
+ </callout>
+ <callout arearefs="manytoone8">
+ <para>
+ <literal>property-ref</literal>: (opcional) O
nome da propriedade da classe associada
+ que faz a junção desta foreign key. Se não especificada, a
chave primaria da
+ classe associada será utilizada.
+ </para>
+ </callout>
+ <callout arearefs="manytoone9">
+ <para>
+ <literal>access</literal> (opcional - valor
default <literal>property</literal>): A
+ estrategia que o Hibernate deve utilizar para acessar o valor
da propriedade.
+ </para>
+ </callout>
+ <callout arearefs="manytoone10">
+ <para>
+ <literal>unique</literal> (opcional): Habilita a
geração DDL de uma constraint
+ unique para a coluna foreign-key. Alem disso, permite ser o
alvo de uma
+ <literal>property-ref</literal>. Isso torna a
associação multipla
+ efetivamente um para um.
+ </para>
+ </callout>
+ <callout arearefs="manytoone11">
+ <para>
+ <literal>not-null</literal> (opcional): Habilita
a geração DDL de uma constraint de
+ nulidade para as foreign keys.
+ </para>
+ </callout>
+ <callout arearefs="manytoone12">
+ <para>
+ <literal>optimistic-lock</literal> (opcional -
valor default <literal>true</literal>):
+ Especifica se mudanças desta propriedade requerem ou não
travamento otimista.
+ Em outras palavras, determina se um incremento de versão deve
ocorrer quando
+ esta propriedade está suja.
+ </para>
+ </callout>
+ <callout arearefs="manytoone13">
+ <para>
+ <literal>lazy</literal>(opcional – valor default
<literal>proxy</literal>):
+ Por default, associações de ponto unico são envoltas em um
proxie.
+ <literal>lazy="no-proxy"</literal>
especifica que a propriedade deve ser
+ trazida de forma tardia quando a instancia da variável é
acessada pela
+ primeira vez (requer instrumentação bytecode em tempo de
criação)
+ <literal>lazy="false"</literal>
especifica que a associação será
+ sempre recuperada fortemente.
+ </para>
+ </callout>
+ <callout arearefs="manytoone14">
+ <para>
+ <literal>not-found</literal> (opcional - valor
default <literal>exception</literal>):
+ Especifica como as foreign keys que referenciam linhas
ausentes serão tratadas:
+ <literal>ignore</literal> irá tratar a linha
ausente como ama associaççao de null
+ </para>
+ </callout>
+ <callout arearefs="manytoone15">
+ <para>
+ <literal>entity-name</literal> (opcional): O nome
da entidade da classe associada.
+ </para>
+ </callout>
+ </calloutlist>
+ <callout arearefs="manytoone16">
+ <para>
+ <literal>formula</literal> (optional): Uma
expressão SQL que define um valor
+ para um foreign key
<emphasis>computed</emphasis>.
+ </para>
+ </callout>
+ </programlistingco>
+
+ <para>
+ Setar o valor do atributo <literal>cascade</literal> para
qualquer valor
+ significativo diferente de <literal>none</literal> irá
propagar certas operações
+ ao objeto associado. Os valores significativos são os nomes das operações
básicas
+ do Hibernate, <literal>persist, merge, delete, save-update, evict,
replicate, lock,
+ refresh</literal>, assim como os valores especiais
<literal>delete-orphan</literal>
+ e <literal>all</literal> e combinações de nomes de operações
separadas por vírgula,
+ como por exemplo,
<literal>cascade="persist,merge,evict"</literal> ou
+ <literal>cascade="all,delete-orphan"</literal>.
Veja a seção
+ <xref linkend="objectstate-transitive"/> para uma
explicação completa. Note que
+ associações valoradas simples (associações muitos-pra-um, e um-pra-um)
não suportam
+ orphan delete.
+ </para>
+
+ <para>
+ Uma típica declaração <literal>muitos-pra-um</literal> se
parece com esta:
+ </para>
+
+ <programlisting><![CDATA[<many-to-one name="product"
class="Product" column="PRODUCT_ID"/>]]></programlisting>
+
+ <para>
+ O atributo <literal>property-ref</literal> deve apenas ser
usado para mapear dados
+ legados onde uma chave estrangeira se referencia a uma chave exclusiva da
tabela
+ associada que não seja à chave primária. Este é um modelo relacional
desagradável.
+ Por exemplo, suponha que a classe <literal>Product</literal>
tenha um número
+ seqüencial exclusivo, que não é a chave primária. (O atributo
<literal>unique</literal>
+ controla a geração de DDL do Hibernate com a ferramenta SchemaExport.)
+ </para>
+
+ <programlisting><![CDATA[<property name="serialNumber"
unique="true" type="string"
column="SERIAL_NUMBER"/>]]></programlisting>
+
+ <para>
+ Então o mapeamento para <literal>OrderItem</literal> poderia
usar:
+ </para>
+
+ <programlisting><![CDATA[<many-to-one name="product"
property-ref="serialNumber"
column="PRODUCT_SERIAL_NUMBER"/>]]></programlisting>
+
+ <para>
+ Porém, isto obviamente não é indicado, nunca.
+ </para>
+
+ <para>
+ Se a chave exclusiva referenciada engloba múltiplas propriedades da
entidade associada,
+ você deve mapear as propriedades referenciadas dentro de um elemento
chamado
+ <literal><properties></literal>
+
+ </para>
+
+ <para>
+ Se a chave exclusiva referenciada é a propriedade de um componente, você
pode especificar
+ um caminho para a propriedade.
+ </para>
+
+ <programlisting><![CDATA[<many-to-one name="owner"
property-ref="identity.ssn"
column="OWNER_SSN"/>]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-onetoone" revision="3">
+ <title>one-to-one (um-pra-um)</title>
+
+ <para>
+ Uma associação um-pra-um para outra classe persistente é declarada usando
+ um elemento <literal>one-to-one </literal>.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="onetoone1" coords="2 70"/>
+ <area id="onetoone2" coords="3 70"/>
+ <area id="onetoone3" coords="4 70"/>
+ <area id="onetoone4" coords="5 70"/>
+ <area id="onetoone5" coords="6 70"/>
+ <area id="onetoone6" coords="7 70"/>
+ <area id="onetoone7" coords="8 70"/>
+ <area id="onetoone8" coords="9 70"/>
+ <area id="onetoone9" coords="10 70"/>
+ <area id="onetoone10" coords="11 70"/>
+ </areaspec>
+ <programlisting><![CDATA[<one-to-one
+ name="propertyName"
+ class="ClassName"
+ cascade="cascade_style"
+ constrained="true|false"
+ fetch="join|select"
+ property-ref="propertyNameFromAssociatedClass"
+ access="field|property|ClassName"
+ formula="any SQL expression"
+ lazy="proxy|no-proxy|false"
+ entity-name="EntityName"
+ node="element-name|@attribute-name|element/(a)attribute|."
+ embed-xml="true|false"
+ foreign-key="foreign_key_name"
+/>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="onetoone1">
+ <para>
+ <literal>name</literal>: O nome da propriedade.
+ </para>
+ </callout>
+ <callout arearefs="onetoone2">
+ <para>
+ <literal>class</literal> (opcional – default para
o tipo da propriedade
+ definido via reflection): O nome da classe associada.
+ </para>
+ </callout>
+ <callout arearefs="onetoone3">
+ <para>
+ <literal>cascade</literal> (opcional): Especifica
qual operação deve
+ ser cascateada do objeto pai para o objeto associado.
+ </para>
+ </callout>
+ <callout arearefs="onetoone4">
+ <para>
+ <literal>constrained</literal> (opcional):
Especifica que uma chave estrangeira
+ constraint na chave primária da tabela mapeada referencia a
tabela da classe
+ associada, Esta opção afeta a ordem em queh
<literal>save()</literal> e
+ <literal>delete()</literal> são cascateadas, e
determina se a associação
+ pode ser substituída (isto também é usado pela ferramenta
schema export).
+ </para>
+ </callout>
+ <callout arearefs="onetoone5">
+ <para>
+ <literal>fetch</literal> ((opcional – valor
default <literal>select</literal>):
+ Escolhe entre outer-join fetching ou sequential select
fetching.
+ </para>
+ </callout>
+ <callout arearefs="onetoone6">
+ <para>
+ <literal>property-ref</literal>(opcional): O nome
da propriedade da classe associada
+ que é ligada a chave primária desta classe. Se não for
especificada, a chave primária
+ da classe associada é utilizada.
+ </para>
+ </callout>
+ <callout arearefs="onetoone7">
+ <para>
+ <literal>access</literal> (opcional - valor
default padrão <literal>property</literal>):
+ A estratégia que o Hibernate pode usar para acessar o valor
da propriedade.
+ </para>
+ </callout>
+ <callout arearefs="onetoone8">
+ <para>
+ <literal>formula</literal> (opcional): Quase
todas associações um-pra-um mapeiam
+ para a chave primária da entidade dona. No caso raro, que não
é o caso, você
+ pode especificar uma outra coluna, colunas ou expressões para
juntar utilizando
+ uma formula SQL. (Veja
<literal>org.hibernate.test.onetooneformula</literal>
+ para exemplo).
+ </para>
+ </callout>
+ <callout arearefs="onetoone9">
+ <para>
+ <literal>lazy</literal> (opcional – valor default
<literal>proxy</literal>):
+ Por default, associações single point são proxied.
<literal>lazy="no-proxy"</literal>
+ especifica que a propriedade deve ser fetched lazily quando o
atributo é acessado
+ pela primeira vez (requer build-time bytecode
instrumentation).
+ <literal>lazy="false"</literal>
especifica que a associação vai sempre ser
+ avidamente fetched. <emphasis>Note que se
<literal>constrained="false"</literal>,
+ proxing é impossível e o Hibernate vai ávido fetch a
associação!</emphasis>
+ </para>
+ </callout>
+ <callout arearefs="onetoone10">
+ <para>
+ <literal>entity-name</literal> (opcional): O nome
da entidade da classe associada.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ Existem duas variedades de associações um-pra-um:
+ </para>
+ <itemizedlist>
+ <listitem><para>
+ associações de chave primária
+ </para></listitem>
+ <listitem><para>
+ associações de chave estrangeira exclusiva
+ </para></listitem>
+ </itemizedlist>
+
+ <para>
+ Associações de chave primária não necessitam de uma coluna extra de
tabela; se duas
+ linhas são relacionadas pela associação então as duas linhas da tabela
dividem a mesmo
+ valor da chave primária. Assim, se você quer que dois objetos sejam
relacionados por
+ uma associação de chave primária, você deve ter certeza que eles são
assinados com o
+ mesmo valor identificador!
+ </para>
+
+ <para>
+ Para uma associação de chave primária, adicione os seguintes mapeamentos
em
+ <literal>Employee</literal> e
<literal>Person</literal>, respectivamente.
+ </para>
+
+ <programlisting><![CDATA[<one-to-one name="person"
class="Person"/>]]></programlisting>
+ <programlisting><![CDATA[<one-to-one name="employee"
class="Employee" constrained="true"/>]]></programlisting>
+
+ <para>
+ Agora nós devemos assegurar que as chaves primárias de linhas
relacionadas nas
+ tabelas PERSON e EMPLOYEE são iguais. Nós usamos uma estratégia especial
de geração
+ de identificador do Hibernate chamada
<literal>foreign</literal>:
+ </para>
+
+ <programlisting><![CDATA[<class name="person"
table="PERSON">
+ <id name="id" column="PERSON_ID">
+ <generator class="foreign">
+ <param name="property">employee</param>
+ </generator>
+ </id>
+ ...
+ <one-to-one name="employee"
+ class="Employee"
+ constrained="true"/>
+</class>]]></programlisting>
+
+ <para>
+ Uma nova instância de <literal>Person</literal> salva
recentemente é então assinada
+ com o mesmo valor da chave primária da instância de
<literal>employee</literal> referenciada
+ com a propriedade <literal>employee</literal> daquela
<literal>Person</literal>.
+ </para>
+
+ <para>
+ Alternativamente, uma chave estrangeira com uma unique constraint, de
+ <literal>Employee</literal> para
<literal>Person</literal>, pode ser expressa como:
+ </para>
+
+ <programlisting><![CDATA[<many-to-one name="person"
class="Person" column="PERSON_ID"
unique="true"/>]]></programlisting>
+
+ <para>
+ E esta associação pode ser feita de forma bi-direcional adicionando o
seguinte
+ no mapeamento de <literal>Person</literal>:
+ </para>
+
+ <programlisting><![CDATA[<one-to-one name="employee"
class="Employee"
property-ref="person"/>]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-naturalid">
+ <title>natural-id</title>
+
+ <programlisting><![CDATA[<natural-id
mutable="true|false"/>
+ <property ... />
+ <many-to-one ... />
+ ......
+</natural-id>]]></programlisting>
+
+ <para>
+ Embora nós recomendemos o uso de surrogate keys como chaves primárias,
você deve
+ ainda identificar chaves naturais para todas as entidades. Uma chave
natural é
+ uma propriedade ou combinação de propriedades que é exclusiva e não nula.
Se não
+ pude ser modificada, melhor ainda. Mapeie as propriedades da chave
natural dentro do
+ elemento <literal><natural-id></literal>. O
Hibernate irá gerar a chave
+ exclusiva necessária e as constraints de nullability , e seu mapeamento
será
+ apropriadamente auto documentado.
+ </para>
+
+ <para>
+ Nós recomendamos com enfase que você implemente
<literal>equals()</literal> e
+ <literal>hashCode()</literal> para comparar as propriedades
da chave natural da
+ entidade.
+ </para>
+
+ <para>
+ Este mapeamento não tem o objetivo de uso com entidades com natural
chaves primárias.
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ <literal>mutable</literal> mutable (opcional, valor
default<literal>false</literal>):
+ Por default, propriedades naturais identificadoras são
consideradas imutáveis (constante).
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-component"
revision="2">
+ <title>componente, componente dinâmico</title>
+
+ <para>
+ O elemento<literal><component></literal> mapeia
propriedades de um
+ objeto filho para colunas da tabela de uma classe pai. Componentes podem,
+ um após o outro, declarar suas próprias propriedades, componentes ou
coleções.
+ Veja "Components" abaixo.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="component1" coords="2 45"/>
+ <area id="component2" coords="3 45"/>
+ <area id="component3" coords="4 45"/>
+ <area id="component4" coords="5 45"/>
+ <area id="component5" coords="6 45"/>
+ <area id="component6" coords="7 45"/>
+ <area id="component7" coords="8 45"/>
+ <area id="component8" coords="9 45"/>
+ </areaspec>
+ <programlisting><![CDATA[<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>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="component1">
+ <para>
+ <literal>name</literal>: O nome da propriedade.
+ </para>
+ </callout>
+ <callout arearefs="component2">
+ <para>
+ <literal>class</literal> (opcional – valor
default para o tipo de
+ propriedade determinada por reflection): O nome da classe
(filha) do
+ componente.
+ </para>
+ </callout>
+ <callout arearefs="component3">
+ <para>
+ <literal>insert</literal>: As colunas mapeadas
aparecem nos
+ SQL de <literal>INSERT</literal>s?
+ </para>
+ </callout>
+ <callout arearefs="component4">
+ <para>
+ <literal>update</literal>: As colunas mapeadas
aparecem nos
+ SQL de <literal>UPDATE</literal>s?
+ </para>
+ </callout>
+ <callout arearefs="component5">
+ <para>
+ <literal>access</literal> (opcional – valor
default <literal>property</literal>):
+ A estratégia que o Hibernate pode usar para acessar o valor
da propriedade.
+ </para>
+ </callout>
+ <callout arearefs="component6">
+ <para>
+ <literal>lazy</literal> (opcional - valor default
<literal>false</literal>):
+ Especifica que este componente deve ser fetched lazily quando
o atributo for
+ acessado pela primeira vez (requer build-time bytecode
instrumentation).
+ </para>
+ </callout>
+ <callout arearefs="component7">
+ <para>
+ <literal>optimistic-lock</literal> (opcional
– valor default <literal>true</literal>):
+ Especifica que atualizações para este componente requerem
ou não aquisição
+ de um lock otimista. Em outras palavras, determina se uma
versão de incremento deve
+ ocorrer quando esta propriedade estiver modificada.
+ </para>
+ </callout>
+ <callout arearefs="component8">
+ <para>
+ <literal>unique</literal> (opcional – valor
default <literal>false</literal>):
+ Especifica que existe uma unique constraint em todas as
colunas mapeadas do
+ componente.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ A tag filha <literal><property></literal>
acrescenta a propriedade
+ de mapeamento da classe filha para colunas de uma tabela.
+ </para>
+
+ <para>
+ O elemento <literal><component></literal>
permite um sub-elemento
+ <literal><parent></literal> mapeie uma
propriedade da classe do componente
+ como uma referencia de volta para a entidade que o contém.
+ </para>
+
+ <para>
+ O elemento
<literal><dynamic-component></literal> permite que um
+ <literal>Map</literal> possa ser mapeado como um componente
onde os nomes das
+ propriedades referem-se para as chaves no mapa, veja
+ <xref linkend="components-dynamic"/>.
+ </para>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-properties"
revision="2">
+ <title>propriedades</title>
+
+ <para>
+ O elemento <literal><properties></literal>
permite a definição de um grupo
+ com nome, lógico de propriedades de uma classe. O uso mais importante do
construtor
+ é que este permite uma combinação de propriedades para ser o objetivo de
uma
+ <literal>property-ref</literal>. É também um modo
conveninente para definir uma
+ unique constraint de múltiplas colunas.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="properties1" coords="2 45"/>
+ <area id="properties2" coords="3 45"/>
+ <area id="properties3" coords="4 45"/>
+ <area id="properties4" coords="5 45"/>
+ <area id="properties5" coords="6 45"/>
+ </areaspec>
+ <programlisting><![CDATA[<properties
+ name="logicalName"
+ insert="true|false"
+ update="true|false"
+ optimistic-lock="true|false"
+ unique="true|false"
+>
+
+ <property ...../>
+ <many-to-one .... />
+ ........
+</properties>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="properties1">
+ <para>
+ <literal>name</literal>:: O nome lógico do
agrupamento –
+ <emphasis>não </emphasis> é o nome atual de
propriedade.
+ </para>
+ </callout>
+ <callout arearefs="properties2">
+ <para>
+ <literal>insert</literal>: As colunas mapeadas
aparecem nos
+ SQL de <literal>INSERT</literal>s?
+ </para>
+ </callout>
+ <callout arearefs="properties3">
+ <para>
+ <literal>update</literal>: As colunas mapeadas
aparecem nos
+ SQL de <literal>UPDATE</literal>s?
+ </para>
+ </callout>
+ <callout arearefs="properties4">
+ <para>
+ <literal>optimistic-lock</literal> (opcional
– valor default <literal>true</literal>):
+ Especifica que atualizações para estes componentes
requerem ou não aquisição de um
+ lock otimista. Em outras palavras, determina se uma
versão de incremento deve ocorrer
+ quando estas propriedades estiverem modificadas.
+ </para>
+ </callout>
+ <callout arearefs="properties5">
+ <para>
+ <literal>unique</literal> (opcional – valor
defautl <literal>false</literal>):
+ Especifica que uma unique constraint existe em todas as
colunas mapeadas do componente.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ Por exemplo, se nós temos o seguinte mapeamento de
<literal><properties></literal>:
+ </para>
+
+ <programlisting><![CDATA[<class name="Person">
+ <id name="personNumber"/>
+ ...
+ <properties name="name"
+ unique="true" update="false">
+ <property name="firstName"/>
+ <property name="initial"/>
+ <property name="lastName"/>
+ </properties>
+</class>]]></programlisting>
+
+ <para>
+ Então nós podemos ter uma associação de dados herdados que referem a
esta chave
+ exclusiva da tabela <literal>Person</literal>, ao invés de se
referirem a chave
+ primária:
+ </para>
+
+ <programlisting><![CDATA[<many-to-one name="person"
+ class="Person" property-ref="name">
+ <column name="firstName"/>
+ <column name="initial"/>
+ <column name="lastName"/>
+</many-to-one>]]></programlisting>
+
+ <para>
+ Nós não recomendamos o uso deste tipo de coisa fora do contexto de
mapeamento de
+ dados herdados.
+ </para>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-subclass" revision="4">
+ <title>subclass (subclasse)</title>
+
+ <para>
+ Finalmente, a persistência polimórfica requer a declaração de cada
subclasse
+ da classe de persistência raiz. Para a estratégia de mapeamento
+ table-per-class-hierarchy, a declaração
<literal><subclass></literal>
+ deve ser usada.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="subclass1" coords="2 55"/>
+ <area id="subclass2" coords="3 55"/>
+ <area id="subclass3" coords="4 55"/>
+ <area id="subclass4" coords="5 55"/>
+ </areaspec>
+ <programlisting><![CDATA[<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">
+
+ <property .... />
+ .....
+</subclass>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="subclass1">
+ <para>
+ <literal>name</literal>: O nome de classe
completamente qualificada da subclasse.
+ </para>
+ </callout>
+ <callout arearefs="subclass2">
+ <para>
+ <literal>discriminator-value</literal> (opcional
– valor default o nome da classe):
+ Um valor que distingue subclasses individuais.
+ </para>
+ </callout>
+ <callout arearefs="subclass3">
+ <para>
+ <literal>proxy</literal> (opcional): Especifica a
classe ou interface que
+ usará os proxies de inicialização atrasada.
+ </para>
+ </callout>
+ <callout arearefs="subclass4">
+ <para>
+ <literal>lazy</literal> (opcional, valor default
<literal>true</literal>):
+ Configurar
<literal>lazy="false"</literal> desabilitará o uso de
+ inicialização atrasada.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+ <para>
+ Cada subclasse deve declarar suas próprias propriedades persistentes e
subclasses.
+ As propriedades <literal><version></literal> e
<literal><id></literal>
+ são configuradas para serem herdades da classe raiz. Cada subclasse numa
hierarquia
+ deve definir um único <literal>discriminator-value</literal>.
Se nenhum for
+ especificado, o nome da classe Java completamente qualificada será
usada.
+ </para>
+
+ <para>
+ Para informações sobre mapeamento de heranças, veja o <xref
linkend="inheritance"/>.
+ </para>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-joinedsubclass"
revision="3">
+ <title>joined-subclass</title>
+
+ <para>
+ Alternativamente, cada subclasse pode ser mapeada para sua própria tabela
+ (Estratégia de mapeamento table-per-subclass). O estado herdado é
devolvido
+ por associação com a tabela da superclasse. Nós usamos o elemento
+ <literal><joined-subclass></literal>.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="joinedsubclass1" coords="2 45"/>
+ <area id="joinedsubclass2" coords="3 45"/>
+ <area id="joinedsubclass3" coords="4 45"/>
+ <area id="joinedsubclass4" coords="5 45"/>
+ </areaspec>
+ <programlisting><![CDATA[<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">
+
+ <key .... >
+
+ <property .... />
+ .....
+</joined-subclass>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="joinedsubclass1">
+ <para>
+ <literal>name</literal>: O nome da classe
completamente qualificada da
+ subclasse.
+ </para>
+ </callout>
+ <callout arearefs="joinedsubclass2">
+ <para>
+ <literal>table</literal>: O nome da tabela da
subclasse.
+ </para>
+ </callout>
+ <callout arearefs="joinedsubclass3">
+ <para>
+ <literal>proxy</literal> (opcional): Especifica a
classe ou interface
+ para usar os proxies de recuperação atrasada.
+ </para>
+ </callout>
+ <callout arearefs="joinedsubclass4">
+ <para>
+ <literal>lazy</literal> (opcional, valor default
<literal>true</literal>):
+ Fixanr <literal>lazy="false"</literal>
desabilita o uso recuperação
+ atrasada.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ A coluna discriminator requerida para esta estratégia de mapeamento.
Porém,
+ cada subclasse deve declarar uma coluna de tabela com o identificador do
objeto
+ usando o elemento <literal><key></literal>. O
mapeamento no início do
+ capítulo poderia ser re-escrito assim:
+ </para>
+
+ <programlisting><![CDATA[<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+ "-//Hibernate/Hibernate Mapping DTD//EN"
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<hibernate-mapping package="eg">
+
+ <class name="Cat" table="CATS">
+ <id name="id" column="uid"
type="long">
+ <generator class="hilo"/>
+ </id>
+ <property name="birthdate" type="date"/>
+ <property name="color" not-null="true"/>
+ <property name="sex" not-null="true"/>
+ <property name="weight"/>
+ <many-to-one name="mate"/>
+ <set name="kittens">
+ <key column="MOTHER"/>
+ <one-to-many class="Cat"/>
+ </set>
+ <joined-subclass name="DomesticCat"
table="DOMESTIC_CATS">
+ <key column="CAT"/>
+ <property name="name" type="string"/>
+ </joined-subclass>
+ </class>
+
+ <class name="eg.Dog">
+ <!-- mapping for Dog could go here -->
+ </class>
+
+</hibernate-mapping>]]></programlisting>
+
+ <para>
+ Para informações de mapeamentos de herança, veja <xref
linkend="inheritance"/>.
+ </para>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-unionsubclass"
revision="2">
+ <title>union-subclass</title>
+
+ <para>
+ Uma terceira opção é mapear para tabelas apenas as classes concretas de
uma
+ hierarquia de heranças, (a estratégia table-per-concrete-class) onde cada
tabela
+ define todos os estados persistentes da classe, incluindo estados
herdados.
+ No Hibernate, não é absolutamente necessário mapear explicitamente como
hierarquia
+ de heranças. Você pode simplesmente mapear cada classe com uma declaração
+ <literal><class></literal> separada. Porém, se
você deseja usar associações
+ polimórficas (por exemplo: uma associação para a superclasse de sua
hierarquia),
+ você precisa usar o mapeamento
<literal><union-subclass></literal>.
+
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="unionsubclass1" coords="2 45"/>
+ <area id="unionsubclass2" coords="3 45"/>
+ <area id="unionsubclass3" coords="4 45"/>
+ <area id="unionsubclass4" coords="5 45"/>
+ </areaspec>
+ <programlisting><![CDATA[<union-subclass
+ name="ClassName"
+ table="tablename"
+ proxy="ProxyInterface"
+ lazy="true|false"
+ dynamic-update="true|false"
+ dynamic-insert="true|false"
+ schema="schema"
+ catalog="catalog"
+ extends="SuperclassName"
+ abstract="true|false"
+ persister="ClassName"
+ subselect="SQL expression"
+ entity-name="EntityName"
+ node="element-name">
+
+ <property .... />
+ .....
+</union-subclass>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="unionsubclass1">
+ <para>
+ <literal>name</literal>: O nome da subclasse
completamente qualificada.
+ </para>
+ </callout>
+ <callout arearefs="unionsubclass2">
+ <para>
+ <literal>table</literal>: O nome da tabela da
subclasse.
+ </para>
+ </callout>
+ <callout arearefs="unionsubclass3">
+ <para>
+ <literal>proxy</literal> (optional): Specifies a
class or interface to use
+ for lazy initializing proxies.
+
+ <literal>proxy</literal> (opcional): Especifica a
classe ou interface para usar
+ os proxies de recuperação atrasada.
+ </para>
+ </callout>
+ <callout arearefs="unionsubclass4">
+ <para>
+ <literal>lazy</literal> (optional, defaults to
<literal>true</literal>): Setting
+ <literal>lazy="false"</literal>
disables the use of lazy fetching.
+ <literal>lazy</literal> (opcional, valor default
p<literal>true</literal>):
+ Fixando <literal>lazy="false"</literal>
desabilita o uso da recuperação atrasada.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ A coluna discriminatõria não é requerida para esta estratégia de
mapeamento.
+
+ </para>
+
+ <para>
+ Para informações sobre mapeamentos de herança, veja <xref
linkend="inheritance"/>.
+ </para>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-join" revision="3">
+ <title>join</title>
+
+ <para>
+ Usando o elemento
<literal><join></literal>>, é possível mapear
+ propriedades de uma classe para várias tabelas.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="join1" coords="2 50"/>
+ <area id="join2" coords="3 50"/>
+ <area id="join3" coords="4 50"/>
+ <area id="join4" coords="5 50"/>
+ <area id="join5" coords="6 50"/>
+ <area id="join6" coords="7 50"/>
+ </areaspec>
+ <programlisting><![CDATA[<join
+ table="tablename"
+ schema="owner"
+ catalog="catalog"
+ fetch="join|select"
+ inverse="true|false"
+ optional="true|false">
+
+ <key ... />
+
+ <property ... />
+ ...
+</join>]]></programlisting>
+
+ <calloutlist>
+ <callout arearefs="join1">
+ <para>
+ <literal>table</literal>: O nome da tabela
associada.
+ </para>
+ </callout>
+ <callout arearefs="join2">
+ <para>
+ <literal>schema</literal> (opcional): Sobrepõe o
nome do esquema
+ especificado pelo elemento raiz
<literal><hibernate-mapping></literal>.
+ </para>
+ </callout>
+ <callout arearefs="join3">
+ <para>
+ <literal>catalog</literal> (opcional): Sobrepõe o
nome do catálogo
+ especificado pelo elemento
raiz<literal><hibernate-mapping></literal>.
+ </para>
+ </callout>
+ <callout arearefs="join4">
+ <para>
+ <literal>fetch</literal>(opcional – valor default
<literal>join</literal>): Se setado
+ para <literal>join</literal>, o padrão, o
Hibernate irá usar um inner join para
+ restaurar um <literal>join</literal> definido por
uma classe ou suas subclasses e
+ uma outer join para um <literal>join</literal>
definido por uma subclasse.
+ Se setado para <literal>select</literal>, então o
Hibernate irá usar uma seleção
+ seqüencial para um
<literal><join></literal> definida numa subclasse, que irá
+ ser emitido apenas se uma linha se concentrar para
representar uma instância
+ da subclasse. Inner joins irá ainda ser usado para restaurar
um
+ <literal><join></literal> definido
pela classe e suas superclasses.
+ </para>
+ </callout>
+ <callout arearefs="join5">
+ <para>
+ <literal>inverse</literal> (opcional – valor
default <literal>false</literal>):
+ Se habilitado, o Hibernate não irá tentar inserir ou
atualizar as propriedades
+ definidas por este join.
+ </para>
+ </callout>
+ <callout arearefs="join6">
+ <para>
+ <literal>optional</literal> (opcional – valor
default <literal>false</literal>):
+ Se habilitado, o Hibernate irá inserir uma linha apenas se as
propriedades definidas
+ por esta junção não forem nulas e irá sempre usar uma outer
join para
+ recuperar as propriedades.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ Por exemplo, a informação de endereço para uma pessoa pode ser mapeada
para uma
+ tabela separada (enquanto preservando o valor da semântica de tipos para
+ todas as propriedades):
+ </para>
+
+ <programlisting><![CDATA[<class name="Person"
+ table="PERSON">
+
+ <id name="id" column="PERSON_ID">...</id>
+
+ <join table="ADDRESS">
+ <key column="ADDRESS_ID"/>
+ <property name="address"/>
+ <property name="zip"/>
+ <property name="country"/>
+ </join>
+ ...]]></programlisting>
+
+ <para>
+ Esta característica é útil apenas para modelos de dados legados, nós
recomendamos
+ menos tabelas do que classes e um modelo de domínio bem granulado. Porém,
é
+ útil para ficar trocando entre estratégias de mapeamento de herança
+ numa hierarquia simples, como explicado mais a frente.
+ </para>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-key">
+ <title>key</title>
+
+ <para>
+ Nós vimos que o elemento
<literal><key></literal> surgiu algumas vezes
+ até agora. Ele aparece em qualquer lugar que o elemento pai define uma
junção
+ para a nova tabela, e define a chave estrangeira para a tabela associada,
que
+ referencia a chave primária da tabela original.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="key1" coords="2 50"/>
+ <area id="key2" coords="3 50"/>
+ <area id="key3" coords="4 50"/>
+ <area id="key4" coords="5 50"/>
+ <area id="key5" coords="6 50"/>
+ <area id="key6" coords="7 50"/>
+ </areaspec>
+ <programlisting><![CDATA[<key
+ column="columnname"
+ on-delete="noaction|cascade"
+ property-ref="propertyName"
+ not-null="true|false"
+ update="true|false"
+ unique="true|false"
+/>]]></programlisting>
+
+ <calloutlist>
+ <callout arearefs="key1">
+ <para>.
+ <literal>column</literal> (opcional): O nome da
coluna da chave estrangeira.
+ Isto também pode ser especificado por aninhamento de
elemento(s)
+ <literal><column></literal>.
+ </para>
+ </callout>
+ <callout arearefs="key2">
+ <para>
+ <literal>on-delete</literal> (opcional, valor
default <literal>noaction</literal>):
+ Especifica se a constraint da chave estrangeira no banco de
dados esta
+ habilitada para cascade delete .
+ </para>
+ </callout>
+ <callout arearefs="key3">
+ <para>
+ <literal>property-ref</literal> (opcional):
Especifica que a chave estrangeira
+ se refere a colunas que não são chave primária da tabela
original.
+ (Util para base de dados legadas.)
+ </para>
+ </callout>
+ <callout arearefs="key4">
+ <para>
+ <literal>not-null</literal> (opcional):
Especifica que a coluna da chave
+ estrangeira não aceita valores nulos (isto é implícito em
qualquer momento
+ que a chave estrangeira também fizer parte da chave
primária).
+ </para>
+ </callout>
+ <callout arearefs="key5">
+ <para>
+ <literal>update</literal> (optional): Specifies
that the foreign key should never
+ be updated (this is implied whenever the foreign key is also
part of the primary
+ key).
+ <literal>update</literal> (opcional): Especifica
que a chave estrangeira nunca
+ deve ser atualizada (isto é implícito em qualquer momento que
a chave estrangeira
+ também fizer parte da chave primária).
+ </para>
+ </callout>
+ <callout arearefs="key6">
+ <para>
+ <literal>unique</literal> (opcional): Especifica
que a chave estrangeira deve ter
+ uma constraint unique (sto é implícito em qualquer momento
que a chave estrangeira
+ também fizer parte da chave primária).
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ Nós recomendamos que para sistemas que a performance de delete seja
importante, todas as
+ chaves deve ser definida
<literal>on-delete="cascade"</literal>, e o Hibernate irá usar
+ uma constraint a nível de banco de dados <literal>ON CASCADE
DELETE</literal>, ao invés
+ de muitas instruções <literal>DELETE</literal>. Esteja ciente
que esta característica é
+ um atalho da estratégia usual de optimistic locking do Hibernate para
dados versionados.
+ </para>
+
+ <para>
+ Os atributos <literal>not-null</literal> e
<literal>update</literal> são úteis quando
+ estamos mapeamos uma associação unidirecional um para muitos. Se você
mapear uma
+ asociação unidirecional um para muitos para uma chave estrangeira
non-nullable, você
+ <emphasis>deve</emphasis> declarar a coluna chave usando
+ <literal><key
not-null="true"></literal>.
+ </para>
+
+ </sect2>
+
+ <sect2 id="mapping-column" revision="4">
+ <title>elementos column e formula</title>
+ <para>
+ Qualquer elemento de mapeamente que aceita um atributo
<literal>column</literal> irá
+ aceitar alternativamente um subelemento
<literal><column></literal>. Da mesma forma,
+ <literal>formula</literal> é uma alternativa para o atributo
<literal>formula</literal>.
+ </para>
+
+ <programlisting><![CDATA[<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"/>]]></programlisting>
+
+ <programlisting><![CDATA[<formula>SQL
expression</formula>]]></programlisting>
+
+ <para>
+ O atributo <literal>column</literal> e
<literal>formula</literal> podem até ser combinados
+ dentro da mesma propriedade ou associação mapeando para expressar,
+ por exemplo, associações exóticas.
+ </para>
+
+ <programlisting><![CDATA[<many-to-one
name="homeAddress" class="Address"
+ insert="false" update="false">
+ <column name="person_id" not-null="true"
length="10"/>
+ <formula>'MAILING'</formula>
+</many-to-one>]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-import">
+ <title>import</title>
+
+ <para>
+ Suponha que a sua aplicação tem duas classes persistentes com o mesmo
nome, e você não quer
+ especificar o nome qualificado (do pacote) nas queries do Hibernate. As
Classes devem
+ ser "importadas" explicitamente, de preferência contando com
<literal>auto-import="true"</literal>.
+ Você pode até importar classes e interfaces que não estão explicitamente
mapeadas.
+ </para>
+
+ <programlisting><![CDATA[<import
class="java.lang.Object"
rename="Universe"/>]]></programlisting>
+
+ <programlistingco>
+ <areaspec>
+ <area id="import1" coords="2 40"/>
+ <area id="import2" coords="3 40"/>
+ </areaspec>
+ <programlisting><![CDATA[<import
+ class="ClassName"
+ rename="ShortName"
+/>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="import1">
+ <para>
+ <literal>class</literal>: O nome qualificado (do
pacote) de qualquer classe Java.
+ </para>
+ </callout>
+ <callout arearefs="import2">
+ <para>
+ <literal>rename</literal> (opcional – valor
default, o nome da classe não
+ qualificada): Um nome que pode ser usado numa linguagem de
consulta.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ </sect2>
+
+ <sect2 id="mapping-types-anymapping" revision="2">
+ <title>any</title>
+
+ <para>
+ Existe mais um tipo de propriedade de mapeamento. O elemento de
mapeamento
+ <literal><any></literal> define uma associação
polimórfica para classes de múltiplas tabelas.
+ Este tipo de mapeamento sempre requer mais de uma coluna. A primeira
coluna possui o tipo da entidade
+ associada. A outra coluna que ficou possui o identificador. É impossível
especificar uma restrição
+ de chave estrangeira para este tipo de associação, assim isto claramente
não é visto
+ como um caminho usual para associações (polimórficas) de mapeamento. Você
deve usar este mapeamento
+ apenas em casos muito especiais (exemplo: audit logs, dados de sessão do
usuário, etc).
+
+ </para>
+
+ <para>
+ O atributo <literal>meta-type</literal> permite a aplicação
especificar um tipo adaptado
+ que mapeia valores de colunas de banco de dados para classes
persistentes que tem propriedades
+ identificadoras do tipo especificado através do
<literal>id-type</literal>. Você deve especificar
+ o mapeamento de valores do meta-type para nome de classes.
+ </para>
+
+ <programlisting><![CDATA[<any name="being"
id-type="long" meta-type="string">
+ <meta-value value="TBL_ANIMAL" class="Animal"/>
+ <meta-value value="TBL_HUMAN" class="Human"/>
+ <meta-value value="TBL_ALIEN" class="Alien"/>
+ <column name="table_name"/>
+ <column name="id"/>
+</any>]]></programlisting>
+
+ <programlistingco>
+ <areaspec>
+ <area id="any1" coords="2 50"/>
+ <area id="any2" coords="3 50"/>
+ <area id="any3" coords="4 50"/>
+ <area id="any4" coords="5 50"/>
+ <area id="any5" coords="6 50"/>
+ <area id="any6" coords="7 50"/>
+ </areaspec>
+ <programlisting><![CDATA[<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>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="any1">
+ <para>
+ <literal>name</literal>: o nome da propriedade.
+ </para>
+ </callout>
+ <callout arearefs="any2">
+ <para>
+ <literal>id-type</literal>: o tipo
identificador.
+ </para>
+ </callout>
+ <callout arearefs="any3">
+ <para>
+ <literal>meta-type</literal> (opcional – valor
default <literal>string</literal>):
+ Qualquer tipo que é permitido para um mapeamento
discriminador.
+ </para>
+ </callout>
+ <callout arearefs="any4">
+ <para>
+ <literal>cascade</literal> (opcional – valor
default <literal>none</literal>):
+ o estilo do cascade.
+ </para>
+ </callout>
+ <callout arearefs="any5">
+ <para>
+ <literal>access</literal> (opcional – valor
default <literal>property</literal>):
+ A estratégia que o hibernate deve usar para acessar o valor
da propriedade.
+ </para>
+ </callout>
+ <callout arearefs="any6">
+ <para>
+ <literal>optimistic-lock</literal> (opcional -
valor default<literal>true</literal>):
+ Especifica que as atualizações para esta propriedade requerem
ou não aquisição da
+ trava otimista. Em outras palavras, define se uma versão de
incremento deve ocorrer
+ se esta propriedade está modificada.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ </sect2>
+
+ </sect1>
+
+ <sect1 id="mapping-types">
+ <title>Tipos do Hibernate</title>
+
+ <sect2 id="mapping-types-entitiesvalues" revision="1">
+ <title>Entidades e valores</title>
+
+ <para>
+ Para entender o comportamento de vários objetos em nível de linguagem de
Java a
+ respeito do serviço de persistência, nós precisamos classificá-los em
dois grupos.
+ </para>
+
+ <para>
+ Uma <emphasis>entidade </emphasis> existe independentemente
de qualquer outro
+ objeto guardando referências para a entidade. Em contraste com o modelo
usual de
+ Java que um objeto não referenciado é coletado pelo garbage collector.
Entidades
+ devem ser explicitamente salvas ou deletada (exceto em operações de
salvamento
+ ou deleção que possam ser executada em
<emphasis>cascata</emphasis> de uma entidade
+ pai para seus filhos). Isto é diferente do modelo ODMG de persistência do
objeto
+ por acessibilidade – e corresponde quase a como objetos de aplicações são
+ geralmente usados em grandes sistemas. Entidades suportam referências
circulares
+ e comuns. Eles podem ser versionadas.
+ </para>
+
+ <para>
+ Uma entidade em estado persistente consiste de referências para outras
entidades
+ e instâncias de tipos de <emphasis>valor</emphasis>. Valores
são primitivos,
+ coleções (não o que tem dentro de uma coleção), componentes e certos
objetos
+ imutáveis. Entidades distintas, valores (em coleções e componentes
particulares)
+ <emphasis>são </emphasis> persistidos e apagados por
acessibilidade. Visto que
+ objetos value (e primitivos) são persistidos e apagados junto com as
entidades
+ que os contém e não podem ser versionados independentemente. Valores têm
+ identidade não independente, assim eles não podem ser comuns para duas
+ entidades ou coleções.
+
+ </para>
+
+ <para>
+ Até agora, nós estivemos usando o termo "classe persistente"
para referir
+ a entidades. Nós iremos continuar a fazer isto. Falando a rigor, porém,
nem todas
+ as classes definidas pelo usuário com estados persistentes são entidades.
Um
+ <emphasis>componente</emphasis> é uma classe de usuário
definida com valores
+ semânticos. Uma propriedade de Java de tipo
<literal>java.lang.String</literal>
+ também tem um valor semêntico. Dada esta definição, nós podemos dizer que
+ todos os tipos (classes) fornecida pelo JDK tem tipo de valor semântico
em Java,
+ enquanto que tipos definidos pelo usuário pode ser mapeados com entidade
ou valor
+ de tipo semântico. Esta decisão pertence ao desenvolvedor da aplicação.
Uma boa
+ dica para uma classe entidade em um modelo de domínio são referências
comuns
+ para uma instância simples daquela classe, enquanto a composição ou
agregação
+ geralmente se traduz para um valor de tipo.
+ </para>
+
+ <para>
+ Nós iremos rever ambos os conceitos durante toda a documentação.
+
+ </para>
+
+ <para>
+ O desafio pe mapear o sistema de tipo de Java (e a definição do
desenvolvedor de
+ entidades e tipos de valor) para o sistema de tipo SQL/banco de dados. A
ponte entre ambos
+ os sistemas é fornecido pelo Hibernate: para entidades que usam
+ <literal><class></literal>,
<literal><subclass></literal> e assim por diante.
+ Para tipos de valores nós usamos
<literal><property></literal>,
+ <literal><component></literal>, etc, geralmente
com um atributo
+ <literal>type</literal>. O valor deste atributo é o nome de
um <emphasis>tipo de
+ mapeamento</emphasis> do Hibernate. O Hibernate fornece muitos
mapeamentos
+ (para tipos de valores do JDK padrão) ut of the box. Você pode escrever
os seus
+ próprios tipos de mapeamentos e implementar sua estratégia de conversão
adaptada,
+ como você verá adiante.
+ </para>
+
+ <para>
+ Todos os tipos internos do hibernate exceto coleções suportam semânticas
nulas.
+
+ </para>
+
+ </sect2>
+
+ <sect2 id="mapping-types-basictypes" revision="3">
+ <title>Valores de tipos básicos</title>
+
+ <para>
+ O tipos internos de mapeamentos básicos podem ser a grosso modo
categorizado como:
+ <variablelist>
+ <varlistentry>
+ <term><literal>integer, long, short, float, double,
character, byte,
+ boolean, yes_no, true_false</literal></term>
+ <listitem>
+ <para>
+ Tipos de mapeamentos de classes primitivas ou wrapper
Java especificos
+ (vendor-specific) para tipos de coluna SQL. Boolean,
+ <literal>boolean, yes_no</literal> são todas
codificações alternativas
+ para um <literal>boolean</literal> ou
<literal>java.lang.Boolean</literal>
+ do Java.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>string</literal></term>
+ <listitem>
+ <para>
+ Um tipo de mapeamento de
<literal>java.lang.String</literal> para
+ <literal>VARCHAR</literal> (ou
<literal>VARCHAR2</literal> no Oracle).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>date, time,
timestamp</literal></term>
+ <listitem>
+ <para>
+ Tipos de mapeamento de
<literal>java.util.Date</literal> e suas
+ subclasses para os tipos SQL
<literal>DATE</literal>,
+ <literal>TIME</literal> e
<literal>TIMESTAMP</literal>
+ (ou equivalente).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>calendar,
calendar_date</literal></term>
+ <listitem>
+ <para>
+ Tipo de mapeamento de
<literal>java.util.Calendar</literal> para
+ os tipos SQL <literal>TIMESTAMP</literal> e
+ <literal>DATE</literal> (ou equivalente).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>big_decimal,
big_integer</literal></term>
+ <listitem>
+ <para>
+ Tipo de mapeamento de
<literal>java.math.BigDecimal</literal> and
+ <literal>java.math.BigInteger</literal> para
<literal>NUMERIC</literal>
+ (ou <literal>NUMBER</literal> no Oracle).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>locale, timezone,
currency</literal></term>
+ <listitem>
+ <para>
+ Tipos de mapeamentos de
<literal>java.util.Locale</literal>,
+ <literal>java.util.TimeZone</literal> e
<literal>java.util.Currency</literal>
+ para <literal>VARCHAR</literal> (ou
<literal>VARCHAR2</literal> no Oracle).
+ Instâncias de f <literal>Locale</literal> e
<literal>Currency</literal>
+ são mapeados para seus códigos ISO. Instâncias de
<literal>TimeZone</literal>
+ são mapeados para seu <literal>ID</literal>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>class</literal></term>
+ <listitem>
+ <para>
+ um tipo de mapeamento de
<literal>java.lang.Class</literal> para
+ <literal>VARCHAR</literal> (ou
<literal>VARCHAR2</literal> no
+ Oracle). Uma <literal>Class</literal> é
mapeada pelo
+ seu nome qualificado (completo).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>binary</literal></term>
+ <listitem>
+ <para>
+ Mapeia arrays de bytes para um tipo binário de SQL
apropriado.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>text</literal></term>
+ <listitem>
+ <para>
+ Maps long Java strings to a SQL
<literal>CLOB</literal> or
+ <literal>TEXT</literal> type.
+ Mapeia strings longas de Java para um tipo SQL
+ <literal>CLOB</literal> ou
<literal>TEXT</literal>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+
<term><literal>serializable</literal></term>
+ <listitem>
+ <para>
+ Mapeia tipos Java serializáveis para um tipo binário SQL
apropriado.
+ Você pode também indicar o tipo
<literal>serializable</literal> do
+ Hibernate com o nome da classe ou interface Java
serializável que
+ não é padrão para um tipo básico.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>clob,
blob</literal></term>
+ <listitem>
+ <para>
+ Tipos de mapeamentos para as classes JDBC
<literal>java.sql.Clob</literal> and
+ <literal>java.sql.Blob</literal>. Estes tipos
podem ser inconveniente para
+ algumas aplicações, visto que o objeto blob ou clob pode
não ser reusado
+ fora de uma transação. (Além disso, o suporte de driver é
imcompleto e
+ inconsistente.)
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ <literal>imm_date, imm_time, imm_timestamp,
imm_calendar, imm_calendar_date,
+ imm_serializable, imm_binary</literal>
+ </term>
+ <listitem>
+ <para>
+ Mapeando tipos para o que geralmente são consideradas
tipos mutáveis de
+ Java, onde o Hibernate faz determinadas otimizações
apropriadas somente
+ para tipos imutáveis de Java, e a aplicação trata o
objeto como imutável.
+ Por exemplo, você não deve chamar
<literal>Date.setTime()</literal> para
+ uma instância mapeada como
<literal>imm_timestamp</literal>. Para mudar
+ o valor da propriedade, e ter a mudança feita
persistente, a aplicação
+ deve atribuir um novo objeto (nonidentical) à
propriedade.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </para>
+
+ <para>
+ Identificadores únicos das entidades e coleções podem ser de qualquer
tipo
+ básico exceto <literal>binary</literal>,
<literal>blob</literal> ou
+ <literal>clob</literal>. (Identificadores compostos também
são permitidos,
+ veja abaixo.)
+ </para>
+
+ <para>
+ Os tipos de valores básicos têm suas constantes
<literal>Type</literal>
+ correspondentes definidas em
<literal>org.hibernate.Hibernate</literal>. Por exemplo,
+ <literal>Hibernate.STRING</literal> representa o tipo
<literal>string</literal>.
+ </para>
+
+ </sect2>
+
+ <sect2 id="mapping-types-custom" revision="2">
+ <title>Tipos de valores personalizados</title>
+
+ <para>
+ É relativamente fácil para desenvolvedores criar seus próprios tipos de
valor.
+ Por exemplo, você pode querer persistir propriedades do tipo
+ <literal>java.lang.BigInteger</literal> para colunas
<literal>VARCHAR</literal>. O
+ Hibernate não fornece um tipo correspondente para isso. Mas os tipos
adaptados
+ não são limitados a mapeamento de uma propriedade (ou elemento de
coleção) a uma
+ única coluna da tabela. Assim, por exemplo, você pôde ter uma propriedade
Java
+
<literal>getName()</literal>/<literal>setName()</literal> do tipo
+ <literal>java.lang.String</literal> que é persistido para
colunas
+ <literal>FIRST_NAME</literal>,
<literal>INITIAL</literal>, <literal>SURNAME</literal>.
+
+ </para>
+
+ <para>
+ Para implementar um tipo personalizado, implemente
<literal>org.hibernate.UserType</literal>
+ or <literal>org.hibernate.CompositeUserType</literal> e
declare propriedades usando o nome
+ qualificado da classe do tipo. Veja
<literal>org.hibernate.test.DoubleStringType</literal>
+ para ver o tipo das coisas que são possíveis.
+ </para>
+
+ <programlisting><![CDATA[<property name="twoStrings"
type="org.hibernate.test.DoubleStringType">
+ <column name="first_string"/>
+ <column name="second_string"/>
+</property>]]></programlisting>
+
+ <para>
+ Observe o uso da tag
<literal><column></literal> para mapear uma propriedade
+ para colunas múltiplas.
+ </para>
+
+ <para>
+ As interfaces <literal>CompositeUserType</literal>,
<literal>EnhancedUserType</literal>,
+ <literal>UserCollectionType</literal>, e
<literal>UserVersionType</literal>
+ fornecem suporte para usos mais especializados.
+ </para>
+
+ <para>
+ Você pode mesmo fornecer parâmetros a um
<literal>UserType</literal> no arquivo de mapeamento.
+ Para isto, seu <literal>UserType</literal> deve implementar a
interface
+ <literal>org.hibernate.usertype.ParameterizedType</literal>.
Para fornecer parâmetros a seu
+ tipo personalizado, você pode usar o elemento
<literal><type></literal> em seus
+ arquivos de mapeamento.
+ </para>
+
+ <programlisting><![CDATA[<property name="priority">
+ <type name="com.mycompany.usertypes.DefaultValueIntegerType">
+ <param name="default">0</param>
+ </type>
+</property>]]></programlisting>
+
+ <para>
+ O <literal>UserType</literal> pode agora recuperar o valor
para o parâmetro chamado
+ <literal>default</literal> da
<literal>Propriedade</literal> do passado a ele.
+ </para>
+
+ <para>
+ Se você usar freqüentemente um determinado
<literal>UserType</literal>, pode ser útil definir
+ um nome mais curto para ele. Você pode fazer isto usando o elemento
+ <literal><typedef></literal>. Typedefs atribui
um nome a um tipo personalizado, e pode também
+ conter uma lista de valores default de parâmetro se o tipo for
parametrizado.
+ </para>
+
+ <programlisting><![CDATA[<typedef
class="com.mycompany.usertypes.DefaultValueIntegerType"
name="default_zero">
+ <param name="default">0</param>
+</typedef>]]></programlisting>
+
+ <programlisting><![CDATA[<property name="priority"
type="default_zero"/>]]></programlisting>
+
+ <para>
+ It is also possible to override the parameters supplied in a typedef on a
case-by-case basis
+ by using type parameters on the property mapping.
+ </para>
+
+ <para>
+ Even though Hibernate's rich range of built-in types and support for
components means you
+ will very rarely <emphasis>need</emphasis> to use a custom
type, it is nevertheless
+ considered good form to use custom types for (non-entity) classes that
occur frequently
+ in your application. For example, a
<literal>MonetaryAmount</literal> class is a good
+ candidate for a <literal>CompositeUserType</literal>, even
though it could easily be mapped
+ as a component. One motivation for this is abstraction. With a custom
type, your mapping
+ documents would be future-proofed against possible changes in your way of
representing
+ monetary values.
+ </para>
+
+ </sect2>
+
+ </sect1>
+
+ <sect1 id="mapping-entityname">
+ <title>Mapping a class more than once</title>
+ <para>
+ It is possible to provide more than one mapping for a particular persistent
class. In this
+ case you must specify an <emphasis>entity name</emphasis> do
disambiguate between instances
+ of the two mapped entities. (By default, the entity name is the same as the
class name.)
+ Hibernate lets you specify the entity name when working with persistent
objects, when writing
+ queries, or when mapping associations to the named entity.
+ </para>
+
+ <programlisting><![CDATA[<class name="Contract"
table="Contracts"
+ entity-name="CurrentContract">
+ ...
+ <set name="history" inverse="true"
+ order-by="effectiveEndDate desc">
+ <key column="currentContractId"/>
+ <one-to-many entity-name="HistoricalContract"/>
+ </set>
+</class>
+
+<class name="Contract" table="ContractHistory"
+ entity-name="HistoricalContract">
+ ...
+ <many-to-one name="currentContract"
+ column="currentContractId"
+ entity-name="CurrentContract"/>
+</class>]]></programlisting>
+
+ <para>
+ Notice how associations are now specified using
<literal>entity-name</literal> instead of
+ <literal>class</literal>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="mapping-quotedidentifiers">
+ <title>SQL quoted identifiers</title>
+ <para>
+ You may force Hibernate to quote an identifier in the generated SQL by
enclosing the table or
+ column name in backticks in the mapping document. Hibernate will use the
correct quotation
+ style for the SQL <literal>Dialect</literal> (usually double
quotes, but brackets for SQL
+ Server and backticks for MySQL).
+ </para>
+
+ <programlisting><![CDATA[<class name="LineItem"
table="`Line Item`">
+ <id name="id" column="`Item Id`"/><generator
class="assigned"/></id>
+ <property name="itemNumber" column="`Item #`"/>
+ ...
+</class>]]></programlisting>
+
+ </sect1>
+
+
+ <sect1 id="mapping-alternatives">
+ <title>Metadata alternatives</title>
+
+ <para>
+ XML isn't for everyone, and so there are some alternative ways to define O/R
mapping metadata in Hibernate.
+ </para>
+
+ <sect2 id="mapping-xdoclet">
+ <title>Using XDoclet markup</title>
+
+ <para>
+ Many Hibernate users prefer to embed mapping information directly in
sourcecode using
+ XDoclet <literal>(a)hibernate.tags</literal>. We will not cover
this approach in this
+ document, since strictly it is considered part of XDoclet. However, we
include the
+ following example of the <literal>Cat</literal> class with
XDoclet mappings.
+ </para>
+
+ <programlisting><![CDATA[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"
+ */
+ public float getWeight() {
+ return weight;
+ }
+ void setWeight(float weight) {
+ this.weight = weight;
+ }
+
+ /**
+ * @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;
+ }
+}]]></programlisting>
+
+ <para>
+ See the Hibernate web site for more examples of XDoclet and Hibernate.
+ </para>
+
+ </sect2>
+
+ <sect2 id="mapping-annotations" revision="2">
+ <title>Using JDK 5.0 Annotations</title>
+
+ <para>
+ JDK 5.0 introduced XDoclet-style annotations at the language level, type-safe
and
+ checked at compile time. This mechnism is more powerful than XDoclet
annotations and
+ better supported by tools and IDEs. IntelliJ IDEA, for example, supports
auto-completion
+ and syntax highlighting of JDK 5.0 annotations. The new revision of the EJB
specification
+ (JSR-220) uses JDK 5.0 annotations as the primary metadata mechanism for
entity beans.
+ Hibernate3 implements the <literal>EntityManager</literal> of
JSR-220 (the persistence API),
+ support for mapping metadata is available via the <emphasis>Hibernate
Annotations</emphasis>
+ package, as a separate download. Both EJB3 (JSR-220) and Hibernate3 metadata
is supported.
+ </para>
+
+ <para>
+ This is an example of a POJO class annotated as an EJB entity bean:
+ </para>
+
+ <programlisting><![CDATA[@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;
+
+ // Getter/setter and business methods
+}]]></programlisting>
+
+ <para>
+ Note that support for JDK 5.0 Annotations (and JSR-220) is still work in
progress and
+ not completed. Please refer to the Hibernate Annotations module for more
details.
+ </para>
+
+ </sect2>
+ </sect1>
+
+ <sect1 id="mapping-generated" revision="1">
+ <title>Generated Properties</title>
+ <para>
+ Generated properties are properties which have their values generated by the
+ database. Typically, Hibernate applications needed to
<literal>refresh</literal>
+ objects which contain any properties for which the database was generating
values.
+ Marking properties as generated, however, lets the application delegate this
+ responsibility to Hibernate. Essentially, whenever Hibernate issues an SQL
INSERT
+ or UPDATE for an entity which has defined generated properties, it
immediately
+ issues a select afterwards to retrieve the generated values.
+ </para>
+ <para>
+ Properties marked as generated must additionally be non-insertable and
non-updateable.
+ Only <xref
linkend="mapping-declaration-version">versions</xref>,
+ <xref
linkend="mapping-declaration-timestamp">timestamps</xref>, and
+ <xref linkend="mapping-declaration-property">simple
properties</xref> can be marked as
+ generated.
+ </para>
+ <para>
+ <literal>never</literal> (the default) - means that the given property
value
+ is not generated within the database.
+ </para>
+ <para>
+ <literal>insert</literal> - states that the given property value is
generated on
+ insert, but is not regenerated on subsequent updates. Things like created-date
would
+ fall into this category. Note that even thought
+ <xref linkend="mapping-declaration-version">version</xref>
and
+ <xref
linkend="mapping-declaration-timestamp">timestamp</xref> properties
can
+ be marked as generated, this option is not available there...
+ </para>
+ <para>
+ <literal>always</literal> - states that the property value is generated
both
+ on insert and on update.
+ </para>
+ </sect1>
+
+ <sect1 id="mapping-database-object">
+ <title>Auxiliary Database Objects</title>
+ <para>
+ Allows CREATE and DROP of arbitrary database objects, in conjunction with
+ Hibernate's schema evolution tools, to provide the ability to fully
define
+ a user schema within the Hibernate mapping files. Although designed
specifically
+ for creating and dropping things like triggers or stored procedures, really
any
+ SQL command that can be run via a
<literal>java.sql.Statement.execute()</literal>
+ method is valid here (ALTERs, INSERTS, etc). There are essentially two modes
for
+ defining auxiliary database objects...
+ </para>
+ <para>
+ The first mode is to explicitly list the CREATE and DROP commands out in the
mapping
+ file:
+ </para>
+ <programlisting><![CDATA[<hibernate-mapping>
+ ...
+ <database-object>
+ <create>CREATE TRIGGER my_trigger ...</create>
+ <drop>DROP TRIGGER my_trigger</drop>
+ </database-object>
+</hibernate-mapping>]]></programlisting>
+ <para>
+ The second mode is to supply a custom class which knows how to construct the
+ CREATE and DROP commands. This custom class must implement the
+ <literal>org.hibernate.mapping.AuxiliaryDatabaseObject</literal>
interface.
+ </para>
+ <programlisting><![CDATA[<hibernate-mapping>
+ ...
+ <database-object>
+ <definition class="MyTriggerDefinition"/>
+ </database-object>
+</hibernate-mapping>]]></programlisting>
+ <para>
+ Additionally, these database objects can be optionally scoped such that they
only
+ apply when certain dialects are used.
+ </para>
+ <programlisting><![CDATA[<hibernate-mapping>
+ ...
+ <database-object>
+ <definition class="MyTriggerDefinition"/>
+ <dialect-scope name="org.hibernate.dialect.Oracle9Dialect"/>
+ <dialect-scope name="org.hibernate.dialect.OracleDialect"/>
+ </database-object>
+</hibernate-mapping>]]></programlisting>
+ </sect1>
+</chapter>
+
Modified: core/trunk/documentation/manual/pt-BR/src/main/docbook/content/batch.xml
===================================================================
--- core/trunk/documentation/manual/pt-BR/src/main/docbook/content/batch.xml 2007-10-26
00:46:38 UTC (rev 14135)
+++ core/trunk/documentation/manual/pt-BR/src/main/docbook/content/batch.xml 2007-10-26
00:48:48 UTC (rev 14136)
@@ -1,360 +1,364 @@
<?xml version='1.0' encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="batch">
- <title>Processamento de lotes</title>
-
- <para>
- Uma alternativa para inserir 100.000 linhas no banco de dados usando o Hibernate
- pode ser a seguinte:
- </para>
-
-<programlisting><![CDATA[Session session = sessionFactory.openSession();
-Transaction tx = session.beginTransaction();
-for ( int i=0; i<100000; i++ ) {
- Customer customer = new Customer(.....);
- session.save(customer);
-}
-tx.commit();
-session.close();]]></programlisting>
-
- <para>
- Isto irá falhar em algum lugar próximo a linha 50.000, lançando uma
- <literal>OutOfMemoryException</literal>. Isso ocorre devido ao fato
do Hibernate
- fazer cache de todas as instâncias de <literal>Customer</literal>
inseridas num
- cachê em nível de sessão.
- </para>
-
- <para>
- Neste capítulo veremos como contornar esse problema. Entretanto, se você vai
realizar
- processamento de lotes, é muito importante que você habilite o uso de lotes JDBC,
se
- você pretende obter um desempenho razoável. Defina o tamanho do lote JDBC em um
- valor razoável (algo entre 10-50):
- </para>
-
-<programlisting><![CDATA[hibernate.jdbc.batch_size
20]]></programlisting>
-
- <para>
- Você também pode querer rodar esse tipo de processamento de lotes com o cache
- secundário completamente desabilitado:
- </para>
-
-<programlisting><![CDATA[hibernate.cache.use_second_level_cache
false]]></programlisting>
-
- <para>
- Mas isto não é absolutamente necessário, desde que nós possamos ajustar o
- <literal>CacheMode</literal> para desabilitar a interação com o
cache secundário.
- </para>
-
- <sect1 id="batch-inserts">
- <title>Inserção de lotes</title>
-
- <para>
- Quando você estiver inserindo novos objetos persistentes, vocês deve executar
- os métodos <literal>flush()</literal> e
<literal>clear()</literal> regularmente
- na sessão, para controlar o tamanho do cache primário.
- </para>
-
-<programlisting><![CDATA[Session session = sessionFactory.openSession();
-Transaction tx = session.beginTransaction();
-
-for ( int i=0; i<100000; i++ ) {
- Customer customer = new Customer(.....);
- session.save(customer);
- if ( i % 20 == 0 ) { //20, same as the JDBC batch size
- //flush a batch of inserts and release memory:
- session.flush();
- session.clear();
- }
-}
-
-tx.commit();
-session.close();]]></programlisting>
-
- </sect1>
-
- <sect1 id="batch-update" >
- <title>Batch updates</title>
-
- <para>
- Para recuperar e atualizar informações a mesma idéia é válida.
Adicionalmente,
- pode precisar usar o <literal>scroll()</literal> para usar
recursos no lado
- do servidor em queries que retornam muita informação.
- </para>
-
-<programlisting><![CDATA[Session session = sessionFactory.openSession();
-Transaction tx = session.beginTransaction();
-
-ScrollableResults customers = session.getNamedQuery("GetCustomers")
- .setCacheMode(CacheMode.IGNORE)
- .scroll(ScrollMode.FORWARD_ONLY);
-int count=0;
-while ( customers.next() ) {
- Customer customer = (Customer) customers.get(0);
- customer.updateStuff(...);
- if ( ++count % 20 == 0 ) {
- //flush a batch of updates and release memory:
- session.flush();
- session.clear();
- }
-}
-
-tx.commit();
-session.close();]]></programlisting>
-
- </sect1>
-
- <sect1 id="batch-statelesssession">
- <title>A interface StatelessSession</title>
- <para>
- Alternativamente, o Hibernate provê uma API orientada à comandos, usada para
- transmitir um fluxo de dados de e para o banco de dados na forma de objetos
soltos.
- Uma <literal>StatelessSession</literal> não tem um contexto
persistente associado e
- não fornece muito das semânticas de alto nível para controle do ciclo de
vida.
- Em especial, uma StatelessSession não implemente o cache primário e nem
interage
- com o cache secundário ou query cache. Ele não implementa salvamento
transacional
- automatico ou checagem automática de mudanças. Operação realizadas usando uma
- StatelessSession não fazem nenhum tipo de cascade com as instancias
associadas.
- As coleções são ignoradas por uma StatelessSession. Operações realizadas com
um
- StatelessSession ignoram a arquitetura de eventos e os interceptadores.
- StatelessSession são vulneráveis aos efeitos do aliasing dos dados, devido a
- falta do cache primário. Uma StatelessSession é uma abstração de baixo nível,
- muito mais próxima do JDBC.
- </para>
-
-<programlisting><![CDATA[StatelessSession session =
sessionFactory.openStatelessSession();
-Transaction tx = session.beginTransaction();
-
-ScrollableResults customers = session.getNamedQuery("GetCustomers")
- .scroll(ScrollMode.FORWARD_ONLY);
-while ( customers.next() ) {
- Customer customer = (Customer) customers.get(0);
- customer.updateStuff(...);
- session.update(customer);
-}
-
-tx.commit();
-session.close();]]></programlisting>
-
- <para>
- Veja neste exempo, as instancias de <literal>Customer</literal>
retornadas pela query
- são imediatamente desvinculadas. Elas nunca serão assossiadas à um contexto
persistente.
- </para>
-
- <para>
- As operações <literal>insert(), update()</literal> e
<literal>delete()</literal>
- definidos pela interface <literal>StatelessSession</literal> são
considerados
- operações diretas no banco de dados (row-level operations), isso resulta em
uma
- execução imediata de comandos SQL <literal>INSERT,
UPDATE</literal> ou
- <literal>DELETE</literal> respectivamente. Devido a isso, eles
possuem uma
- semântica bem diferente das operações <literal>save(),
saveOrUpdate()</literal>
- ou <literal>delete()</literal> definidas na interface
<literal>Session</literal>.
- </para>
-
- </sect1>
-
- <sect1 id="batch-direct" revision="3">
- <title>Operações no estilo DML</title>
-
- <para>
- Como já discutido, mapeamento objeto/relacional automático e transparente é
conseguido
- com a gerência do estado do objeto. Com isto o estado daquele objeto fica
disponível na
- memória, manipulando(usando as expressões SQL <literal>Data
Manipulation Language</literal>
- (SQL-style DML): <literal>INSERT</literal>,
<literal>UPDATE</literal>, <literal>DELETE</literal>)
- os dados diretamente no banco de dados não irá afetar o estado registrado em
memória.
- Entretanto, o Hibernate provê métodos para executar queries SQL-style DML,
que são
- totalmente executas com HQL (Hibernate Query Language)
- (<xref linkend="queryhql">HQL</xref>).
- </para>
-
- <para>
- A pseudo-sintaxe para expressões <literal>UPDATE</literal> e
<literal>DELETE</literal> é:
- <literal>( UPDATE | DELETE ) FROM? NomeEntidade (WHERE
condições_where)?</literal>.
- Algumas observações:
- </para>
-
- <itemizedlist spacing="compact">
- <listitem>
- <para>
- Na clausula from, a palavra chave FROM é opcional;
- </para>
- </listitem>
- <listitem>
- <para>
- Somente uma entidade pode ser chamada na clausula from; opcionalmente
pode ter
- um alias. Se o nome da entidade for possuir um alias, então qualquer
propriedade
- referenciada deve usar esse alias qualificado; se o nome da entidade
não possuir
- um alias, então nenhuma das propriedade precisa usar o acesso
qualificado.
- </para>
- </listitem>
- <listitem>
- <para>
- Na <xref linkend="queryhql-joins-forms">joins</xref>
(ambas implícita ou explicita)
- pode ser especificada em um bulk HQL query. Sub-queries podem ser usadas na
clausula
- where; as subqueries podem conter joins.
- </para>
- </listitem>
- <listitem>
- <para>
- A clausula where também é opcional.
- </para>
- </listitem>
- </itemizedlist>
-
- <para>
- Como exemplo para executar um HQL <literal>UPDATE</literal>, use
o
- método <literal>Query.executeUpdate()</literal>(o método ganhou o
nome
- devido a sua familiaridade com o do JDBC
- <literal>PreparedStatement.executeUpdate()</literal>):
- </para>
-
-<programlisting><![CDATA[Session session = sessionFactory.openSession();
-Transaction tx = session.beginTransaction();
-
-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();]]></programlisting>
-
- <para>
- HQL <literal>UPDATE</literal> statements, by default do not
effect the
- <xref
linkend="mapping-declaration-version">version</xref>
- or the <xref
linkend="mapping-declaration-timestamp">timestamp</xref> property
values
- for the affected entities; this is in keeping with the EJB3 specification.
However,
- you can force Hibernate to properly reset the
<literal>version</literal> or
- <literal>timestamp</literal> property values through the use of a
<literal>versioned update</literal>.
- This is achieved by adding the <literal>VERSIONED</literal>
keyword after the <literal>UPDATE</literal>
- keyword.
-
- </para>
-<programlisting><![CDATA[Session session = sessionFactory.openSession();
-Transaction tx = session.beginTransaction();
-String hqlVersionedUpdate = "update versioned Customer set name = :newName where
name = :oldName";
-int updatedEntities = s.createQuery( hqlUpdate )
- .setString( "newName", newName )
- .setString( "oldName", oldName )
- .executeUpdate();
-tx.commit();
-session.close();]]></programlisting>
-
- <para>
- Note that custom version types
(<literal>org.hibernate.usertype.UserVersionType</literal>)
- are not allowed in conjunction with a <literal>update
versioned</literal> statement.
- </para>
-
- <para>
-
- Para executar um HQL <literal>DELETE</literal>, use o mesmo
método
- <literal>Query.executeUpdate()</literal>:
- </para>
-
-<programlisting><![CDATA[Session session = sessionFactory.openSession();
-Transaction tx = session.beginTransaction();
-
-String hqlDelete = "delete Customer c where c.name = :oldName";
-// or String hqlDelete = "delete Customer where name = :oldName";
-int deletedEntities = s.createQuery( hqlDelete )
- .setString( "oldName", oldName )
- .executeUpdate();
-tx.commit();
-session.close();]]></programlisting>
-
- <para>
- O valor <literal>int</literal> retornado pelo método
<literal>Query.executeUpdate()</literal>
- indica o numero de entidade afetadas pela operação. Lembre-se que isso pode
estar ou não
- relacionado ao número de linhas alteradas no banco de dados. Uma operação
bulk HQL pode resultar
- em várias expressões SQL reais a serem executadas, por exemplo, no caso de
joined-subclass.
- O número retornado indica a quantidade real de entidades afetadas pela
expressão. Voltando
- ao exemplo da joined-subclass, a exclusão de uma das subclasses pode resultar
numa
- exclusão em outra tabelas, não apenas na tabela para qual a subclasses está
mapeada, mas
- também tabela "root" e possivelmente nas tabelas joined-subclass
num nível hierárquico
- imediatamente abaixo.
- </para>
-
- <para>
-
- A pseudo-sintaxe para o comando <literal>INSERT</literal> é:
- <literal>INSERT INTO EntityName properties_list
select_statement</literal>. Alguns
- pontos a observar:
- </para>
-
- <itemizedlist spacing="compact">
- <listitem>
- <para>
- Apenas a forma INSERT INTO ... SELECT ... é suportada; INSERT INTO
... VALUES ...
- não é suportada.
- </para>
- <para>
- A lista de propriedade é análoga à <literal>especificação da
coluna</literal>
- do comando SQL <literal>INSERT</literal>. Para entidades
envolvidas em mapeamentos,
- apenas a propriedades definidas diretamente a nível da classe podem
ser usandas na
- properties_list. Propriedades da superclass não são permitidas; e as
propriedades
- da subclasse não faz sentido. Em outras palavras, os comandos
- <literal>INSERT</literal> não são polimorficos.
- </para>
- </listitem>
- <listitem>
- <para>
- O camando select pode ser qualquer query HQL válida, que tenha um
retorno compatível
- com o tipo com o esperado pela inclusão. Atualmente, isto é
verificado durante a compilação
- da query, isto é melhor do que permitir que a verificação chegue ao
banco de dados.
- Entretanto perceba que isso pode causar problemas entre os
<literal>Tipo</literal> do Hibernate
- que são <emphasis>equivalentes</emphasis> em oposição a
<emphasis>equal</emphasis>.
- Isso pode causar problemas nas combinações entre a propriedade
definida como
- <literal>org.hibernate.type.DateType</literal>e um
propriedade definida como
- <literal>org.hibernate.type.TimestampType</literal>,
embora o banco de dados não possa
- fazer uma distinção ou possa ser capaz de manusear a conversão.
- </para>
- </listitem>
- <listitem>
- <para>
- Para a propriedade id, a expressão insert oferece duas opções. Você
pode especificar
- qualquer propriedade id explicitamente no properties_list (em alguns
casos esse valor
- é obtido diretamente da expressão select) ou pode omitir do
properties_list (nesse caso,
- um valor gerado é usado). Essa ultima opção só é válida quando são
usados geradores de ids
- que operam no banco de dados; a tentativa de usar essa opção com
geradores do tipo
- "em memória" vai causar um exceção durante a etapa de
parser. Veja a finalidades desta
- discussão, os seguintes geradores operam com o banco de dados
- <literal>org.hibernate.id.SequenceGenerator</literal> (e
suas subclasses)
- e qualquer implementação de
<literal>org.hibernate.id.PostInsertIdentifierGenerator</literal>.
- Aqui, a exceção mais notável é o
<literal>org.hibernate.id.TableHiLoGenerator</literal>, que
- não pode ser usado porque ele não dispõe de mecanismos para recuperar
o seu valor.
- </para>
- </listitem>
- <listitem>
- <para>
- For properties mapped as either
<literal>version</literal> or <literal>timestamp</literal>,
- the insert statement gives you two options. You can either specify
the property in the
- properties_list (in which case its value is taken from the
corresponding select expressions)
- or omit it from the properties_list (in which case the
<literal>seed value</literal> defined
- by the <literal>org.hibernate.type.VersionType</literal>
is used).
-
- Para propriedades mapeadas como
<literal>version</literal> ou <literal>timestamp</literal>,
- a expressão insert oferece a você duas opções. Você pode especificar
a propriedade na
- properties_list (nesse caso o seu valor é obtido a partir da
expressão select correspondente)
- ou ele pode ser omitido da properties_list (neste caso o usa o
<literal>valor semente</literal>
- definido pela classe
<literal>org.hibernate.type.VersionType</literal>).
- </para>
- </listitem>
- </itemizedlist>
-
- <para>
- Exemplo da execução de um HQL <literal>INSERT</literal>:
- </para>
-
-<programlisting><![CDATA[Session session = sessionFactory.openSession();
-Transaction tx = session.beginTransaction();
-
-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();]]></programlisting>
-
- </sect1>
-
-</chapter>
+<chapter id="batch">
+ <title>Processamento de lotes</title>
+
+ <para>
+ Uma alternativa para inserir 100.000 linhas no banco de dados usando o Hibernate
+ pode ser a seguinte:
+ </para>
+
+<programlisting><![CDATA[Session session = sessionFactory.openSession();
+Transaction tx = session.beginTransaction();
+for ( int i=0; i<100000; i++ ) {
+ Customer customer = new Customer(.....);
+ session.save(customer);
+}
+tx.commit();
+session.close();]]></programlisting>
+
+ <para>
+ Isto irá falhar em algum lugar próximo a linha 50.000, lançando uma
+ <literal>OutOfMemoryException</literal>. Isso ocorre devido ao fato
do Hibernate
+ fazer cache de todas as instâncias de <literal>Customer</literal>
inseridas num
+ cachê em nível de sessão.
+ </para>
+
+ <para>
+ Neste capítulo veremos como contornar esse problema. Entretanto, se você vai
realizar
+ processamento de lotes, é muito importante que você habilite o uso de lotes JDBC,
se
+ você pretende obter um desempenho razoável. Defina o tamanho do lote JDBC em um
+ valor razoável (algo entre 10-50):
+ </para>
+
+<programlisting><![CDATA[hibernate.jdbc.batch_size
20]]></programlisting>
+
+ <para>
+ Você também pode querer rodar esse tipo de processamento de lotes com o cache
+ secundário completamente desabilitado:
+ </para>
+
+<programlisting><![CDATA[hibernate.cache.use_second_level_cache
false]]></programlisting>
+<para id="disablebatching" revision="1">
+ Note that Hibernate disables insert batching at the JDBC level transparently if you
+ use an <literal>identiy</literal> identifier generator.
+</para>
+
+ <para>
+ Mas isto não é absolutamente necessário, desde que nós possamos ajustar o
+ <literal>CacheMode</literal> para desabilitar a interação com o
cache secundário.
+ </para>
+
+ <sect1 id="batch-inserts">
+ <title>Inserção de lotes</title>
+
+ <para>
+ Quando você estiver inserindo novos objetos persistentes, vocês deve executar
+ os métodos <literal>flush()</literal> e
<literal>clear()</literal> regularmente
+ na sessão, para controlar o tamanho do cache primário.
+ </para>
+
+<programlisting><![CDATA[Session session = sessionFactory.openSession();
+Transaction tx = session.beginTransaction();
+
+for ( int i=0; i<100000; i++ ) {
+ Customer customer = new Customer(.....);
+ session.save(customer);
+ if ( i % 20 == 0 ) { //20, same as the JDBC batch size
+ //flush a batch of inserts and release memory:
+ session.flush();
+ session.clear();
+ }
+}
+
+tx.commit();
+session.close();]]></programlisting>
+
+ </sect1>
+
+ <sect1 id="batch-update" >
+ <title>Batch updates</title>
+
+ <para>
+ Para recuperar e atualizar informações a mesma idéia é válida.
Adicionalmente,
+ pode precisar usar o <literal>scroll()</literal> para usar
recursos no lado
+ do servidor em queries que retornam muita informação.
+ </para>
+
+<programlisting><![CDATA[Session session = sessionFactory.openSession();
+Transaction tx = session.beginTransaction();
+
+ScrollableResults customers = session.getNamedQuery("GetCustomers")
+ .setCacheMode(CacheMode.IGNORE)
+ .scroll(ScrollMode.FORWARD_ONLY);
+int count=0;
+while ( customers.next() ) {
+ Customer customer = (Customer) customers.get(0);
+ customer.updateStuff(...);
+ if ( ++count % 20 == 0 ) {
+ //flush a batch of updates and release memory:
+ session.flush();
+ session.clear();
+ }
+}
+
+tx.commit();
+session.close();]]></programlisting>
+
+ </sect1>
+
+ <sect1 id="batch-statelesssession">
+ <title>A interface StatelessSession</title>
+ <para>
+ Alternativamente, o Hibernate provê uma API orientada à comandos, usada para
+ transmitir um fluxo de dados de e para o banco de dados na forma de objetos
soltos.
+ Uma <literal>StatelessSession</literal> não tem um contexto
persistente associado e
+ não fornece muito das semânticas de alto nível para controle do ciclo de
vida.
+ Em especial, uma StatelessSession não implemente o cache primário e nem
interage
+ com o cache secundário ou query cache. Ele não implementa salvamento
transacional
+ automatico ou checagem automática de mudanças. Operação realizadas usando uma
+ StatelessSession não fazem nenhum tipo de cascade com as instancias
associadas.
+ As coleções são ignoradas por uma StatelessSession. Operações realizadas com
um
+ StatelessSession ignoram a arquitetura de eventos e os interceptadores.
+ StatelessSession são vulneráveis aos efeitos do aliasing dos dados, devido a
+ falta do cache primário. Uma StatelessSession é uma abstração de baixo nível,
+ muito mais próxima do JDBC.
+ </para>
+
+<programlisting><![CDATA[StatelessSession session =
sessionFactory.openStatelessSession();
+Transaction tx = session.beginTransaction();
+
+ScrollableResults customers = session.getNamedQuery("GetCustomers")
+ .scroll(ScrollMode.FORWARD_ONLY);
+while ( customers.next() ) {
+ Customer customer = (Customer) customers.get(0);
+ customer.updateStuff(...);
+ session.update(customer);
+}
+
+tx.commit();
+session.close();]]></programlisting>
+
+ <para>
+ Veja neste exempo, as instancias de <literal>Customer</literal>
retornadas pela query
+ são imediatamente desvinculadas. Elas nunca serão assossiadas à um contexto
persistente.
+ </para>
+
+ <para>
+ As operações <literal>insert(), update()</literal> e
<literal>delete()</literal>
+ definidos pela interface <literal>StatelessSession</literal> são
considerados
+ operações diretas no banco de dados (row-level operations), isso resulta em
uma
+ execução imediata de comandos SQL <literal>INSERT,
UPDATE</literal> ou
+ <literal>DELETE</literal> respectivamente. Devido a isso, eles
possuem uma
+ semântica bem diferente das operações <literal>save(),
saveOrUpdate()</literal>
+ ou <literal>delete()</literal> definidas na interface
<literal>Session</literal>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="batch-direct" revision="3">
+ <title>Operações no estilo DML</title>
+
+ <para>
+ Como já discutido, mapeamento objeto/relacional automático e transparente é
conseguido
+ com a gerência do estado do objeto. Com isto o estado daquele objeto fica
disponível na
+ memória, manipulando(usando as expressões SQL <literal>Data
Manipulation Language</literal>
+ (SQL-style DML): <literal>INSERT</literal>,
<literal>UPDATE</literal>, <literal>DELETE</literal>)
+ os dados diretamente no banco de dados não irá afetar o estado registrado em
memória.
+ Entretanto, o Hibernate provê métodos para executar queries SQL-style DML,
que são
+ totalmente executas com HQL (Hibernate Query Language)
+ (<xref linkend="queryhql">HQL</xref>).
+ </para>
+
+ <para>
+ A pseudo-sintaxe para expressões <literal>UPDATE</literal> e
<literal>DELETE</literal> é:
+ <literal>( UPDATE | DELETE ) FROM? NomeEntidade (WHERE
condições_where)?</literal>.
+ Algumas observações:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ Na clausula from, a palavra chave FROM é opcional;
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Somente uma entidade pode ser chamada na clausula from; opcionalmente
pode ter
+ um alias. Se o nome da entidade for possuir um alias, então qualquer
propriedade
+ referenciada deve usar esse alias qualificado; se o nome da entidade
não possuir
+ um alias, então nenhuma das propriedade precisa usar o acesso
qualificado.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Na <xref linkend="queryhql-joins-forms">joins</xref>
(ambas implícita ou explicita)
+ pode ser especificada em um bulk HQL query. Sub-queries podem ser usadas na
clausula
+ where; as subqueries podem conter joins.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ A clausula where também é opcional.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Como exemplo para executar um HQL <literal>UPDATE</literal>, use
o
+ método <literal>Query.executeUpdate()</literal>(o método ganhou o
nome
+ devido a sua familiaridade com o do JDBC
+ <literal>PreparedStatement.executeUpdate()</literal>):
+ </para>
+
+<programlisting><![CDATA[Session session = sessionFactory.openSession();
+Transaction tx = session.beginTransaction();
+
+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();]]></programlisting>
+
+ <para>
+ HQL <literal>UPDATE</literal> statements, by default do not
effect the
+ <xref
linkend="mapping-declaration-version">version</xref>
+ or the <xref
linkend="mapping-declaration-timestamp">timestamp</xref> property
values
+ for the affected entities; this is in keeping with the EJB3 specification.
However,
+ you can force Hibernate to properly reset the
<literal>version</literal> or
+ <literal>timestamp</literal> property values through the use of a
<literal>versioned update</literal>.
+ This is achieved by adding the <literal>VERSIONED</literal>
keyword after the <literal>UPDATE</literal>
+ keyword.
+
+ </para>
+<programlisting><![CDATA[Session session = sessionFactory.openSession();
+Transaction tx = session.beginTransaction();
+String hqlVersionedUpdate = "update versioned Customer set name = :newName where
name = :oldName";
+int updatedEntities = s.createQuery( hqlUpdate )
+ .setString( "newName", newName )
+ .setString( "oldName", oldName )
+ .executeUpdate();
+tx.commit();
+session.close();]]></programlisting>
+
+ <para>
+ Note that custom version types
(<literal>org.hibernate.usertype.UserVersionType</literal>)
+ are not allowed in conjunction with a <literal>update
versioned</literal> statement.
+ </para>
+
+ <para>
+
+ Para executar um HQL <literal>DELETE</literal>, use o mesmo
método
+ <literal>Query.executeUpdate()</literal>:
+ </para>
+
+<programlisting><![CDATA[Session session = sessionFactory.openSession();
+Transaction tx = session.beginTransaction();
+
+String hqlDelete = "delete Customer c where c.name = :oldName";
+// or String hqlDelete = "delete Customer where name = :oldName";
+int deletedEntities = s.createQuery( hqlDelete )
+ .setString( "oldName", oldName )
+ .executeUpdate();
+tx.commit();
+session.close();]]></programlisting>
+
+ <para>
+ O valor <literal>int</literal> retornado pelo método
<literal>Query.executeUpdate()</literal>
+ indica o numero de entidade afetadas pela operação. Lembre-se que isso pode
estar ou não
+ relacionado ao número de linhas alteradas no banco de dados. Uma operação
bulk HQL pode resultar
+ em várias expressões SQL reais a serem executadas, por exemplo, no caso de
joined-subclass.
+ O número retornado indica a quantidade real de entidades afetadas pela
expressão. Voltando
+ ao exemplo da joined-subclass, a exclusão de uma das subclasses pode resultar
numa
+ exclusão em outra tabelas, não apenas na tabela para qual a subclasses está
mapeada, mas
+ também tabela "root" e possivelmente nas tabelas joined-subclass
num nível hierárquico
+ imediatamente abaixo.
+ </para>
+
+ <para>
+
+ A pseudo-sintaxe para o comando <literal>INSERT</literal> é:
+ <literal>INSERT INTO EntityName properties_list
select_statement</literal>. Alguns
+ pontos a observar:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ Apenas a forma INSERT INTO ... SELECT ... é suportada; INSERT INTO
... VALUES ...
+ não é suportada.
+ </para>
+ <para>
+ A lista de propriedade é análoga à <literal>especificação da
coluna</literal>
+ do comando SQL <literal>INSERT</literal>. Para entidades
envolvidas em mapeamentos,
+ apenas a propriedades definidas diretamente a nível da classe podem
ser usandas na
+ properties_list. Propriedades da superclass não são permitidas; e as
propriedades
+ da subclasse não faz sentido. Em outras palavras, os comandos
+ <literal>INSERT</literal> não são polimorficos.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ O camando select pode ser qualquer query HQL válida, que tenha um
retorno compatível
+ com o tipo com o esperado pela inclusão. Atualmente, isto é
verificado durante a compilação
+ da query, isto é melhor do que permitir que a verificação chegue ao
banco de dados.
+ Entretanto perceba que isso pode causar problemas entre os
<literal>Tipo</literal> do Hibernate
+ que são <emphasis>equivalentes</emphasis> em oposição a
<emphasis>equal</emphasis>.
+ Isso pode causar problemas nas combinações entre a propriedade
definida como
+ <literal>org.hibernate.type.DateType</literal>e um
propriedade definida como
+ <literal>org.hibernate.type.TimestampType</literal>,
embora o banco de dados não possa
+ fazer uma distinção ou possa ser capaz de manusear a conversão.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Para a propriedade id, a expressão insert oferece duas opções. Você
pode especificar
+ qualquer propriedade id explicitamente no properties_list (em alguns
casos esse valor
+ é obtido diretamente da expressão select) ou pode omitir do
properties_list (nesse caso,
+ um valor gerado é usado). Essa ultima opção só é válida quando são
usados geradores de ids
+ que operam no banco de dados; a tentativa de usar essa opção com
geradores do tipo
+ "em memória" vai causar um exceção durante a etapa de
parser. Veja a finalidades desta
+ discussão, os seguintes geradores operam com o banco de dados
+ <literal>org.hibernate.id.SequenceGenerator</literal> (e
suas subclasses)
+ e qualquer implementação de
<literal>org.hibernate.id.PostInsertIdentifierGenerator</literal>.
+ Aqui, a exceção mais notável é o
<literal>org.hibernate.id.TableHiLoGenerator</literal>, que
+ não pode ser usado porque ele não dispõe de mecanismos para recuperar
o seu valor.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ For properties mapped as either
<literal>version</literal> or <literal>timestamp</literal>,
+ the insert statement gives you two options. You can either specify
the property in the
+ properties_list (in which case its value is taken from the
corresponding select expressions)
+ or omit it from the properties_list (in which case the
<literal>seed value</literal> defined
+ by the <literal>org.hibernate.type.VersionType</literal>
is used).
+
+ Para propriedades mapeadas como
<literal>version</literal> ou <literal>timestamp</literal>,
+ a expressão insert oferece a você duas opções. Você pode especificar
a propriedade na
+ properties_list (nesse caso o seu valor é obtido a partir da
expressão select correspondente)
+ ou ele pode ser omitido da properties_list (neste caso o usa o
<literal>valor semente</literal>
+ definido pela classe
<literal>org.hibernate.type.VersionType</literal>).
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Exemplo da execução de um HQL <literal>INSERT</literal>:
+ </para>
+
+<programlisting><![CDATA[Session session = sessionFactory.openSession();
+Transaction tx = session.beginTransaction();
+
+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();]]></programlisting>
+
+ </sect1>
+
+</chapter>
Modified:
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/best_practices.xml
===================================================================
---
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/best_practices.xml 2007-10-26
00:46:38 UTC (rev 14135)
+++
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/best_practices.xml 2007-10-26
00:48:48 UTC (rev 14136)
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="best-practices" revision="3">
+<chapter id="best-practices" revision="3">
<title>Boas práticas</title>
<variablelist spacing="compact">
Modified:
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/collection_mapping.xml
===================================================================
---
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/collection_mapping.xml 2007-10-26
00:46:38 UTC (rev 14135)
+++
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/collection_mapping.xml 2007-10-26
00:48:48 UTC (rev 14136)
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="collections">
+<chapter id="collections">
<title>Mapeamento de Coleções</title>
<sect1 id="collections-persistent" revision="3">
Modified:
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/component_mapping.xml
===================================================================
---
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/component_mapping.xml 2007-10-26
00:46:38 UTC (rev 14135)
+++
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/component_mapping.xml 2007-10-26
00:48:48 UTC (rev 14136)
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="components">
+<chapter id="components">
<title>Mapeamento de Componentes</title>
<para>
Modified:
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/configuration.xml
===================================================================
---
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/configuration.xml 2007-10-26
00:46:38 UTC (rev 14135)
+++
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/configuration.xml 2007-10-26
00:48:48 UTC (rev 14136)
@@ -1,1792 +1,1789 @@
<?xml version='1.0' encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="session-configuration" revision="1">
-
- <title>Configuração</title>
-
- <para>
- Devido ao fato de o Hibernate ser projetado para operar em vários ambientes
diferentes,
- há um grande número de parâmetros de configuração. Felizmente, a maioria tem
valores default
- lógicos e o Hibernate é distribuído com um arquivo
<literal>hibernate.properties</literal>
- de exemplo no <literal>etc/</literal> que mostra várias opções.
Apenas coloque o arquivo
- de exemplo no seu classpath e personalize-o.
- </para>
-
- <sect1 id="configuration-programmatic" revision="1">
- <title>1.11 Configuração programática</title>
-
- <para>
- Uma instância de
<literal>org.hibernate.cfg.Configuration</literal>
- representa um conjunto inteiro de mapeamentos de tipos Java da aplicação para
- um banco de dados SQL. O <literal>Configuration</literal> é usado
para construir
- uma <literal>SessionFactory</literal> (imutável). Os mapeamentos
são compilados
- a partir de arquivos de mapeamento XML.
-
- </para>
-
- <para>
- Você pode obter uma instância <literal>Configuration</literal>
intanciando-
- o diretamente e especificando documentos de mapeamento XML. Se o arquivo
- de mapeamento estão no classpath, use use
<literal>addResource()</literal>:
- </para>
-
- <programlisting><![CDATA[Configuration cfg = new Configuration()
- .addResource("Item.hbm.xml")
- .addResource("Bid.hbm.xml");]]></programlisting>
-
- <para>
- Uma alternativa (às vezes melhor) é especificar a classe mapeada,
- e permitir que o Hibernate encontre o documento de mapeamento para você:
- </para>
-
- <programlisting><![CDATA[Configuration cfg = new Configuration()
- .addClass(org.hibernate.auction.Item.class)
- .addClass(org.hibernate.auction.Bid.class);]]></programlisting>
-
- <para>
- Então o Hibernate procurará pelos arquivos de mapeamento chamados
- <literal>/org/hibernate/auction/Item.hbm.xml</literal> e
- <literal>/org/hibernate/auction/Bid.hbm.xml</literal> no
classpath.
- Esta abordagem elimina qualquer nome de arquivo de difícil compreensão.
- </para>
-
- <para>
- Uma <literal>Configuration</literal> também permite você
especificar
- propriedades de configuração:
- </para>
-
- <programlisting><![CDATA[Configuration cfg = new Configuration()
- .addClass(org.hibernate.auction.Item.class)
- .addClass(org.hibernate.auction.Bid.class)
- .setProperty("hibernate.dialect",
"org.hibernate.dialect.MySQLInnoDBDialect")
- .setProperty("hibernate.connection.datasource",
"java:comp/env/jdbc/test")
- .setProperty("hibernate.order_updates",
"true");]]></programlisting>
-
- <para>
- Este não é o único caminho para passar as propriedades de configuração
- para o Hibernate. As várias opções incluem:
- </para>
-
- <orderedlist spacing="compact">
- <listitem>
- <para>
- Passar uma instância de
<literal>java.util.Properties</literal>
- para <literal>Configuration.setProperties()</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- Colocar <literal>hibernate.properties</literal> no
diretório
- raiz do classpath.
- </para>
- </listitem>
- <listitem>
- <para>
- Determinar as propriedades do <literal>System</literal>
- usando <literal>java -Dproperty=value</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- Include <literal><property></literal>
elements in
- <literal>hibernate.cfg.xml</literal> (discussed later).
- Incluir elementos
<literal><property></literal> no
- <literal>hibernate.cfg.xml</literal> (discutido mais
tarde).
- </para>
- </listitem>
- </orderedlist>
-
- <para>
- <literal>hibernate.properties</literal> é o caminho mais facil
- se você quer começar mais rápido.
- </para>
-
- <para>
- O <literal>Configuration</literal> é entendido como um objeto
startup-time,
- é descartado uma vez que a <literal>SessionFactory</literal> é
criada.
- </para>
-
- </sect1>
-
- <sect1 id="configuration-sessionfactory">
- <title>Obtendo uma SessionFactory</title>
-
- <para>
- Quando todos os mapeamentos têm sido analisados pelo
<literal>Configuration</literal>,
- a aplicação deve obter uma factory para as instâncias da
<literal>Session</literal>.
- O objetivo desta factory é ser compartilhado por todas as threads da
aplicação:
- </para>
-
- <programlisting><![CDATA[SessionFactory sessions =
cfg.buildSessionFactory();]]></programlisting>
-
- <para>
- Hibernate permite sua aplicação instanciar mais do que uma
- <literal>SessionFactory</literal>. Isto é útil se você está
usando mais
- do que um banco de dados.
- </para>
-
- </sect1>
-
- <sect1 id="configuration-hibernatejdbc" revision="1">
- <title>Conexões JDBC</title>
-
- <para>
- Normalmente, você quer mandar criar a
<literal>SessionFactory</literal> criar um
- pool de conexões JDBC para você. Se você seguir essa abordagem, a abertura de
uma
- <literal>Session</literal> é tão simples quanto:
-
- </para>
-
- <programlisting><![CDATA[Session session = sessions.openSession(); //
open a new Session]]></programlisting>
-
- <para>
- Assim que você fizer algo que requer o acesso ao banco de dados, uma
- conexão JDBC será obtida do pool.
- </para>
-
- <para>
- Para esse trabalho, nós necessitamos passar algumas propriedades da conexão
JDBC
- para o Hibernate. Todos os nomes de propriedades Hibernate e semânticas são
definidas
- <literal>org.hibernate.cfg.Environment</literal>. Nós iremos
descrever agora
- o mais importantes configurações de conexão JDBC.
- </para>
-
- <para>
- O Hibernate obterá conexões( e pool) usando
<literal>java.sql.DriverManager</literal>
- se você determinar as seguintes propriedades:
- </para>
-
- <table frame="topbot">
- <title>Propriedades JDBC Hibernate</title>
- <tgroup cols="2">
- <colspec colname="c1" colwidth="1*"/>
- <colspec colname="c2" colwidth="1*"/>
- <thead>
- <row>
- <entry>Nome da Propriedade</entry>
- <entry>Propósito</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
- <literal>hibernate.connection.driver_class</literal>
- </entry>
- <entry>
- <emphasis>Classe driver jdbc</emphasis>
- </entry>
- </row>
- <row>
- <entry>
- <literal>hibernate.connection.url</literal>
- </entry>
- <entry>
- <emphasis>URL jdbc</emphasis>
- </entry>
- </row>
- <row>
- <entry>
- <literal>hibernate.connection.username</literal>
- </entry>
- <entry>
- <emphasis>Usuário do banco de dados</emphasis>
- </entry>
- </row>
- <row>
- <entry>
- <literal>hibernate.connection.password</literal>
- </entry>
- <entry>
- <emphasis>Senha do usuário do banco de dados</emphasis>
- </entry>
- </row>
- <row>
- <entry>
- <literal>hibernate.connection.pool_size</literal>
- </entry>
- <entry>
- <emphasis>Número máximo de connecxões no pool</emphasis>
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <para>
- O algoritmo de pool de conexões do próprio Hibernate entretanto é
completamente
- rudimentar. A intenção dele e ajudar a iniciar e <emphasis>não para
usar em um
- sistema de produção</emphasis> ou até para testar desempenho. Você
deveria usar
- uma ferramente de pool de terceiros para conseguir melhor desempenho e
estabilidade.
- Apenas especifique a propriedade
<literal>hibernate.connection.pool_size</literal>
- com a definição do pool de conexões. Isto irá desligar o pool interno do
Hibernate.
- Por exemplo, você pode gostar de usar C3P0.
- </para>
-
- <para>
- O C3P0 é um pool conexão JDBC de código aberto distribuído junto com
- Hibernate no diretório <literal>lib</literal>. O Hibernate
usará o
- <literal>C3P0ConnectionProvider</literal> para o pool de conexão
se
- você configurar a propriedade
<literal>hibernate.c3p0.*</literal>. Se você
- gostar de usar Proxool consulte ao pacote
<literal>hibernate.properties</literal>
- e o web site do Hibernate para mais informações.
- </para>
-
- <para>
- Aqui é um exemplo de arquivo
<literal>hibernate.properties</literal> para C3P0:
- </para>
-
- <programlisting id="c3p0-configuration"
revision="1"><![CDATA[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]]></programlisting>
-
- <para>
- Para usar dentro de um servidor de aplicação, você deve configurar
- o Hibernate para obter conexões de um application server
- <literal>Datasource</literal> registrado no JNDI. Você
necessitará
- determinar pelo menos uma das seguintes propriedades:
- </para>
-
- <table frame="topbot">
- <title>Propriedades do Datasource do Hibernate</title>
- <tgroup cols="2">
- <colspec colname="c1" colwidth="1*"/>
- <colspec colname="c2" colwidth="1*"/>
- <thead>
- <row>
- <entry>Nome da Propriedade</entry>
- <entry>Propósito</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
- <literal>hibernate.connection.datasource</literal>
- </entry>
- <entry>
- <emphasis>Nome datasource JNDI</emphasis>
- </entry>
- </row>
- <row>
- <entry>
- <literal>hibernate.jndi.url</literal>
- </entry>
- <entry>
- <emphasis>URL do fornecedor JNDI</emphasis> (opcional)
- </entry>
- </row>
- <row>
- <entry>
- <literal>hibernate.jndi.class</literal>
- </entry>
- <entry>
- <emphasis>Classe do JNDI
<literal>InitialContextFactory</literal></emphasis> (opcional)
- </entry>
- </row>
- <row>
- <entry>
- <literal>hibernate.connection.username</literal>
- </entry>
- <entry>
- <emphasis>Usuário do banco de dados</emphasis>
(opcional)
- </entry>
- </row>
- <row>
- <entry>
- <literal>hibernate.connection.password</literal>
- </entry>
- <entry>
- <emphasis>Senha do usuário do banco de dados</emphasis>
(opcional)
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <para>
- Eis um exemplo de arquivo <literal>hibernate.properties</literal>
para
- um servidor de aplicação fornecedor de datasources JNDI:
- </para>
-
- <programlisting><![CDATA[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]]></programlisting>
-
- <para>
- Conexões JDBC obtidas de um datasource JNDI irão automaticamente irão
participar
- das transações gerenciadas pelo container no servidor de aplicação.
- </para>
-
- <para>
- Arbitrariamente as propriedades de conexão podem ser acrescentandas ao
- "<literal>hibernate.connnection</literal>" ao nome da
propriedade. Por exemplo,
- você deve especificar o <literal>charSet</literal> usando
<literal>hibernate.connection.charSet</literal>.t.
- </para>
-
- <para>
- Você pode definir sua própria estratégia de plugin para obter conexões JDBC
implementando
- a interface
<literal>org.hibernate.connection.ConnectionProvider</literal>. Você pode
- escolher uma implementação customizada setando
<literal>hibernate.connection.provider_class</literal>.
- </para>
-
- </sect1>
-
- <sect1 id="configuration-optional" revision="1">
- <title>Propriedades opcionais de configuração</title>
-
- <para>
- Há um grande número de outras propriedades que controlam o comportamento do
Hibernate
- em tempo de execução. Todos são opcionais e tem valores default lógicos.
- </para>
-
- <para>
- <emphasis>Aviso: algumas destas propriedades são somente a "nível
de sistema".</emphasis>
- Propriedades nível de sistema podem ser determinados somente via
<literal>java -Dproperty=value</literal>
- ou <literal>hibernate.properties</literal>. Elas
<emphasis>não</emphasis>podem ser
- configuradas por outras técnicas descritas abaixo.
- </para>
-
- <table frame="topbot"
id="configuration-optional-properties" revision="8">
- <title>Hibernate Configuration Properties</title>
- <tgroup cols="2">
- <colspec colname="c1" colwidth="1*"/>
- <colspec colname="c2" colwidth="1*"/>
- <thead>
- <row>
- <entry>Nome da Propriedade</entry>
- <entry>Propósito</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
- <literal>hibernate.dialect</literal>
- </entry>
- <entry>
- O nome da classe de um <literal>Dialeto</literal>
- que permite o Hibernate gerar SQL otimizado para um banco de
- dados relacional em particular.
- <para>
- <emphasis
role="strong">Ex.</emphasis>
- <literal>full.classname.of.Dialect</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <literal>hibernate.show_sql</literal>
- </entry>
- <entry>
- Escreve todas as instruções SQL no console. Esta é uma
alternativa
- a configurar a categoria de log
<literal>org.hibernate.SQL</literal>
- para <literal>debug</literal>.
- <para>
- <emphasis
role="strong">Ex.</emphasis>
- <literal>true</literal> |
<literal>false</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <literal>hibernate.format_sql</literal>
- </entry>
- <entry>
- Imprime o SQL formatado no log e console.
- <para>
- <emphasis
role="strong">Ex.</emphasis>
- <literal>true</literal> |
<literal>false</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <literal>hibernate.default_schema</literal>
- </entry>
- <entry>
- Qualifica no sql gerado, os nome das tabelas sem qualificar
- com schena/tablespace dado
- <para>
- <emphasis
role="strong">Ex.</emphasis>
- <literal>SCHEMA_NAME</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <literal>hibernate.default_catalog</literal>
- </entry>
- <entry>
- Qualifica no sql gerado, os nome das tabelas sem qualificar
- com catálogo dado
- <para>
- <emphasis
role="strong">Ex.</emphasis>
- <literal>CATALOG_NAME</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
-
<literal>hibernate.session_factory_name</literal>
- </entry>
- <entry>
- O <literal>SessionFactory</literal> irá
automaticamente
- se ligar a este nome no JNDI depois de ter sido criado.
- <para>
- <emphasis
role="strong">Ex.</emphasis>
- <literal>jndi/composite/name</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <literal>hibernate.max_fetch_depth</literal>
- </entry>
- <entry>
- Estabelece a "profundidade" máxima para árvore
outer join fetch
- para associações finais únicas(one-to-one,many-to-one).
- Um <literal>0</literal> desativa por default a
busca outer join.
- <para>
- <emphasis
role="strong">eg.</emphasis>
- Valores recomendados
entre<literal>0</literal> e <literal>3</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
-
<literal>hibernate.default_batch_fetch_size</literal>
- </entry>
- <entry>
- Determina um tamanho default para busca de associações em
lotes do Hibernate
- <para>
- <emphasis
role="strong">eg.</emphasis>
- Valores recomendados <literal>4</literal>,
<literal>8</literal>,
- <literal>16</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <literal>hibernate.default_entity_mode</literal>
- </entry>
- <entry>
- Determina um modo default para representação de entidades
- para todas as sessões abertas desta
<literal>SessionFactory</literal>
- <para>
- <literal>dynamic-map</literal>,
<literal>dom4j</literal>,
- <literal>pojo</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <literal>hibernate.order_updates</literal>
- </entry>
- <entry>
- Força o Hibernate a ordenar os updates SQL pelo valor da
chave
- primária dos itens a serem atualizados. Isto resultará em
menos
- deadlocks nas transações em sistemas altamente concorrente.
- <para>
- <emphasis
role="strong">Ex.</emphasis>
- <literal>true</literal> |
<literal>false</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <literal>hibernate.generate_statistics</literal>
- </entry>
- <entry>
- If enabled, Hibernate will collect statistics useful for
- performance tuning.
- Se habilitado, o Hibernate coletará estatísticas úties
- para performance tuning dos bancos.
- <para>
- <emphasis
role="strong">Ex.</emphasis>
- <literal>true</literal> |
<literal>false</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
-
<literal>hibernate.use_identifer_rollback</literal>
- </entry>
- <entry>
- Se habilitado, propriedades identificadoras geradas
- serão zeradas para os valores default quando os
- objetos forem apagados.
- <para>
- <emphasis
role="strong">Ex.</emphasis>
- <literal>true</literal> |
<literal>false</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <literal>hibernate.use_sql_comments</literal>
- </entry>
- <entry>
- Se ligado, o Hibernate irá gerar comentários dentro do SQL,
- para facilitar o debugging, o valor default é
<literal>false</literal>.
- <para>
- <emphasis
role="strong">eg.</emphasis>
- <literal>true</literal> |
<literal>false</literal>
- </para>
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table frame="topbot" id="configuration-jdbc-properties"
revision="8">
- <title>JDBC Hibernate e Propriedades de Conexão</title>
- <tgroup cols="2">
- <colspec colname="c1" colwidth="1*"/>
- <colspec colname="c2" colwidth="1*"/>
- <thead>
- <row>
- <entry>Nome da Propriedade</entry>
- <entry>Propósito</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
- <literal>hibernate.jdbc.fetch_size</literal>
- </entry>
- <entry>
- Um valor maior que zero determina o tamanho do fetch
- do JDBC( chamadas
<literal>Statement.setFetchSize()</literal>).
- </entry>
- </row>
- <row>
- <entry>
- <literal>hibernate.jdbc.batch_size</literal>
- </entry>
- <entry>
- Um valor maior que zero habilita uso de batch updates JDBC2
pelo Hibernate.
- <para>
- <emphasis
role="strong">Ex.</emphasis>
- valores recomentados entre
<literal>5</literal> e <literal>30</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
-
<literal>hibernate.jdbc.batch_versioned_data</literal>
- </entry>
- <entry>
- Sete esta propriedade como
<literal>true</literal> se seu driver JDBC retorna
- o número correto de linhas no
<literal>executeBatch()</literal> ( É usualmente
- seguro tornar esta opção ligada). O Hibernate então irá usar
betched DML
- para automaticamente versionar dados.
<literal>false</literal> por default.
- <para>
- <emphasis
role="strong">Ex.</emphasis>
- <literal>true</literal> |
<literal>false</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <literal>hibernate.jdbc.factory_class</literal>
- </entry>
- <entry>
- Escolher um <literal>Batcher</literal>
customizado. Muitas
- aplicações não irão necessitar desta propriedade de
configuração
- <para>
- <emphasis
role="strong">Ex.</emphasis>
-
<literal>classname.of.BatcherFactory</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
-
<literal>hibernate.jdbc.use_scrollable_resultset</literal>
- </entry>
- <entry>
- Habilita o uso de JDBC2 scrollable resultsets pelo
Hibernate.
- Essa propriedade somente é necessaria quando se usa
Conexeções
- JDBC providas pelo usuário, caso contrário o Hibernate os os
- metadados da conexão.
- <para>
- <emphasis
role="strong">Ex.</emphasis>
- <literal>true</literal> |
<literal>false</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
-
<literal>hibernate.jdbc.use_streams_for_binary</literal>
- </entry>
- <entry>
- Use streams para escrever/ler tipos
<literal>binary</literal>
- ou <literal>serializable</literal> para/a o JDBC(
propriedade a nível de sistema).
- <para>
- <emphasis
role="strong">Ex.</emphasis>
- <literal>true</literal> |
<literal>false</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
-
<literal>hibernate.jdbc.use_get_generated_keys</literal>
- </entry>
- <entry>
- Possibilita o uso
<literal>PreparedStatement.getGeneratedKeys()</literal>
- do JDBC3 para recuperar chaves geradas nativamente depois da
inserçãp.
- Requer driver JDBC3+ e JRE1.4+, determine para false se seu
driver tem
- problemas com gerador de indentificadores Hibernate. Por
default, tente
- determinar o driver capaz de usar metadados da conexão.
- <para>
- <emphasis
role="strong">Ex.</emphasis>
- <literal>true|false</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
-
<literal>hibernate.connection.provider_class</literal>
- </entry>
- <entry>
- O nome da classe de um
<literal>ConnectionProvider</literal> personalizado
- o qual proverá conexões JDBC para o Hibernate.
- <para>
- <emphasis
role="strong">Ex.</emphasis>
-
<literal>classname.of.ConnectionProvider</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <literal>hibernate.connection.isolation</literal>
- </entry>
- <entry>
- Determina o nível de isolamento de uma transação JDBC.
- Verifique <literal>java.sql.Connection</literal> para
valores
- siginificativos mas note que a maior parte dos bancos de dados
- não suportam todos os níveis de isolamento.
- <para>
- <emphasis role="strong">Ex.</emphasis>
- <literal>1, 2, 4, 8</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
-
<literal>hibernate.connection.autocommit</literal>
- </entry>
- <entry>
- Habilita autocommit para conexões no pool JDBC( não
recomendado).
- <para>
- <emphasis
role="strong">Ex.</emphasis>
- <literal>true</literal> |
<literal>false</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
-
<literal>hibernate.connection.release_mode</literal>
- </entry>
- <entry>
- Especifica quando o Hibernate deve liberar conexões JDBC. Por
default,
- uma conexão JDBC é retida até a sessão está explicitamente
fechada
- ou desconectada. Para um datasource JTA do servidor de
aplicação, você deve
- usar <literal>after_statement</literal> para
forçar s liberação da conexões
- depois de todas as chamadas JDBC. Para uma conexão não-JTA,
freqüentemente
- faz sentido liberar a conexão ao fim de cada transação,
usando
- <literal>after_transaction</literal>.
<literal>auto</literal> escolheremos
- <literal>after_statement</literal> para as
estratégias de transaçãoes JTA e CMT
- e <literal>after_transaction</literal> para as
estratégias de transação JDBC
- <para>
- <emphasis
role="strong">Ex.</emphasis>
- <literal>auto</literal> (default) |
<literal>on_close</literal> |
- <literal>after_transaction</literal> |
<literal>after_statement</literal>
- </para>
- <para>
- Note that this setting only affects
<literal>Session</literal>s returned from
-
<literal>SessionFactory.openSession</literal>. For
<literal>Session</literal>s
- obtained through
<literal>SessionFactory.getCurrentSession</literal>, the
- <literal>CurrentSessionContext</literal>
implementation configured for use
- controls the connection release mode for those
<literal>Session</literal>s.
- See <xref
linkend="architecture-current-session"/>
- </para>
- </entry>
- </row>
- <row>
- <entry>
-
<literal>hibernate.connection.<emphasis><propertyName></emphasis></literal>
- </entry>
- <entry>
- Passa a propriedade JDBC
<literal>propertyName</literal>
- para
<literal>DriverManager.getConnection()</literal>.
- </entry>
- </row>
- <row>
- <entry>
-
<literal>hibernate.jndi.<emphasis><propertyName></emphasis></literal>
- </entry>
- <entry>
- Passar a propriedade
<literal>propertyName</literal> para
- o <literal>InitialContextFactory</literal> JNDI.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table frame="topbot" id="configuration-cache-properties"
revision="7">
- <title>Propriedades de Cachê do Hibernate</title>
- <tgroup cols="2">
- <colspec colname="c1" colwidth="1*"/>
- <colspec colname="c2" colwidth="1*"/>
- <thead>
- <row>
- <entry>Nome da Propriedade</entry>
- <entry>Propósito</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
-
<literal>hibernate.cache.provider_class</literal>
- </entry>
- <entry>
- O nome da classe de um
<literal>CacheProvider</literal> customizado.
- <para>
- <emphasis
role="strong">Ex.</emphasis>
-
<literal>classname.of.CacheProvider</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
-
<literal>hibernate.cache.use_minimal_puts</literal>
- </entry>
- <entry>
- Otimizar operação de cachê de segundo nível para minimizar
escritas,
- ao custo de leituras mais frequantes. Esta configuração é
mais útil
- para cachês clusterizados e, no Hibernate3, é habilitado por
default
- para implementações de cachê clusterizar.
- <para>
- <emphasis
role="strong">Ex.</emphasis>
- <literal>true|false</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
-
<literal>hibernate.cache.use_query_cache</literal>
- </entry>
- <entry>
- Habilita a cache de consultas, Mesmo assim, consultas
individuais ainda tem que ser
- habilitadas para o cache.
- <para>
- <emphasis
role="strong">Ex.</emphasis>
- <literal>true|false</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
-
<literal>hibernate.cache.use_second_level_cache</literal>
- </entry>
- <entry>
- May be used to completely disable the second level cache,
which is enabled
- by default for classes which specify a
<literal><cache></literal>
- mapping.
- Pode ser usada para desabilitar completamente ocache de
segundo nível,
- o qual está habilitado por default para classes que
especificam
- um mapeamento
<literal><cache></literal>.
-
- <para>
- <emphasis
role="strong">Ex.</emphasis>
- <literal>true|false</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
-
<literal>hibernate.cache.query_cache_factory</literal>
- </entry>
- <entry>
- O nome de uma classe que implementa a interface
- <literal>QueryCache</literal> personalizada, por
- default, um
<literal>StandardQueryCache</literal>
- criado automaticamente.
- <para>
- <emphasis
role="strong">Ex.</emphasis>
- <literal>classname.of.QueryCache</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <literal>hibernate.cache.region_prefix</literal>
- </entry>
- <entry>
- Um prefixo para usar nos nomes da área especial
- do cachê de segundo nível.
- <para>
- <emphasis
role="strong">Ex.</emphasis>
- <literal>prefix</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
-
<literal>hibernate.cache.use_structured_entries</literal>
- </entry>
- <entry>
- Forces Hibernate to store data in the second-level cache
- in a more human-friendly format.
- Força o Hibernate armazenar dados no cachê se segundo
- nível em um formato mais legivel.
- <para>
- <emphasis
role="strong">Ex.</emphasis>
- <literal>true|false</literal>
- </para>
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table frame="topbot"
id="configuration-transaction-properties" revision="9">
- <title>Propriedades de Transação do Hibernate</title>
- <tgroup cols="2">
- <colspec colname="c1" colwidth="1*"/>
- <colspec colname="c2" colwidth="1*"/>
- <thead>
- <row>
- <entry>Nome da Propriedade</entry>
- <entry>Propósito</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
-
<literal>hibernate.transaction.factory_class</literal>
- </entry>
- <entry>
- O nome da clase de um a
<literal>TransactionFactory</literal>
- para usar com API <literal>Transaction</literal>
- ( por default JDBCTransactionFactory).
- <para>
- <emphasis
role="strong">Ex.</emphasis>
-
<literal>classname.of.TransactionFactory</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <literal>jta.UserTransaction</literal>
- </entry>
- <entry>
- Um nome JNDI usado pelo
<literal>JTATransactionFactory</literal>
- para obter uma <literal>UserTransaction</literal>
JTA a partir
- do servidor de aplicação.
- <para>
- <emphasis
role="strong">Ex.</emphasis>
- <literal>jndi/composite/name</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
-
<literal>hibernate.transaction.manager_lookup_class</literal>
- </entry>
- <entry>
- O nome da classe de um
<literal>TransactionManagerLookup</literal>
- – requerido quando caching a nível JVM esta habilitado ou
quando
- estivermos usando um generator hilo em um ambiente JTA.
- <para>
- <emphasis
role="strong">Ex.</emphasis>
-
<literal>classname.of.TransactionManagerLookup</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
-
<literal>hibernate.transaction.flush_before_completion</literal>
- </entry>
- <entry>
- Se habilitado, a sessão será automaticamente limpa antes da
fase de
- conclusão da transação. É preferivel a gerência interna e
- automática do contexto da sessão, veja
- <xref
linkend="architecture-current-session"/>
- <para>
- <emphasis
role="strong">Ex.</emphasis>
- <literal>true</literal> |
<literal>false</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
-
<literal>hibernate.transaction.auto_close_session</literal>
- </entry>
- <entry>
- Se habilitado, a sessão será automaticamente fechada após a
fase de
- conclusão da transação. É preferivel a gerência interna e
- automática do contexto da sessão, veja
- <xref
linkend="architecture-current-session"/>
- <para>
- <emphasis
role="strong">Ex.</emphasis>
- <literal>true</literal> |
<literal>false</literal>
- </para>
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table frame="topbot" id="configuration-misc-properties"
revision="10">
- <title>Propriedades Variadas</title>
- <tgroup cols="2">
- <colspec colname="c1" colwidth="1*"/>
- <colspec colname="c2" colwidth="1*"/>
- <thead>
- <row>
- <entry>Nome da Propriedade</entry>
- <entry>Propósito</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
-
<literal>hibernate.current_session_context_class</literal>
- </entry>
- <entry>
- Forneçe uma estratégia (personalizada) para extensão
- da <literal>Session</literal>
"corrente". Veja
- <xref
linkend="architecture-current-session"/> para
- mais informação sobre estratégias internas.
- <para>
- <emphasis
role="strong">Ex.</emphasis>
- <literal>jta</literal> |
<literal>thread</literal> |
- <literal>managed</literal> |
<literal>custom.Class</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <literal>hibernate.query.factory_class</literal>
- </entry>
- <entry>
- Escolha a implementação de análise HQL.
- <para>
- <emphasis
role="strong">eg.</emphasis>
-
<literal>org.hibernate.hql.ast.ASTQueryTranslatorFactory</literal> or
-
<literal>org.hibernate.hql.classic.ClassicQueryTranslatorFactory</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <literal>hibernate.query.substitutions</literal>
- </entry>
- <entry>
- Mapeamento a partir de símbolos em consultas HQL para
- símbolos SQL( símbolos devem ser funções ou nome literais
- , por exemplo).
- <para>
- <emphasis
role="strong">eg.</emphasis>
- <literal>hqlLiteral=SQL_LITERAL,
hqlFunction=SQLFUNC</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <literal>hibernate.hbm2ddl.auto</literal>
- </entry>
- <entry>
- Automaticamente valida ou exporta schema DDL para o banco de
- dados quando o <literal>SessionFactory</literal>
é criads.
- Com <literal>create-drop</literal>, o schema do
banco de dados
- será excluido quando a
<literal>create-drop</literal> for
- fechada esplicitamente.
- <para>
- <emphasis
role="strong">Ex.</emphasis>
- <literal>validate</literal> |
<literal>update</literal> |
- <literal>create</literal> |
<literal>create-drop</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry>
-
<literal>hibernate.cglib.use_reflection_optimizer</literal>
- </entry>
- <entry>
- Habilita o uso de CGLIB em vez de reflexão em tempo de
execução
- ( propriedade a nível de sistema). Reflexão pode algumas
vezes ser ú
- til quando controlar erros, note que o Hibernate sempre irá
requerer a CGLIB
- mesmo se você desligar o otimizador. Você não pode determinar
esta
- propriedade no hibernate.cfg.xml.
- <para>
- <emphasis
role="strong">Ex.</emphasis>
- <literal>true</literal> |
<literal>false</literal>
- </para>
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <sect2 id="configuration-optional-dialects"
revision="1">
- <title>Dialetos SQL</title>
-
- <para>
- Você deve sempre determinar a propriedade
<literal>hibernate.dialect</literal>
- para a subclasse de
<literal>org.hibernate.dialect.Dialect</literal> correta de seu
- banco de dados. Se você especificar um dialeto, Hibernate usará defaults
lógicos
- para qualquer um das outras propriedades listadas abaixo, reduzindo o
esforço de
- especificá-los manualmente.
- </para>
-
- <table frame="topbot" id="sql-dialects"
revision="2">
- <title>Hibernate SQL Dialects
(<literal>hibernate.dialect</literal>)</title>
- <tgroup cols="2">
- <colspec colwidth="1*"/>
- <colspec colwidth="2.5*"/>
- <thead>
- <row>
- <entry>RDBMS</entry>
- <entry>Dialect</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>DB2</entry>
<entry><literal>org.hibernate.dialect.DB2Dialect</literal></entry>
- </row>
- <row>
- <entry>DB2 AS/400</entry>
<entry><literal>org.hibernate.dialect.DB2400Dialect</literal></entry>
- </row>
- <row>
- <entry>DB2 OS390</entry>
<entry><literal>org.hibernate.dialect.DB2390Dialect</literal></entry>
- </row>
- <row>
- <entry>PostgreSQL</entry>
<entry><literal>org.hibernate.dialect.PostgreSQLDialect</literal></entry>
- </row>
- <row>
- <entry>MySQL</entry>
<entry><literal>org.hibernate.dialect.MySQLDialect</literal></entry>
- </row>
- <row>
- <entry>MySQL with InnoDB</entry>
<entry><literal>org.hibernate.dialect.MySQLInnoDBDialect</literal></entry>
- </row>
- <row>
- <entry>MySQL with MyISAM</entry>
<entry><literal>org.hibernate.dialect.MySQLMyISAMDialect</literal></entry>
- </row>
- <row>
- <entry>Oracle (any version)</entry>
<entry><literal>org.hibernate.dialect.OracleDialect</literal></entry>
- </row>
- <row>
- <entry>Oracle 9i/10g</entry>
<entry><literal>org.hibernate.dialect.Oracle9Dialect</literal></entry>
- </row>
- <row>
- <entry>Sybase</entry>
<entry><literal>org.hibernate.dialect.SybaseDialect</literal></entry>
- </row>
- <row>
- <entry>Sybase Anywhere</entry>
<entry><literal>org.hibernate.dialect.SybaseAnywhereDialect</literal></entry>
- </row>
- <row>
- <entry>Microsoft SQL Server</entry>
<entry><literal>org.hibernate.dialect.SQLServerDialect</literal></entry>
- </row>
- <row>
- <entry>SAP DB</entry>
<entry><literal>org.hibernate.dialect.SAPDBDialect</literal></entry>
- </row>
- <row>
- <entry>Informix</entry>
<entry><literal>org.hibernate.dialect.InformixDialect</literal></entry>
- </row>
- <row>
- <entry>HypersonicSQL</entry>
<entry><literal>org.hibernate.dialect.HSQLDialect</literal></entry>
- </row>
- <row>
- <entry>Ingres</entry>
<entry><literal>org.hibernate.dialect.IngresDialect</literal></entry>
- </row>
- <row>
- <entry>Progress</entry>
<entry><literal>org.hibernate.dialect.ProgressDialect</literal></entry>
- </row>
- <row>
- <entry>Mckoi SQL</entry>
<entry><literal>org.hibernate.dialect.MckoiDialect</literal></entry>
- </row>
- <row>
- <entry>Interbase</entry>
<entry><literal>org.hibernate.dialect.InterbaseDialect</literal></entry>
- </row>
- <row>
- <entry>Pointbase</entry>
<entry><literal>org.hibernate.dialect.PointbaseDialect</literal></entry>
- </row>
- <row>
- <entry>FrontBase</entry>
<entry><literal>org.hibernate.dialect.FrontbaseDialect</literal></entry>
- </row>
- <row>
- <entry>Firebird</entry>
<entry><literal>org.hibernate.dialect.FirebirdDialect</literal></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- </sect2>
-
- <sect2 id="configuration-optional-outerjoin"
revision="4">
- <title>Recuperação por união externa (Outer Join
Fetching)</title>
-
- <para>
- Se seu banco de dados suporta Recuperação por união externa (Outer Join
Fetching) no estilo ANSI,
- Oracle ou Sybase, A recuperação por união externa (Outer Join Fetching)
frequentemente aumentará
- o desempenho limitando o número de chamadas (round trips) ao banco de
dados( ao custo de
- possivelmente mais trabalho desempenhado pelo próprio banco de dados). A
recuperação por
- união externa (Outer Join Fetching)permite um gráfico completo de objetos
conectados
- por muitos-para-um, um-para-muitos, muitos-para-muitos e associações
um-para-um para ser
- recuperadas em um simples instrução SQL SELECT .
-
- </para>
-
- <para>
- A recuperação por união externa (Outer Join Fetching) pode ser
desabilitado
- <emphasis>globalmente</emphasis> setando a propriedade
- <literal>hibernate.max_fetch_depth</literal> para
<literal>0</literal>.
- Uma valor 1 ou maior habilita o outer join fetching para associações
um-para-um
- e muitos-para-umos cujos quais tem sido mapeado com
<literal>fetch="join"</literal>.
- </para>
-
- <para>
- Veja <xref linkend="performance-fetching"/> para mais
informações.
- </para>
-
- </sect2>
-
- <sect2 id="configuration-optional-binarystreams"
revision="1">
- <title>Fluxos Binários (Binary Streams)</title>
-
- <para>
- O Oracle limita o tamanho de arrays de
<literal>byte</literal> que pode ser
- passado para/de o driver JDBC. Se você desejar usar grandes instâncias de
- tipos <literal>binary</literal> ou
<literal>serializable</literal>, você
- deve habilitar
<literal>hibernate.jdbc.use_streams_for_binary</literal>.
- <emphasis>Essa é uma configuração que só pode ser feita a nível de
sistema.</emphasis>
- </para>
-
- </sect2>
-
- <sect2 id="configuration-optional-cacheprovider"
revision="2">
- <title>Cachê de segundo nível e query</title>
-
- <para>
- As propriedades prefixadas pelo
<literal>hibernate.cache</literal>
- permite você usar um sistema de cachê de segundo nível
- em um processo executado em clustercom Hibernate.
- Veja <xref linkend="performance-cache"/> para mais
detalhes.
- </para>
-
- </sect2>
-
- <sect2 id="configuration-optional-querysubstitution">
- <title>Substituições na Linguagem de Consulta</title>
-
- <para>
- Você pode definir novos símbolos de consulta Hibernate usando
- <literal>hibernate.query.substitutions</literal>.
- Por exemplo:
- </para>
-
- <programlisting>hibernate.query.substitutions true=1,
false=0</programlisting>
-
- <para>
- Faria com que os símbolos <literal>true</literal> e
<literal>false</literal>
- passasem a ser traduzidos para literais inteiro no SQL gerado.
- </para>
-
- <programlisting>hibernate.query.substitutions
toLowercase=LOWER</programlisting>
-
- <para>
- permitirá você renomear a função <literal>LOWER</literal> no
SQL.
- </para>
-
- </sect2>
-
- <sect2 id="configuration-optional-statistics"
revision="2">
- <title>Estatísticas do Hibernate</title>
-
- <para>
- If you enable
<literal>hibernate.generate_statistics</literal>, Hibernate will
- expose a number of metrics that are useful when tuning a running system
via
- <literal>SessionFactory.getStatistics()</literal>. Hibernate
can even be configured
- to expose these statistics via JMX. Read the Javadoc of the interfaces
in
- <literal>org.hibernate.stats</literal> for more information.
-
- Se você habilitar
<literal>hibernate.generate_statistics</literal>, o Hibernate
- exibirá um número de métricas bastante útil ao ajustar um sistema via
- <literal>SessionFactory.getStatistics()</literal>. O
Hibernate pode até ser
- configurado para exibir essas estatísticas via JMX. Leia o Javadoc da
interface
- <literal>org.hibernate.stats</literal> para mais
informações.
- </para>
-
- </sect2>
- </sect1>
-
- <sect1 id="configuration-logging">
- <title>Logging</title>
-
- <para>
- Hibernate registra vários eventos usando Apache commons-logging.
- </para>
-
- <para>
- O serviço commons-logging direcionará a saída para o Apache Log4j
- ( se você incluir <literal>log4j.jar</literal>r no seu classpath)
ou
- JDK1.4 logging( se estiver em uso JDK1.4 ou maior). Você pode fazer o
- download do Log4j a partir de
<literal>http://jakarta.apache.org</literal>.
- Para usar Log4j você necessitará colocar um arquivo
- <literal>log4j.properties</literal> no seu classpath, um exemplo
de arquivo
- de propriedades é distribuído com o Hibernate no diretório
- <literal>src/</literal>.
-
- </para>
-
- <para>
- We strongly recommend that you familiarize yourself with Hibernate's log
- messages. A lot of work has been put into making the Hibernate log as
- detailed as possible, without making it unreadable. It is an essential
- troubleshooting device. The most interesting log categories are the
- following:
-
- Nós recomendamos enfaticamente que você se familiarize-se com mensagens de
- log do Hibernate. Uma parte do trabalho tem sido posto em fazer o log
- Hibernate tão detalhado quanto possível, sem fazê-lo ilegível.
- É um essencial dispositivos de controle de erros. As categorias de log
- mais interessantes são as seguintes:
- </para>
-
- <table frame="topbot" id="log-categories"
revision="2">
- <title>Categorias de Log do Hibernate</title>
- <tgroup cols="2">
- <colspec colwidth="1*"/>
- <colspec colwidth="2.5*"/>
- <thead>
- <row>
- <entry>Categoria</entry>
- <entry>Função</entry>
- </row>
- </thead>
- <tbody>
- <row>
-
<entry><literal>org.hibernate.SQL</literal></entry>
- <entry>Registra todas as instruções SQL DML a medida
que elas são executadas</entry>
- </row>
- <row>
-
<entry><literal>org.hibernate.type</literal></entry>
- <entry>Registra todos os parâmetros JDBC</entry>
- </row>
- <row>
-
<entry><literal>org.hibernate.tool.hbm2ddl</literal></entry>
- <entry>Registra todas as instruções SQL DDL a medida
que elas são executadas</entry>
- </row>
- <row>
-
<entry><literal>org.hibernate.pretty</literal></entry>
- <entry>
- Log the state of all entities (max 20 entities)
associated
- with the session at flush time
- Registra o estado de todas as entidades (máximo 20
entidades)
- associadas a session no momento da limpeza (flush).
- </entry>
- </row>
- <row>
-
<entry><literal>org.hibernate.cache</literal></entry>
- <entry>Registra todas as atividades de cachê de segundo
nível</entry>
- </row>
- <row>
-
<entry><literal>org.hibernate.transaction</literal></entry>
- <entry>Registra atividades relacionada a
transação</entry>
- </row>
- <row>
-
<entry><literal>org.hibernate.jdbc</literal></entry>
- <entry>Registra todas as requisições de recursos
JDBC</entry>
- </row>
- <row>
-
<entry><literal>org.hibernate.hql.ast.AST</literal></entry>
- <entry>
- Registra instruções SQL e HQL durante a análise da
consultas
- </entry>
- </row>
- <row>
-
<entry><literal>org.hibernate.secure</literal></entry>
- <entry>Registra todas as requisições de autorização
JAAS</entry>
- </row>
- <row>
-
<entry><literal>org.hibernate</literal></entry>
- <entry>
- Registra tudo ( uma parte das informações, mas muito
- útil para controle de erros )
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <para>
- Quando desenvolver aplicações com Hibernate, você deve quase sempre trabalhar
com
- debug <literal>debug</literal> para a categoria
<literal>org.hibernate.SQL</literal>,
- ou, alternativamente, a com a propriedade
<literal>hibernate.show_sql</literal> habilitada.
- </para>
-
-
- </sect1>
-
- <sect1 id="configuration-namingstrategy">
- <title>Implementado uma
<literal>NamingStrategy</literal></title>
-
- <para>
- A interface <literal>org.hibernate.cfg.NamingStrategy</literal>
permite você
- especificar um "padrão de nomeação" para objetos do banco de dados
e elementos schema.
- </para>
-
- <para>
- Você deve criar regras para a geração automaticamente de identificadores
- do banco de dados a partir de identificadores Java ou para processar
- colunas "computadas" e nomes de tabelas dado o arquivo de
mapeamento
- para nomes "físicos" de tabelas e colunas. Esta característica
ajuda a
- reduzir a verbosidade do documento de mapeamento, eliminando interferências
- repetitivas( <literal>TBL_</literal>prefixos, por exemplo). A
estratégia
- default usada pelo Hibernate é completamente mínima.
- </para>
-
- <para>
- Você pode especificar uma estratégia diferente ao chamar
- <literal>Configuration.setNamingStrategy()</literal> antes de
adicionar
- os mapeamentos:
- </para>
-
- <programlisting><![CDATA[SessionFactory sf = new Configuration()
- .setNamingStrategy(ImprovedNamingStrategy.INSTANCE)
- .addFile("Item.hbm.xml")
- .addFile("Bid.hbm.xml")
- .buildSessionFactory();]]></programlisting>
-
- <para>
- <literal>org.hibernate.cfg.ImprovedNamingStrategy</literal> é uma
estratégia
- interna que pode ser um ponto de começo útil para algumas aplicações.
- </para>
-
- </sect1>
-
- <sect1 id="configuration-xmlconfig" revision="2">
- <title>Arquivo de configuração XML</title>
-
- <para>
- Uma maneira alternativa de configuração é especificar uma configuração
completa
- em um arquivo chamado <literal>hibernate.cfg.xml</literal>. Este
arquivo pode
- ser usado como um substituto para o arquivo
<literal>hibernate.properties</literal>
- ou, se ambos estão presentes, sobrescrever propriedades.
- </para>
-
- <para>
- The XML configuration file is by default expected to be in the root o
- your <literal>CLASSPATH</literal>. Here is an example:
- O arquivo XML de configuração é por default esperado para estar na
- raiz do seu <literal>CLASSPATH</literal>. Veja um exemplo:
- </para>
-
- <programlisting><![CDATA[<?xml version='1.0'
encoding='utf-8'?>
-<!DOCTYPE hibernate-configuration PUBLIC
- "-//Hibernate/Hibernate Configuration DTD//EN"
- "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
-
-<hibernate-configuration>
-
- <!-- a SessionFactory instance listed as /jndi/name -->
- <session-factory
- name="java:hibernate/SessionFactory">
-
- <!-- properties -->
- <property
name="connection.datasource">java:/comp/env/jdbc/MyDB</property>
- <property
name="dialect">org.hibernate.dialect.MySQLDialect</property>
- <property name="show_sql">false</property>
- <property name="transaction.factory_class">
- org.hibernate.transaction.JTATransactionFactory
- </property>
- <property
name="jta.UserTransaction">java:comp/UserTransaction</property>
-
- <!-- mapping files -->
- <mapping resource="org/hibernate/auction/Item.hbm.xml"/>
- <mapping resource="org/hibernate/auction/Bid.hbm.xml"/>
-
- <!-- cache settings -->
- <class-cache class="org.hibernate.auction.Item"
usage="read-write"/>
- <class-cache class="org.hibernate.auction.Bid"
usage="read-only"/>
- <collection-cache collection="org.hibernate.auction.Item.bids"
usage="read-write"/>
-
- </session-factory>
-
-</hibernate-configuration>]]></programlisting>
-
- <para>
- Como você pode ver, a vantagem deste enfoque é a externalização dos nomes dos
- arquivos de mapeamento para configuração. O
<literal>hibernate.cfg.xml</literal>
- também é mais conveniente caso você tenha que ajustar o cache do Hibernate.
- Note que a escolha é sua em usar
<literal>hibernate.properties</literal> ou
- <literal>hibernate.cfg.xml</literal>, ambos são equivalente, à
exceção dos benefícios
- acima mencionados de usar a sintaxe de XML.
- </para>
-
- <para>
- Com a configuração do XML, iniciar o Hibernate é então tão simples como
- </para>
-
- <programlisting><![CDATA[SessionFactory sf = new
Configuration().configure().buildSessionFactory();]]></programlisting>
-
- <para>
- You can pick a different XML configuration file using
- </para>
-
- <programlisting><![CDATA[SessionFactory sf = new Configuration()
- .configure("catdb.cfg.xml")
- .buildSessionFactory();]]></programlisting>
-
- </sect1>
-
- <sect1 id="configuration-j2ee" revision="1">
- <title>Integração com servidores de aplicação J2EE</title>
-
- <para>
- O Hibernate tem os seguintes pontos da integração para o infraestrutura de
J2EE:
- </para>
-
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>DataSources gerenciados pelo container</emphasis>:
O Hibernate pode
- usar conexões JDBC gerenciadas pelo Container e fornecidas pela JNDI.
Geralmente,
- um <literal>TransactionManager</literal> compatível com JTA e
um
- <literal>ResourceManager</literal> cuidam do gerenciamento da
transação ( CMT ),
- especialmente em transações distribuídas manipuladas através de vários
DataSources.
- Naturalmente, você também pode demarcar os limites das transações
programaticamente (BMT)
- ou você poderia querer usar a API opcional do Hibernate
<literal>Transaction</literal>
- para esta manter seu código portável.
- </para>
- </listitem>
- </itemizedlist>
-
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>Ligação (binding) automática a JNDI</emphasis>: O
Hibernate pode
- associar sua <literal>SessionFactory</literal> a JNDI depois
de iniciado.
- </para>
- </listitem>
- </itemizedlist>
-
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>Ligação (binding) Session na JTA:</emphasis>
- A <literal>Session</literal> do Hibernate pode
automaticamente ser ligada
- ao escopo da transações JTA. Simplesmente localizando a
<literal>SessionFactory</literal>
- da JNDI e obtendo a<literal>Session</literal> corrente. Deixe
o Hibernate cuidar
- da limpeza e encerramento da <literal>Session</literal>
quando as transações JTA
- terminarem. A Demarcação de transação pode ser declarativa (CMT) ou
- programática(BMT/Transação do usuário).
- </para>
- </listitem>
- </itemizedlist>
-
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>JMX deployment:</emphasis> Se você usa um JMX
servidor de
- aplicações capaz (ex. Jboss AS), você pode fazer a instação do Hibernate
- como um Mbean controlado. Isto evita ter que iniciar uma linha de
- código para construir sua <literal>SessionFactory</literal>
de uma
- <literal>Configuration</literal>. O container iniciará seu
- <literal>HibernateService</literal>, e idealmente também
cuidará
- das dependências de serviços (DataSources, têm que estar disponíveis
- antes do Hibernate iniciar, etc.).
- </para>
- </listitem>
- </itemizedlist>
-
- <para>
- Dependendo em seu ambiente, você poderia ter que ajustar a opção de
configuração
- <literal>hibernate.connection.aggressive_release</literal> para
verdadeiro ( true ),
- se seu servidor de aplicações lançar exeções "retenção de
conecção".
- </para>
-
- <sect2 id="configuration-optional-transactionstrategy"
revision="3">
- <title>Configuração de estratégia de transação</title>
-
- <para>
- A API Hibernate <literal>Session</literal> é independente de
qualquer sistema de
- demarcação de transação em sua arquitetura. Se você deixar o Hibernate
usar
- a JDBC diretamente, através de um pool de conexões, você pode inicializar
e
- encerrar suas transações chamando a API JDBC. Se você rodar em um
servidor de
- aplicações J2EE, você poderá usar transações controladas por beans e
chamar
- a API JTA e <literal>UserTransaction</literal> quando
necessário.
-
- </para>
-
- <para>
- Para manter seu código portável entre estes dois ( e outros ) ambientes,
recomendamos
- a API Hibernate <literal>Transaction</literal>, que envolve e
esconde o sistema subjacente.
- Você tem que especificar um classe construtora para
<literal>Transaction</literal> instanciar
- ajustando a propriedade de configuração do
<literal>hibernate.transaction.factory_class</literal>.
-
- </para>
-
- <para>
- Existem três escolhas (internas) padrões:
- </para>
-
- <variablelist spacing="compact">
- <varlistentry>
-
<term><literal>org.hibernate.transaction.JDBCTransactionFactory</literal></term>
- <listitem>
- <para>delegada as transações (JDBC)a bases de dados
(Padrão)</para>
-
- </listitem>
- </varlistentry>
- <varlistentry>
-
<term><literal>org.hibernate.transaction.JTATransactionFactory</literal></term>
- <listitem>
- <para>
- delegada a transação a um container gerenciador se a
transação
- existente estiver de acordo neste contexto (ex: método bean
sessão EJB),
- se não uma nova transação é iniciada e uma transação
controlado por
- um bean é usada.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
-
<term><literal>org.hibernate.transaction.CMTTransactionFactory</literal></term>
- <listitem>
- <para>delega para um container gerenciador de transações
JTA</para>
- </listitem>
- </varlistentry>
- </variablelist>
-
- <para>
- Você também pode definir suas próprias estratégias de transação ( para um
serviço de
- transação CORBA por exemplo).
- </para>
-
- <para>
- Algumas características no Hibernate (ex., o cache de segundo nível,
sessões contextuais
- com JTA, etc.) requerem acesso a JTA
<literal>TransactionManager</literal> em um ambiente
- controlado. Em um servidor de aplicação você tem que especificar como o
Hibernate pode
- obter uma referência para a
<literal>TransactionManager</literal>, pois o J2EE não
- padronize um mecanismo simples :
- </para>
-
- <table frame="topbot" id="jtamanagerlookup"
revision="1">
- <title>Gerenciadores de transações JTA</title>
- <tgroup cols="2">
- <colspec colwidth="2.5*"/>
- <colspec colwidth="1*"/>
- <thead>
- <row>
- <entry>Transaction Factory</entry>
- <entry align="center">Application
Server</entry>
- </row>
- </thead>
- <tbody>
- <row>
-
<entry><literal>org.hibernate.transaction.JBossTransactionManagerLookup</literal></entry>
- <entry align="center">JBoss</entry>
- </row>
- <row>
-
<entry><literal>org.hibernate.transaction.WeblogicTransactionManagerLookup</literal></entry>
- <entry align="center">Weblogic</entry>
- </row>
- <row>
-
<entry><literal>org.hibernate.transaction.WebSphereTransactionManagerLookup</literal></entry>
- <entry
align="center">WebSphere</entry>
- </row>
- <row>
-
<entry><literal>org.hibernate.transaction.WebSphereExtendedJTATransactionLookup</literal></entry>
- <entry align="center">WebSphere
6</entry>
- </row>
- <row>
-
<entry><literal>org.hibernate.transaction.OrionTransactionManagerLookup</literal></entry>
- <entry align="center">Orion</entry>
- </row>
- <row>
-
<entry><literal>org.hibernate.transaction.ResinTransactionManagerLookup</literal></entry>
- <entry align="center">Resin</entry>
- </row>
- <row>
-
<entry><literal>org.hibernate.transaction.JOTMTransactionManagerLookup</literal></entry>
- <entry align="center">JOTM</entry>
- </row>
- <row>
-
<entry><literal>org.hibernate.transaction.JOnASTransactionManagerLookup</literal></entry>
- <entry align="center">JOnAS</entry>
- </row>
- <row>
-
<entry><literal>org.hibernate.transaction.JRun4TransactionManagerLookup</literal></entry>
- <entry align="center">JRun4</entry>
- </row>
- <row>
-
<entry><literal>org.hibernate.transaction.BESTransactionManagerLookup</literal></entry>
- <entry align="center">Borland
ES</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- </sect2>
-
- <sect2 id="configuration-optional-jndi" revision="3">
- <title><literal>SessionFactory</literal> ligada a
JNDI</title>
-
- <para>
- Uma <literal>SessionFactory</literal> de Hibernate ligada a
JNDI pode simplificar
- a localização da fabrica e a criação de novas
<literal>Session</literal>s.
- Observe que isto não relacionado a um
<literal>Datasource</literal> ligado
- a JNDI, simplemente ambos usam o mesmo registro!
- </para>
-
- <para>
- If you wish to have the <literal>SessionFactory</literal>
bound to a JNDI namespace, specify
- a name (eg. <literal>java:hibernate/SessionFactory</literal>)
using the property
- <literal>hibernate.session_factory_name</literal>. If this
property is omitted, the
- <literal>SessionFactory</literal> will not be bound to JNDI.
(This is especially useful in
- environments with a read-only JNDI default implementation, e.g. Tomcat.)
- </para>
-
- <para>
- When binding the <literal>SessionFactory</literal> to JNDI,
Hibernate will use the values of
- <literal>hibernate.jndi.url</literal>,
<literal>hibernate.jndi.class</literal> to instantiate
- an initial context. If they are not specified, the default
<literal>InitialContext</literal>
- will be used.
- </para>
-
- <para>
- Hibernate will automatically place the
<literal>SessionFactory</literal> in JNDI after
- you call <literal>cfg.buildSessionFactory()</literal>. This
means you will at least have
- this call in some startup code (or utility class) in your application,
unless you use
- JMX deployment with the <literal>HibernateService</literal>
(discussed later).
- </para>
-
- <para>
- If you use a JNDI <literal>SessionFactory</literal>, an EJB
or any other class may
- obtain the <literal>SessionFactory</literal> using a JNDI
lookup.
- </para>
-
- <para>
- We recommend that you bind the
<literal>SessionFactory</literal> to JNDI in
- a managend environment and use a <literal>static</literal>
singleton otherwise.
- To shield your application code from these details, we also recommend to
hide the
- actual lookup code for a <literal>SessionFactory</literal> in
a helper class,
- such as <literal>HibernateUtil.getSessionFactory()</literal>.
Note that such a
- class is also a convenient way to startup Hibernate—see chapter
1.
- </para>
-
- </sect2>
-
- <sect2 id="configuration-j2ee-currentsession"
revision="4">
- <title>Current Session context management with JTA</title>
-
- <para>
- The easiest way to handle <literal>Session</literal>s and
transactions is
- Hibernates automatic "current"
<literal>Session</literal> management.
- See the discussion of <xref
linkend="architecture-current-session">current sessions</xref>.
- Using the <literal>"jta"</literal> session context,
if there is no Hibernate
- <literal>Session</literal> associated with the current JTA
transaction, one will
- be started and associated with that JTA transaction the first time you call
- <literal>sessionFactory.getCurrentSession()</literal>. The
<literal>Session</literal>s
- retrieved via <literal>getCurrentSession()</literal> in
<literal>"jta"</literal> context
- will be set to automatically flush before the transaction completes, close
- after the transaction completes, and aggressively release JDBC connections
- after each statement. This allows the
<literal>Session</literal>s to
- be managed by the life cycle of the JTA transaction to which it is
associated,
- keeping user code clean of such management concerns. Your code can either
use
- JTA programmatically through <literal>UserTransaction</literal>,
or (recommended
- for portable code) use the Hibernate
<literal>Transaction</literal> API to set
- transaction boundaries. If you run in an EJB container, declarative
transaction
- demarcation with CMT is preferred.
- </para>
-
- </sect2>
-
- <sect2 id="configuration-j2ee-jmx" revision="1">
- <title>JMX deployment</title>
-
- <para>
- The line <literal>cfg.buildSessionFactory()</literal> still
has to be executed
- somewhere to get a <literal>SessionFactory</literal> into
JNDI. You can do this
- either in a <literal>static</literal> initializer block (like
the one in
- <literal>HibernateUtil</literal>) or you deploy Hibernate as
a <emphasis>managed
- service</emphasis>.
- </para>
-
- <para>
- Hibernate is distributed with
<literal>org.hibernate.jmx.HibernateService</literal>
- for deployment on an application server with JMX capabilities, such as
JBoss AS.
- The actual deployment and configuration is vendor specific. Here is an
example
- <literal>jboss-service.xml</literal> for JBoss 4.0.x:
- </para>
-
- <programlisting><![CDATA[<?xml version="1.0"?>
-<server>
-
-<mbean code="org.hibernate.jmx.HibernateService"
- name="jboss.jca:service=HibernateFactory,name=HibernateFactory">
-
- <!-- Required services -->
- <depends>jboss.jca:service=RARDeployer</depends>
- <depends>jboss.jca:service=LocalTxCM,name=HsqlDS</depends>
-
- <!-- Bind the Hibernate service to JNDI -->
- <attribute
name="JndiName">java:/hibernate/SessionFactory</attribute>
-
- <!-- Datasource settings -->
- <attribute name="Datasource">java:HsqlDS</attribute>
- <attribute
name="Dialect">org.hibernate.dialect.HSQLDialect</attribute>
-
- <!-- Transaction integration -->
- <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>
-
- <!-- Fetching options -->
- <attribute name="MaximumFetchDepth">5</attribute>
-
- <!-- Second-level caching -->
- <attribute name="SecondLevelCacheEnabled">true</attribute>
- <attribute
name="CacheProviderClass">org.hibernate.cache.EhCacheProvider</attribute>
- <attribute name="QueryCacheEnabled">true</attribute>
-
- <!-- Logging -->
- <attribute name="ShowSqlEnabled">true</attribute>
-
- <!-- Mapping files -->
- <attribute
name="MapResources">auction/Item.hbm.xml,auction/Category.hbm.xml</attribute>
-
-</mbean>
-
-</server>]]></programlisting>
-
- <para>
- This file is deployed in a directory called
<literal>META-INF</literal> and packaged
- in a JAR file with the extension <literal>.sar</literal>
(service archive). You also need
- to package Hibernate, its required third-party libraries, your compiled
persistent classes,
- as well as your mapping files in the same archive. Your enterprise beans
(usually session
- beans) may be kept in their own JAR file, but you may include this EJB
JAR file in the
- main service archive to get a single (hot-)deployable unit. Consult the
JBoss AS
- documentation for more information about JMX service and EJB deployment.
- </para>
-
- </sect2>
-
- </sect1>
-
-</chapter>
-
+<chapter id="session-configuration" revision="1">
+
+ <title>Configuração</title>
+
+ <para>
+ Devido ao fato de o Hibernate ser projetado para operar em vários ambientes
diferentes,
+ há um grande número de parâmetros de configuração. Felizmente, a maioria tem
valores default
+ lógicos e o Hibernate é distribuído com um arquivo
<literal>hibernate.properties</literal>
+ de exemplo no <literal>etc/</literal> que mostra várias opções.
Apenas coloque o arquivo
+ de exemplo no seu classpath e personalize-o.
+ </para>
+
+ <sect1 id="configuration-programmatic" revision="1">
+ <title>1.11 Configuração programática</title>
+
+ <para>
+ Uma instância de
<literal>org.hibernate.cfg.Configuration</literal>
+ representa um conjunto inteiro de mapeamentos de tipos Java da aplicação para
+ um banco de dados SQL. O <literal>Configuration</literal> é usado
para construir
+ uma <literal>SessionFactory</literal> (imutável). Os mapeamentos
são compilados
+ a partir de arquivos de mapeamento XML.
+
+ </para>
+
+ <para>
+ Você pode obter uma instância <literal>Configuration</literal>
intanciando-
+ o diretamente e especificando documentos de mapeamento XML. Se o arquivo
+ de mapeamento estão no classpath, use use
<literal>addResource()</literal>:
+ </para>
+
+ <programlisting><![CDATA[Configuration cfg = new Configuration()
+ .addResource("Item.hbm.xml")
+ .addResource("Bid.hbm.xml");]]></programlisting>
+
+ <para>
+ Uma alternativa (às vezes melhor) é especificar a classe mapeada,
+ e permitir que o Hibernate encontre o documento de mapeamento para você:
+ </para>
+
+ <programlisting><![CDATA[Configuration cfg = new Configuration()
+ .addClass(org.hibernate.auction.Item.class)
+ .addClass(org.hibernate.auction.Bid.class);]]></programlisting>
+
+ <para>
+ Então o Hibernate procurará pelos arquivos de mapeamento chamados
+ <literal>/org/hibernate/auction/Item.hbm.xml</literal> e
+ <literal>/org/hibernate/auction/Bid.hbm.xml</literal> no
classpath.
+ Esta abordagem elimina qualquer nome de arquivo de difícil compreensão.
+ </para>
+
+ <para>
+ Uma <literal>Configuration</literal> também permite você
especificar
+ propriedades de configuração:
+ </para>
+
+ <programlisting><![CDATA[Configuration cfg = new Configuration()
+ .addClass(org.hibernate.auction.Item.class)
+ .addClass(org.hibernate.auction.Bid.class)
+ .setProperty("hibernate.dialect",
"org.hibernate.dialect.MySQLInnoDBDialect")
+ .setProperty("hibernate.connection.datasource",
"java:comp/env/jdbc/test")
+ .setProperty("hibernate.order_updates",
"true");]]></programlisting>
+
+ <para>
+ Este não é o único caminho para passar as propriedades de configuração
+ para o Hibernate. As várias opções incluem:
+ </para>
+
+ <orderedlist spacing="compact">
+ <listitem>
+ <para>
+ Passar uma instância de
<literal>java.util.Properties</literal>
+ para <literal>Configuration.setProperties()</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Colocar <literal>hibernate.properties</literal> no
diretório
+ raiz do classpath.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Determinar as propriedades do <literal>System</literal>
+ usando <literal>java -Dproperty=value</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Include <literal><property></literal>
elements in
+ <literal>hibernate.cfg.xml</literal> (discussed later).
+ Incluir elementos
<literal><property></literal> no
+ <literal>hibernate.cfg.xml</literal> (discutido mais
tarde).
+ </para>
+ </listitem>
+ </orderedlist>
+
+ <para>
+ <literal>hibernate.properties</literal> é o caminho mais facil
+ se você quer começar mais rápido.
+ </para>
+
+ <para>
+ O <literal>Configuration</literal> é entendido como um objeto
startup-time,
+ é descartado uma vez que a <literal>SessionFactory</literal> é
criada.
+ </para>
+
+ </sect1>
+
+ <sect1 id="configuration-sessionfactory">
+ <title>Obtendo uma SessionFactory</title>
+
+ <para>
+ Quando todos os mapeamentos têm sido analisados pelo
<literal>Configuration</literal>,
+ a aplicação deve obter uma factory para as instâncias da
<literal>Session</literal>.
+ O objetivo desta factory é ser compartilhado por todas as threads da
aplicação:
+ </para>
+
+ <programlisting><![CDATA[SessionFactory sessions =
cfg.buildSessionFactory();]]></programlisting>
+
+ <para>
+ Hibernate permite sua aplicação instanciar mais do que uma
+ <literal>SessionFactory</literal>. Isto é útil se você está
usando mais
+ do que um banco de dados.
+ </para>
+
+ </sect1>
+
+ <sect1 id="configuration-hibernatejdbc" revision="1">
+ <title>Conexões JDBC</title>
+
+ <para>
+ Normalmente, você quer mandar criar a
<literal>SessionFactory</literal> criar um
+ pool de conexões JDBC para você. Se você seguir essa abordagem, a abertura de
uma
+ <literal>Session</literal> é tão simples quanto:
+
+ </para>
+
+ <programlisting><![CDATA[Session session = sessions.openSession(); //
open a new Session]]></programlisting>
+
+ <para>
+ Assim que você fizer algo que requer o acesso ao banco de dados, uma
+ conexão JDBC será obtida do pool.
+ </para>
+
+ <para>
+ Para esse trabalho, nós necessitamos passar algumas propriedades da conexão
JDBC
+ para o Hibernate. Todos os nomes de propriedades Hibernate e semânticas são
definidas
+ <literal>org.hibernate.cfg.Environment</literal>. Nós iremos
descrever agora
+ o mais importantes configurações de conexão JDBC.
+ </para>
+
+ <para>
+ O Hibernate obterá conexões( e pool) usando
<literal>java.sql.DriverManager</literal>
+ se você determinar as seguintes propriedades:
+ </para>
+
+ <table frame="topbot">
+ <title>Propriedades JDBC Hibernate</title>
+ <tgroup cols="2">
+ <colspec colname="c1" colwidth="1*"/>
+ <colspec colname="c2" colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>Nome da Propriedade</entry>
+ <entry>Propósito</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <literal>hibernate.connection.driver_class</literal>
+ </entry>
+ <entry>
+ <emphasis>Classe driver jdbc</emphasis>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.connection.url</literal>
+ </entry>
+ <entry>
+ <emphasis>URL jdbc</emphasis>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.connection.username</literal>
+ </entry>
+ <entry>
+ <emphasis>Usuário do banco de dados</emphasis>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.connection.password</literal>
+ </entry>
+ <entry>
+ <emphasis>Senha do usuário do banco de dados</emphasis>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.connection.pool_size</literal>
+ </entry>
+ <entry>
+ <emphasis>Número máximo de connecxões no pool</emphasis>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>
+ O algoritmo de pool de conexões do próprio Hibernate entretanto é
completamente
+ rudimentar. A intenção dele e ajudar a iniciar e <emphasis>não para
usar em um
+ sistema de produção</emphasis> ou até para testar desempenho. Você
deveria usar
+ uma ferramente de pool de terceiros para conseguir melhor desempenho e
estabilidade.
+ Apenas especifique a propriedade
<literal>hibernate.connection.pool_size</literal>
+ com a definição do pool de conexões. Isto irá desligar o pool interno do
Hibernate.
+ Por exemplo, você pode gostar de usar C3P0.
+ </para>
+
+ <para>
+ O C3P0 é um pool conexão JDBC de código aberto distribuído junto com
+ Hibernate no diretório <literal>lib</literal>. O Hibernate
usará o
+ <literal>C3P0ConnectionProvider</literal> para o pool de conexão
se
+ você configurar a propriedade
<literal>hibernate.c3p0.*</literal>. Se você
+ gostar de usar Proxool consulte ao pacote
<literal>hibernate.properties</literal>
+ e o web site do Hibernate para mais informações.
+ </para>
+
+ <para>
+ Aqui é um exemplo de arquivo
<literal>hibernate.properties</literal> para C3P0:
+ </para>
+
+ <programlisting id="c3p0-configuration"
revision="1"><![CDATA[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]]></programlisting>
+
+ <para>
+ Para usar dentro de um servidor de aplicação, você deve configurar
+ o Hibernate para obter conexões de um application server
+ <literal>Datasource</literal> registrado no JNDI. Você
necessitará
+ determinar pelo menos uma das seguintes propriedades:
+ </para>
+
+ <table frame="topbot">
+ <title>Propriedades do Datasource do Hibernate</title>
+ <tgroup cols="2">
+ <colspec colname="c1" colwidth="1*"/>
+ <colspec colname="c2" colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>Nome da Propriedade</entry>
+ <entry>Propósito</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <literal>hibernate.connection.datasource</literal>
+ </entry>
+ <entry>
+ <emphasis>Nome datasource JNDI</emphasis>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.jndi.url</literal>
+ </entry>
+ <entry>
+ <emphasis>URL do fornecedor JNDI</emphasis> (opcional)
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.jndi.class</literal>
+ </entry>
+ <entry>
+ <emphasis>Classe do JNDI
<literal>InitialContextFactory</literal></emphasis> (opcional)
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.connection.username</literal>
+ </entry>
+ <entry>
+ <emphasis>Usuário do banco de dados</emphasis>
(opcional)
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.connection.password</literal>
+ </entry>
+ <entry>
+ <emphasis>Senha do usuário do banco de dados</emphasis>
(opcional)
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>
+ Eis um exemplo de arquivo <literal>hibernate.properties</literal>
para
+ um servidor de aplicação fornecedor de datasources JNDI:
+ </para>
+
+ <programlisting><![CDATA[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]]></programlisting>
+
+ <para>
+ Conexões JDBC obtidas de um datasource JNDI irão automaticamente irão
participar
+ das transações gerenciadas pelo container no servidor de aplicação.
+ </para>
+
+ <para>
+ Arbitrariamente as propriedades de conexão podem ser acrescentandas ao
+ "<literal>hibernate.connnection</literal>" ao nome da
propriedade. Por exemplo,
+ você deve especificar o <literal>charSet</literal> usando
<literal>hibernate.connection.charSet</literal>.t.
+ </para>
+
+ <para>
+ Você pode definir sua própria estratégia de plugin para obter conexões JDBC
implementando
+ a interface
<literal>org.hibernate.connection.ConnectionProvider</literal>. Você pode
+ escolher uma implementação customizada setando
<literal>hibernate.connection.provider_class</literal>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="configuration-optional" revision="1">
+ <title>Propriedades opcionais de configuração</title>
+
+ <para>
+ Há um grande número de outras propriedades que controlam o comportamento do
Hibernate
+ em tempo de execução. Todos são opcionais e tem valores default lógicos.
+ </para>
+
+ <para>
+ <emphasis>Aviso: algumas destas propriedades são somente a "nível
de sistema".</emphasis>
+ Propriedades nível de sistema podem ser determinados somente via
<literal>java -Dproperty=value</literal>
+ ou <literal>hibernate.properties</literal>. Elas
<emphasis>não</emphasis>podem ser
+ configuradas por outras técnicas descritas abaixo.
+ </para>
+
+ <table frame="topbot"
id="configuration-optional-properties" revision="8">
+ <title>Hibernate Configuration Properties</title>
+ <tgroup cols="2">
+ <colspec colname="c1" colwidth="1*"/>
+ <colspec colname="c2" colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>Nome da Propriedade</entry>
+ <entry>Propósito</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <literal>hibernate.dialect</literal>
+ </entry>
+ <entry>
+ O nome da classe de um <literal>Dialeto</literal>
+ que permite o Hibernate gerar SQL otimizado para um banco de
+ dados relacional em particular.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>full.classname.of.Dialect</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.show_sql</literal>
+ </entry>
+ <entry>
+ Escreve todas as instruções SQL no console. Esta é uma
alternativa
+ a configurar a categoria de log
<literal>org.hibernate.SQL</literal>
+ para <literal>debug</literal>.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true</literal> |
<literal>false</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.format_sql</literal>
+ </entry>
+ <entry>
+ Imprime o SQL formatado no log e console.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true</literal> |
<literal>false</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.default_schema</literal>
+ </entry>
+ <entry>
+ Qualifica no sql gerado, os nome das tabelas sem qualificar
+ com schena/tablespace dado
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>SCHEMA_NAME</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.default_catalog</literal>
+ </entry>
+ <entry>
+ Qualifica no sql gerado, os nome das tabelas sem qualificar
+ com catálogo dado
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>CATALOG_NAME</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.session_factory_name</literal>
+ </entry>
+ <entry>
+ O <literal>SessionFactory</literal> irá
automaticamente
+ se ligar a este nome no JNDI depois de ter sido criado.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>jndi/composite/name</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.max_fetch_depth</literal>
+ </entry>
+ <entry>
+ Estabelece a "profundidade" máxima para árvore
outer join fetch
+ para associações finais únicas(one-to-one,many-to-one).
+ Um <literal>0</literal> desativa por default a
busca outer join.
+ <para>
+ <emphasis
role="strong">eg.</emphasis>
+ Valores recomendados
entre<literal>0</literal> e <literal>3</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.default_batch_fetch_size</literal>
+ </entry>
+ <entry>
+ Determina um tamanho default para busca de associações em
lotes do Hibernate
+ <para>
+ <emphasis
role="strong">eg.</emphasis>
+ Valores recomendados <literal>4</literal>,
<literal>8</literal>,
+ <literal>16</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.default_entity_mode</literal>
+ </entry>
+ <entry>
+ Determina um modo default para representação de entidades
+ para todas as sessões abertas desta
<literal>SessionFactory</literal>
+ <para>
+ <literal>dynamic-map</literal>,
<literal>dom4j</literal>,
+ <literal>pojo</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.order_updates</literal>
+ </entry>
+ <entry>
+ Força o Hibernate a ordenar os updates SQL pelo valor da
chave
+ primária dos itens a serem atualizados. Isto resultará em
menos
+ deadlocks nas transações em sistemas altamente concorrente.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true</literal> |
<literal>false</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.generate_statistics</literal>
+ </entry>
+ <entry>
+ If enabled, Hibernate will collect statistics useful for
+ performance tuning.
+ Se habilitado, o Hibernate coletará estatísticas úties
+ para performance tuning dos bancos.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true</literal> |
<literal>false</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.use_identifer_rollback</literal>
+ </entry>
+ <entry>
+ Se habilitado, propriedades identificadoras geradas
+ serão zeradas para os valores default quando os
+ objetos forem apagados.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true</literal> |
<literal>false</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.use_sql_comments</literal>
+ </entry>
+ <entry>
+ Se ligado, o Hibernate irá gerar comentários dentro do SQL,
+ para facilitar o debugging, o valor default é
<literal>false</literal>.
+ <para>
+ <emphasis
role="strong">eg.</emphasis>
+ <literal>true</literal> |
<literal>false</literal>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <table frame="topbot" id="configuration-jdbc-properties"
revision="8">
+ <title>JDBC Hibernate e Propriedades de Conexão</title>
+ <tgroup cols="2">
+ <colspec colname="c1" colwidth="1*"/>
+ <colspec colname="c2" colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>Nome da Propriedade</entry>
+ <entry>Propósito</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <literal>hibernate.jdbc.fetch_size</literal>
+ </entry>
+ <entry>
+ Um valor maior que zero determina o tamanho do fetch
+ do JDBC( chamadas
<literal>Statement.setFetchSize()</literal>).
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.jdbc.batch_size</literal>
+ </entry>
+ <entry>
+ Um valor maior que zero habilita uso de batch updates JDBC2
pelo Hibernate.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ valores recomentados entre
<literal>5</literal> e <literal>30</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.jdbc.batch_versioned_data</literal>
+ </entry>
+ <entry>
+ Sete esta propriedade como
<literal>true</literal> se seu driver JDBC retorna
+ o número correto de linhas no
<literal>executeBatch()</literal> ( É usualmente
+ seguro tornar esta opção ligada). O Hibernate então irá usar
betched DML
+ para automaticamente versionar dados.
<literal>false</literal> por default.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true</literal> |
<literal>false</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.jdbc.factory_class</literal>
+ </entry>
+ <entry>
+ Escolher um <literal>Batcher</literal>
customizado. Muitas
+ aplicações não irão necessitar desta propriedade de
configuração
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+
<literal>classname.of.BatcherFactory</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.jdbc.use_scrollable_resultset</literal>
+ </entry>
+ <entry>
+ Habilita o uso de JDBC2 scrollable resultsets pelo
Hibernate.
+ Essa propriedade somente é necessaria quando se usa
Conexeções
+ JDBC providas pelo usuário, caso contrário o Hibernate os os
+ metadados da conexão.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true</literal> |
<literal>false</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.jdbc.use_streams_for_binary</literal>
+ </entry>
+ <entry>
+ Use streams para escrever/ler tipos
<literal>binary</literal>
+ ou <literal>serializable</literal> para/a o JDBC(
propriedade a nível de sistema).
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true</literal> |
<literal>false</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.jdbc.use_get_generated_keys</literal>
+ </entry>
+ <entry>
+ Possibilita o uso
<literal>PreparedStatement.getGeneratedKeys()</literal>
+ do JDBC3 para recuperar chaves geradas nativamente depois da
inserçãp.
+ Requer driver JDBC3+ e JRE1.4+, determine para false se seu
driver tem
+ problemas com gerador de indentificadores Hibernate. Por
default, tente
+ determinar o driver capaz de usar metadados da conexão.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true|false</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.connection.provider_class</literal>
+ </entry>
+ <entry>
+ O nome da classe de um
<literal>ConnectionProvider</literal> personalizado
+ o qual proverá conexões JDBC para o Hibernate.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+
<literal>classname.of.ConnectionProvider</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.connection.isolation</literal>
+ </entry>
+ <entry>
+ Determina o nível de isolamento de uma transação JDBC.
+ Verifique <literal>java.sql.Connection</literal> para
valores
+ siginificativos mas note que a maior parte dos bancos de dados
+ não suportam todos os níveis de isolamento.
+ <para>
+ <emphasis role="strong">Ex.</emphasis>
+ <literal>1, 2, 4, 8</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.connection.autocommit</literal>
+ </entry>
+ <entry>
+ Habilita autocommit para conexões no pool JDBC( não
recomendado).
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true</literal> |
<literal>false</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.connection.release_mode</literal>
+ </entry>
+ <entry>
+ Especifica quando o Hibernate deve liberar conexões JDBC. Por
default,
+ uma conexão JDBC é retida até a sessão está explicitamente
fechada
+ ou desconectada. Para um datasource JTA do servidor de
aplicação, você deve
+ usar <literal>after_statement</literal> para
forçar s liberação da conexões
+ depois de todas as chamadas JDBC. Para uma conexão não-JTA,
freqüentemente
+ faz sentido liberar a conexão ao fim de cada transação,
usando
+ <literal>after_transaction</literal>.
<literal>auto</literal> escolheremos
+ <literal>after_statement</literal> para as
estratégias de transaçãoes JTA e CMT
+ e <literal>after_transaction</literal> para as
estratégias de transação JDBC
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>auto</literal> (default) |
<literal>on_close</literal> |
+ <literal>after_transaction</literal> |
<literal>after_statement</literal>
+ </para>
+ <para>
+ Note that this setting only affects
<literal>Session</literal>s returned from
+
<literal>SessionFactory.openSession</literal>. For
<literal>Session</literal>s
+ obtained through
<literal>SessionFactory.getCurrentSession</literal>, the
+ <literal>CurrentSessionContext</literal>
implementation configured for use
+ controls the connection release mode for those
<literal>Session</literal>s.
+ See <xref
linkend="architecture-current-session"/>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.connection.<emphasis><propertyName></emphasis></literal>
+ </entry>
+ <entry>
+ Passa a propriedade JDBC
<literal>propertyName</literal>
+ para
<literal>DriverManager.getConnection()</literal>.
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.jndi.<emphasis><propertyName></emphasis></literal>
+ </entry>
+ <entry>
+ Passar a propriedade
<literal>propertyName</literal> para
+ o <literal>InitialContextFactory</literal> JNDI.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <table frame="topbot" id="configuration-cache-properties"
revision="7">
+ <title>Propriedades de Cachê do Hibernate</title>
+ <tgroup cols="2">
+ <colspec colname="c1" colwidth="1*"/>
+ <colspec colname="c2" colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>Nome da Propriedade</entry>
+ <entry>Propósito</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+
<literal>hibernate.cache.provider_class</literal>
+ </entry>
+ <entry>
+ O nome da classe de um
<literal>CacheProvider</literal> customizado.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+
<literal>classname.of.CacheProvider</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.cache.use_minimal_puts</literal>
+ </entry>
+ <entry>
+ Otimizar operação de cachê de segundo nível para minimizar
escritas,
+ ao custo de leituras mais frequantes. Esta configuração é
mais útil
+ para cachês clusterizados e, no Hibernate3, é habilitado por
default
+ para implementações de cachê clusterizar.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true|false</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.cache.use_query_cache</literal>
+ </entry>
+ <entry>
+ Habilita a cache de consultas, Mesmo assim, consultas
individuais ainda tem que ser
+ habilitadas para o cache.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true|false</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.cache.use_second_level_cache</literal>
+ </entry>
+ <entry>
+ Pode ser usada para desabilitar completamente ocache de
segundo nível,
+ o qual está habilitado por default para classes que
especificam
+ um mapeamento
<literal><cache></literal>.
+
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true|false</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.cache.query_cache_factory</literal>
+ </entry>
+ <entry>
+ O nome de uma classe que implementa a interface
+ <literal>QueryCache</literal> personalizada, por
+ default, um
<literal>StandardQueryCache</literal>
+ criado automaticamente.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>classname.of.QueryCache</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.cache.region_prefix</literal>
+ </entry>
+ <entry>
+ Um prefixo para usar nos nomes da área especial
+ do cachê de segundo nível.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>prefix</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.cache.use_structured_entries</literal>
+ </entry>
+ <entry>
+ Forces Hibernate to store data in the second-level cache
+ in a more human-friendly format.
+ Força o Hibernate armazenar dados no cachê se segundo
+ nível em um formato mais legivel.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true|false</literal>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <table frame="topbot"
id="configuration-transaction-properties" revision="9">
+ <title>Propriedades de Transação do Hibernate</title>
+ <tgroup cols="2">
+ <colspec colname="c1" colwidth="1*"/>
+ <colspec colname="c2" colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>Nome da Propriedade</entry>
+ <entry>Propósito</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+
<literal>hibernate.transaction.factory_class</literal>
+ </entry>
+ <entry>
+ O nome da clase de um a
<literal>TransactionFactory</literal>
+ para usar com API <literal>Transaction</literal>
+ ( por default <literal>JDBCTransactionFactory</literal>).
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+
<literal>classname.of.TransactionFactory</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>jta.UserTransaction</literal>
+ </entry>
+ <entry>
+ Um nome JNDI usado pelo
<literal>JTATransactionFactory</literal>
+ para obter uma <literal>UserTransaction</literal>
JTA a partir
+ do servidor de aplicação.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>jndi/composite/name</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.transaction.manager_lookup_class</literal>
+ </entry>
+ <entry>
+ O nome da classe de um
<literal>TransactionManagerLookup</literal>
+ – requerido quando caching a nível JVM esta habilitado ou
quando
+ estivermos usando um generator hilo em um ambiente JTA.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+
<literal>classname.of.TransactionManagerLookup</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.transaction.flush_before_completion</literal>
+ </entry>
+ <entry>
+ Se habilitado, a sessão será automaticamente limpa antes da
fase de
+ conclusão da transação. É preferivel a gerência interna e
+ automática do contexto da sessão, veja
+ <xref
linkend="architecture-current-session"/>
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true</literal> |
<literal>false</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.transaction.auto_close_session</literal>
+ </entry>
+ <entry>
+ Se habilitado, a sessão será automaticamente fechada após a
fase de
+ conclusão da transação. É preferivel a gerência interna e
+ automática do contexto da sessão, veja
+ <xref
linkend="architecture-current-session"/>
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true</literal> |
<literal>false</literal>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <table frame="topbot" id="configuration-misc-properties"
revision="10">
+ <title>Propriedades Variadas</title>
+ <tgroup cols="2">
+ <colspec colname="c1" colwidth="1*"/>
+ <colspec colname="c2" colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>Nome da Propriedade</entry>
+ <entry>Propósito</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+
<literal>hibernate.current_session_context_class</literal>
+ </entry>
+ <entry>
+ Forneçe uma estratégia (personalizada) para extensão
+ da <literal>Session</literal>
"corrente". Veja
+ <xref
linkend="architecture-current-session"/> para
+ mais informação sobre estratégias internas.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>jta</literal> |
<literal>thread</literal> |
+ <literal>managed</literal> |
<literal>custom.Class</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.query.factory_class</literal>
+ </entry>
+ <entry>
+ Escolha a implementação de análise HQL.
+ <para>
+ <emphasis
role="strong">eg.</emphasis>
+
<literal>org.hibernate.hql.ast.ASTQueryTranslatorFactory</literal> or
+
<literal>org.hibernate.hql.classic.ClassicQueryTranslatorFactory</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.query.substitutions</literal>
+ </entry>
+ <entry>
+ Mapeamento a partir de símbolos em consultas HQL para
+ símbolos SQL( símbolos devem ser funções ou nome literais
+ , por exemplo).
+ <para>
+ <emphasis
role="strong">eg.</emphasis>
+ <literal>hqlLiteral=SQL_LITERAL,
hqlFunction=SQLFUNC</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.hbm2ddl.auto</literal>
+ </entry>
+ <entry>
+ Automaticamente valida ou exporta schema DDL para o banco de
+ dados quando o <literal>SessionFactory</literal>
é criads.
+ Com <literal>create-drop</literal>, o schema do
banco de dados
+ será excluido quando a
<literal>create-drop</literal> for
+ fechada esplicitamente.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>validate</literal> |
<literal>update</literal> |
+ <literal>create</literal> |
<literal>create-drop</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.cglib.use_reflection_optimizer</literal>
+ </entry>
+ <entry>
+ Habilita o uso de CGLIB em vez de reflexão em tempo de
execução
+ ( propriedade a nível de sistema). Reflexão pode algumas
vezes ser ú
+ til quando controlar erros, note que o Hibernate sempre irá
requerer a CGLIB
+ mesmo se você desligar o otimizador. Você não pode determinar
esta
+ propriedade no <literal>hibernate.cfg.xml</literal>.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true</literal> |
<literal>false</literal>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <sect2 id="configuration-optional-dialects"
revision="1">
+ <title>Dialetos SQL</title>
+
+ <para>
+ Você deve sempre determinar a propriedade
<literal>hibernate.dialect</literal>
+ para a subclasse de
<literal>org.hibernate.dialect.Dialect</literal> correta de seu
+ banco de dados. Se você especificar um dialeto, Hibernate usará defaults
lógicos
+ para qualquer um das outras propriedades listadas abaixo, reduzindo o
esforço de
+ especificá-los manualmente.
+ </para>
+
+ <table frame="topbot" id="sql-dialects"
revision="2">
+ <title>Hibernate SQL Dialects
(<literal>hibernate.dialect</literal>)</title>
+ <tgroup cols="2">
+ <colspec colwidth="1*"/>
+ <colspec colwidth="2.5*"/>
+ <thead>
+ <row>
+ <entry>RDBMS</entry>
+ <entry>Dialect</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>DB2</entry>
<entry><literal>org.hibernate.dialect.DB2Dialect</literal></entry>
+ </row>
+ <row>
+ <entry>DB2 AS/400</entry>
<entry><literal>org.hibernate.dialect.DB2400Dialect</literal></entry>
+ </row>
+ <row>
+ <entry>DB2 OS390</entry>
<entry><literal>org.hibernate.dialect.DB2390Dialect</literal></entry>
+ </row>
+ <row>
+ <entry>PostgreSQL</entry>
<entry><literal>org.hibernate.dialect.PostgreSQLDialect</literal></entry>
+ </row>
+ <row>
+ <entry>MySQL</entry>
<entry><literal>org.hibernate.dialect.MySQLDialect</literal></entry>
+ </row>
+ <row>
+ <entry>MySQL with InnoDB</entry>
<entry><literal>org.hibernate.dialect.MySQLInnoDBDialect</literal></entry>
+ </row>
+ <row>
+ <entry>MySQL with MyISAM</entry>
<entry><literal>org.hibernate.dialect.MySQLMyISAMDialect</literal></entry>
+ </row>
+ <row>
+ <entry>Oracle (any version)</entry>
<entry><literal>org.hibernate.dialect.OracleDialect</literal></entry>
+ </row>
+ <row>
+ <entry>Oracle 9i/10g</entry>
<entry><literal>org.hibernate.dialect.Oracle9Dialect</literal></entry>
+ </row>
+ <row>
+ <entry>Sybase</entry>
<entry><literal>org.hibernate.dialect.SybaseDialect</literal></entry>
+ </row>
+ <row>
+ <entry>Sybase Anywhere</entry>
<entry><literal>org.hibernate.dialect.SybaseAnywhereDialect</literal></entry>
+ </row>
+ <row>
+ <entry>Microsoft SQL Server</entry>
<entry><literal>org.hibernate.dialect.SQLServerDialect</literal></entry>
+ </row>
+ <row>
+ <entry>SAP DB</entry>
<entry><literal>org.hibernate.dialect.SAPDBDialect</literal></entry>
+ </row>
+ <row>
+ <entry>Informix</entry>
<entry><literal>org.hibernate.dialect.InformixDialect</literal></entry>
+ </row>
+ <row>
+ <entry>HypersonicSQL</entry>
<entry><literal>org.hibernate.dialect.HSQLDialect</literal></entry>
+ </row>
+ <row>
+ <entry>Ingres</entry>
<entry><literal>org.hibernate.dialect.IngresDialect</literal></entry>
+ </row>
+ <row>
+ <entry>Progress</entry>
<entry><literal>org.hibernate.dialect.ProgressDialect</literal></entry>
+ </row>
+ <row>
+ <entry>Mckoi SQL</entry>
<entry><literal>org.hibernate.dialect.MckoiDialect</literal></entry>
+ </row>
+ <row>
+ <entry>Interbase</entry>
<entry><literal>org.hibernate.dialect.InterbaseDialect</literal></entry>
+ </row>
+ <row>
+ <entry>Pointbase</entry>
<entry><literal>org.hibernate.dialect.PointbaseDialect</literal></entry>
+ </row>
+ <row>
+ <entry>FrontBase</entry>
<entry><literal>org.hibernate.dialect.FrontbaseDialect</literal></entry>
+ </row>
+ <row>
+ <entry>Firebird</entry>
<entry><literal>org.hibernate.dialect.FirebirdDialect</literal></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ </sect2>
+
+ <sect2 id="configuration-optional-outerjoin"
revision="4">
+ <title>Recuperação por união externa (Outer Join
Fetching)</title>
+
+ <para>
+ Se seu banco de dados suporta Recuperação por união externa (Outer Join
Fetching) no estilo ANSI,
+ Oracle ou Sybase, A recuperação por união externa (Outer Join Fetching)
frequentemente aumentará
+ o desempenho limitando o número de chamadas (round trips) ao banco de
dados( ao custo de
+ possivelmente mais trabalho desempenhado pelo próprio banco de dados). A
recuperação por
+ união externa (Outer Join Fetching)permite um gráfico completo de objetos
conectados
+ por muitos-para-um, um-para-muitos, muitos-para-muitos e associações
um-para-um para ser
+ recuperadas em um simples instrução SQL SELECT .
+
+ </para>
+
+ <para>
+ A recuperação por união externa (Outer Join Fetching) pode ser
desabilitado
+ <emphasis>globalmente</emphasis> setando a propriedade
+ <literal>hibernate.max_fetch_depth</literal> para
<literal>0</literal>.
+ Uma valor 1 ou maior habilita o outer join fetching para associações
um-para-um
+ e muitos-para-umos cujos quais tem sido mapeado com
<literal>fetch="join"</literal>.
+ </para>
+
+ <para>
+ Veja <xref linkend="performance-fetching"/> para mais
informações.
+ </para>
+
+ </sect2>
+
+ <sect2 id="configuration-optional-binarystreams"
revision="1">
+ <title>Fluxos Binários (Binary Streams)</title>
+
+ <para>
+ O Oracle limita o tamanho de arrays de
<literal>byte</literal> que pode ser
+ passado para/de o driver JDBC. Se você desejar usar grandes instâncias de
+ tipos <literal>binary</literal> ou
<literal>serializable</literal>, você
+ deve habilitar
<literal>hibernate.jdbc.use_streams_for_binary</literal>.
+ <emphasis>Essa é uma configuração que só pode ser feita a nível de
sistema.</emphasis>
+ </para>
+
+ </sect2>
+
+ <sect2 id="configuration-optional-cacheprovider"
revision="2">
+ <title>Cachê de segundo nível e query</title>
+
+ <para>
+ As propriedades prefixadas pelo
<literal>hibernate.cache</literal>
+ permite você usar um sistema de cachê de segundo nível
+ em um processo executado em clustercom Hibernate.
+ Veja <xref linkend="performance-cache"/> para mais
detalhes.
+ </para>
+
+ </sect2>
+
+ <sect2 id="configuration-optional-querysubstitution">
+ <title>Substituições na Linguagem de Consulta</title>
+
+ <para>
+ Você pode definir novos símbolos de consulta Hibernate usando
+ <literal>hibernate.query.substitutions</literal>.
+ Por exemplo:
+ </para>
+
+ <programlisting>hibernate.query.substitutions true=1,
false=0</programlisting>
+
+ <para>
+ Faria com que os símbolos <literal>true</literal> e
<literal>false</literal>
+ passasem a ser traduzidos para literais inteiro no SQL gerado.
+ </para>
+
+ <programlisting>hibernate.query.substitutions
toLowercase=LOWER</programlisting>
+
+ <para>
+ permitirá você renomear a função <literal>LOWER</literal> no
SQL.
+ </para>
+
+ </sect2>
+
+ <sect2 id="configuration-optional-statistics"
revision="2">
+ <title>Estatísticas do Hibernate</title>
+
+ <para>
+ If you enable
<literal>hibernate.generate_statistics</literal>, Hibernate will
+ expose a number of metrics that are useful when tuning a running system
via
+ <literal>SessionFactory.getStatistics()</literal>. Hibernate
can even be configured
+ to expose these statistics via JMX. Read the Javadoc of the interfaces
in
+ <literal>org.hibernate.stats</literal> for more information.
+
+ Se você habilitar
<literal>hibernate.generate_statistics</literal>, o Hibernate
+ exibirá um número de métricas bastante útil ao ajustar um sistema via
+ <literal>SessionFactory.getStatistics()</literal>. O
Hibernate pode até ser
+ configurado para exibir essas estatísticas via JMX. Leia o Javadoc da
interface
+ <literal>org.hibernate.stats</literal> para mais
informações.
+ </para>
+
+ </sect2>
+ </sect1>
+
+ <sect1 id="configuration-logging">
+ <title>Logging</title>
+
+ <para>
+ Hibernate registra vários eventos usando Apache commons-logging.
+ </para>
+
+ <para>
+ O serviço commons-logging direcionará a saída para o Apache Log4j
+ ( se você incluir <literal>log4j.jar</literal>r no seu classpath)
ou
+ JDK1.4 logging( se estiver em uso JDK1.4 ou maior). Você pode fazer o
+ download do Log4j a partir de
<literal>http://jakarta.apache.org</literal>.
+ Para usar Log4j você necessitará colocar um arquivo
+ <literal>log4j.properties</literal> no seu classpath, um exemplo
de arquivo
+ de propriedades é distribuído com o Hibernate no diretório
+ <literal>src/</literal>.
+
+ </para>
+
+ <para>
+ We strongly recommend that you familiarize yourself with Hibernate's log
+ messages. A lot of work has been put into making the Hibernate log as
+ detailed as possible, without making it unreadable. It is an essential
+ troubleshooting device. The most interesting log categories are the
+ following:
+
+ Nós recomendamos enfaticamente que você se familiarize-se com mensagens de
+ log do Hibernate. Uma parte do trabalho tem sido posto em fazer o log
+ Hibernate tão detalhado quanto possível, sem fazê-lo ilegível.
+ É um essencial dispositivos de controle de erros. As categorias de log
+ mais interessantes são as seguintes:
+ </para>
+
+ <table frame="topbot" id="log-categories"
revision="2">
+ <title>Categorias de Log do Hibernate</title>
+ <tgroup cols="2">
+ <colspec colwidth="1*"/>
+ <colspec colwidth="2.5*"/>
+ <thead>
+ <row>
+ <entry>Categoria</entry>
+ <entry>Função</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+
<entry><literal>org.hibernate.SQL</literal></entry>
+ <entry>Registra todas as instruções SQL DML a medida
que elas são executadas</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.type</literal></entry>
+ <entry>Registra todos os parâmetros JDBC</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.tool.hbm2ddl</literal></entry>
+ <entry>Registra todas as instruções SQL DDL a medida
que elas são executadas</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.pretty</literal></entry>
+ <entry>
+ Log the state of all entities (max 20 entities)
associated
+ with the session at flush time
+ Registra o estado de todas as entidades (máximo 20
entidades)
+ associadas a session no momento da limpeza (flush).
+ </entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.cache</literal></entry>
+ <entry>Registra todas as atividades de cachê de segundo
nível</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.transaction</literal></entry>
+ <entry>Registra atividades relacionada a
transação</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.jdbc</literal></entry>
+ <entry>Registra todas as requisições de recursos
JDBC</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.hql.ast.AST</literal></entry>
+ <entry>
+ Registra instruções SQL e HQL durante a análise da
consultas
+ </entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.secure</literal></entry>
+ <entry>Registra todas as requisições de autorização
JAAS</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate</literal></entry>
+ <entry>
+ Registra tudo ( uma parte das informações, mas muito
+ útil para controle de erros )
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>
+ Quando desenvolver aplicações com Hibernate, você deve quase sempre trabalhar
com
+ debug <literal>debug</literal> para a categoria
<literal>org.hibernate.SQL</literal>,
+ ou, alternativamente, a com a propriedade
<literal>hibernate.show_sql</literal> habilitada.
+ </para>
+
+
+ </sect1>
+
+ <sect1 id="configuration-namingstrategy">
+ <title>Implementado uma
<literal>NamingStrategy</literal></title>
+
+ <para>
+ A interface <literal>org.hibernate.cfg.NamingStrategy</literal>
permite você
+ especificar um "padrão de nomeação" para objetos do banco de dados
e elementos schema.
+ </para>
+
+ <para>
+ Você deve criar regras para a geração automaticamente de identificadores
+ do banco de dados a partir de identificadores Java ou para processar
+ colunas "computadas" e nomes de tabelas dado o arquivo de
mapeamento
+ para nomes "físicos" de tabelas e colunas. Esta característica
ajuda a
+ reduzir a verbosidade do documento de mapeamento, eliminando interferências
+ repetitivas( <literal>TBL_</literal>prefixos, por exemplo). A
estratégia
+ default usada pelo Hibernate é completamente mínima.
+ </para>
+
+ <para>
+ Você pode especificar uma estratégia diferente ao chamar
+ <literal>Configuration.setNamingStrategy()</literal> antes de
adicionar
+ os mapeamentos:
+ </para>
+
+ <programlisting><![CDATA[SessionFactory sf = new Configuration()
+ .setNamingStrategy(ImprovedNamingStrategy.INSTANCE)
+ .addFile("Item.hbm.xml")
+ .addFile("Bid.hbm.xml")
+ .buildSessionFactory();]]></programlisting>
+
+ <para>
+ <literal>org.hibernate.cfg.ImprovedNamingStrategy</literal> é uma
estratégia
+ interna que pode ser um ponto de começo útil para algumas aplicações.
+ </para>
+
+ </sect1>
+
+ <sect1 id="configuration-xmlconfig" revision="2">
+ <title>Arquivo de configuração XML</title>
+
+ <para>
+ Uma maneira alternativa de configuração é especificar uma configuração
completa
+ em um arquivo chamado <literal>hibernate.cfg.xml</literal>. Este
arquivo pode
+ ser usado como um substituto para o arquivo
<literal>hibernate.properties</literal>
+ ou, se ambos estão presentes, sobrescrever propriedades.
+ </para>
+
+ <para>
+ The XML configuration file is by default expected to be in the root o
+ your <literal>CLASSPATH</literal>. Here is an example:
+ O arquivo XML de configuração é por default esperado para estar na
+ raiz do seu <literal>CLASSPATH</literal>. Veja um exemplo:
+ </para>
+
+ <programlisting><![CDATA[<?xml version='1.0'
encoding='utf-8'?>
+<!DOCTYPE hibernate-configuration PUBLIC
+ "-//Hibernate/Hibernate Configuration DTD//EN"
+ "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
+
+<hibernate-configuration>
+
+ <!-- a SessionFactory instance listed as /jndi/name -->
+ <session-factory
+ name="java:hibernate/SessionFactory">
+
+ <!-- properties -->
+ <property
name="connection.datasource">java:/comp/env/jdbc/MyDB</property>
+ <property
name="dialect">org.hibernate.dialect.MySQLDialect</property>
+ <property name="show_sql">false</property>
+ <property name="transaction.factory_class">
+ org.hibernate.transaction.JTATransactionFactory
+ </property>
+ <property
name="jta.UserTransaction">java:comp/UserTransaction</property>
+
+ <!-- mapping files -->
+ <mapping resource="org/hibernate/auction/Item.hbm.xml"/>
+ <mapping resource="org/hibernate/auction/Bid.hbm.xml"/>
+
+ <!-- cache settings -->
+ <class-cache class="org.hibernate.auction.Item"
usage="read-write"/>
+ <class-cache class="org.hibernate.auction.Bid"
usage="read-only"/>
+ <collection-cache collection="org.hibernate.auction.Item.bids"
usage="read-write"/>
+
+ </session-factory>
+
+</hibernate-configuration>]]></programlisting>
+
+ <para>
+ Como você pode ver, a vantagem deste enfoque é a externalização dos nomes dos
+ arquivos de mapeamento para configuração. O
<literal>hibernate.cfg.xml</literal>
+ também é mais conveniente caso você tenha que ajustar o cache do Hibernate.
+ Note que a escolha é sua em usar
<literal>hibernate.properties</literal> ou
+ <literal>hibernate.cfg.xml</literal>, ambos são equivalente, à
exceção dos benefícios
+ acima mencionados de usar a sintaxe de XML.
+ </para>
+
+ <para>
+ Com a configuração do XML, iniciar o Hibernate é então tão simples como
+ </para>
+
+ <programlisting><![CDATA[SessionFactory sf = new
Configuration().configure().buildSessionFactory();]]></programlisting>
+
+ <para>
+ You can pick a different XML configuration file using
+ </para>
+
+ <programlisting><![CDATA[SessionFactory sf = new Configuration()
+ .configure("catdb.cfg.xml")
+ .buildSessionFactory();]]></programlisting>
+
+ </sect1>
+
+ <sect1 id="configuration-j2ee" revision="1">
+ <title>Integração com servidores de aplicação J2EE</title>
+
+ <para>
+ O Hibernate tem os seguintes pontos da integração para o infraestrutura de
J2EE:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis>DataSources gerenciados pelo container</emphasis>:
O Hibernate pode
+ usar conexões JDBC gerenciadas pelo Container e fornecidas pela JNDI.
Geralmente,
+ um <literal>TransactionManager</literal> compatível com JTA e
um
+ <literal>ResourceManager</literal> cuidam do gerenciamento da
transação ( CMT ),
+ especialmente em transações distribuídas manipuladas através de vários
DataSources.
+ Naturalmente, você também pode demarcar os limites das transações
programaticamente (BMT)
+ ou você poderia querer usar a API opcional do Hibernate
<literal>Transaction</literal>
+ para esta manter seu código portável.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis>Ligação (binding) automática a JNDI</emphasis>: O
Hibernate pode
+ associar sua <literal>SessionFactory</literal> a JNDI depois
de iniciado.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis>Ligação (binding) Session na JTA:</emphasis>
+ A <literal>Session</literal> do Hibernate pode
automaticamente ser ligada
+ ao escopo da transações JTA. Simplesmente localizando a
<literal>SessionFactory</literal>
+ da JNDI e obtendo a<literal>Session</literal> corrente. Deixe
o Hibernate cuidar
+ da limpeza e encerramento da <literal>Session</literal>
quando as transações JTA
+ terminarem. A Demarcação de transação pode ser declarativa (CMT) ou
+ programática(BMT/Transação do usuário).
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis>JMX deployment:</emphasis> Se você usa um JMX
servidor de
+ aplicações capaz (ex. Jboss AS), você pode fazer a instação do Hibernate
+ como um Mbean controlado. Isto evita ter que iniciar uma linha de
+ código para construir sua <literal>SessionFactory</literal>
de uma
+ <literal>Configuration</literal>. O container iniciará seu
+ <literal>HibernateService</literal>, e idealmente também
cuidará
+ das dependências de serviços (DataSources, têm que estar disponíveis
+ antes do Hibernate iniciar, etc.).
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Dependendo em seu ambiente, você poderia ter que ajustar a opção de
configuração
+ <literal>hibernate.connection.aggressive_release</literal> para
verdadeiro ( true ),
+ se seu servidor de aplicações lançar exeções "retenção de
conecção".
+ </para>
+
+ <sect2 id="configuration-optional-transactionstrategy"
revision="3">
+ <title>Configuração de estratégia de transação</title>
+
+ <para>
+ A API Hibernate <literal>Session</literal> é independente de
qualquer sistema de
+ demarcação de transação em sua arquitetura. Se você deixar o Hibernate
usar
+ a JDBC diretamente, através de um pool de conexões, você pode inicializar
e
+ encerrar suas transações chamando a API JDBC. Se você rodar em um
servidor de
+ aplicações J2EE, você poderá usar transações controladas por beans e
chamar
+ a API JTA e <literal>UserTransaction</literal> quando
necessário.
+
+ </para>
+
+ <para>
+ Para manter seu código portável entre estes dois ( e outros ) ambientes,
recomendamos
+ a API Hibernate <literal>Transaction</literal>, que envolve e
esconde o sistema subjacente.
+ Você tem que especificar um classe construtora para
<literal>Transaction</literal> instanciar
+ ajustando a propriedade de configuração do
<literal>hibernate.transaction.factory_class</literal>.
+
+ </para>
+
+ <para>
+ Existem três escolhas (internas) padrões:
+ </para>
+
+ <variablelist spacing="compact">
+ <varlistentry>
+
<term><literal>org.hibernate.transaction.JDBCTransactionFactory</literal></term>
+ <listitem>
+ <para>delegada as transações (JDBC)a bases de dados
(Padrão)</para>
+
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+
<term><literal>org.hibernate.transaction.JTATransactionFactory</literal></term>
+ <listitem>
+ <para>
+ delegada a transação a um container gerenciador se a
transação
+ existente estiver de acordo neste contexto (ex: método bean
sessão EJB),
+ se não uma nova transação é iniciada e uma transação
controlado por
+ um bean é usada.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+
<term><literal>org.hibernate.transaction.CMTTransactionFactory</literal></term>
+ <listitem>
+ <para>delega para um container gerenciador de transações
JTA</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>
+ Você também pode definir suas próprias estratégias de transação ( para um
serviço de
+ transação CORBA por exemplo).
+ </para>
+
+ <para>
+ Algumas características no Hibernate (ex., o cache de segundo nível,
sessões contextuais
+ com JTA, etc.) requerem acesso a JTA
<literal>TransactionManager</literal> em um ambiente
+ controlado. Em um servidor de aplicação você tem que especificar como o
Hibernate pode
+ obter uma referência para a
<literal>TransactionManager</literal>, pois o J2EE não
+ padronize um mecanismo simples :
+ </para>
+
+ <table frame="topbot" id="jtamanagerlookup"
revision="1">
+ <title>Gerenciadores de transações JTA</title>
+ <tgroup cols="2">
+ <colspec colwidth="2.5*"/>
+ <colspec colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>Transaction Factory</entry>
+ <entry align="center">Application
Server</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+
<entry><literal>org.hibernate.transaction.JBossTransactionManagerLookup</literal></entry>
+ <entry align="center">JBoss</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.transaction.WeblogicTransactionManagerLookup</literal></entry>
+ <entry align="center">Weblogic</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.transaction.WebSphereTransactionManagerLookup</literal></entry>
+ <entry
align="center">WebSphere</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.transaction.WebSphereExtendedJTATransactionLookup</literal></entry>
+ <entry align="center">WebSphere
6</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.transaction.OrionTransactionManagerLookup</literal></entry>
+ <entry align="center">Orion</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.transaction.ResinTransactionManagerLookup</literal></entry>
+ <entry align="center">Resin</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.transaction.JOTMTransactionManagerLookup</literal></entry>
+ <entry align="center">JOTM</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.transaction.JOnASTransactionManagerLookup</literal></entry>
+ <entry align="center">JOnAS</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.transaction.JRun4TransactionManagerLookup</literal></entry>
+ <entry align="center">JRun4</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.transaction.BESTransactionManagerLookup</literal></entry>
+ <entry align="center">Borland
ES</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ </sect2>
+
+ <sect2 id="configuration-optional-jndi" revision="3">
+ <title><literal>SessionFactory</literal> ligada a
JNDI</title>
+
+ <para>
+ Uma <literal>SessionFactory</literal> de Hibernate ligada a
JNDI pode simplificar
+ a localização da fabrica e a criação de novas
<literal>Session</literal>s.
+ Observe que isto não relacionado a um
<literal>Datasource</literal> ligado
+ a JNDI, simplemente ambos usam o mesmo registro!
+ </para>
+
+ <para>
+ If you wish to have the <literal>SessionFactory</literal>
bound to a JNDI namespace, specify
+ a name (eg. <literal>java:hibernate/SessionFactory</literal>)
using the property
+ <literal>hibernate.session_factory_name</literal>. If this
property is omitted, the
+ <literal>SessionFactory</literal> will not be bound to JNDI.
(This is especially useful in
+ environments with a read-only JNDI default implementation, e.g. Tomcat.)
+ </para>
+
+ <para>
+ When binding the <literal>SessionFactory</literal> to JNDI,
Hibernate will use the values of
+ <literal>hibernate.jndi.url</literal>,
<literal>hibernate.jndi.class</literal> to instantiate
+ an initial context. If they are not specified, the default
<literal>InitialContext</literal>
+ will be used.
+ </para>
+
+ <para>
+ Hibernate will automatically place the
<literal>SessionFactory</literal> in JNDI after
+ you call <literal>cfg.buildSessionFactory()</literal>. This
means you will at least have
+ this call in some startup code (or utility class) in your application,
unless you use
+ JMX deployment with the <literal>HibernateService</literal>
(discussed later).
+ </para>
+
+ <para>
+ If you use a JNDI <literal>SessionFactory</literal>, an EJB
or any other class may
+ obtain the <literal>SessionFactory</literal> using a JNDI
lookup.
+ </para>
+
+ <para>
+ We recommend that you bind the
<literal>SessionFactory</literal> to JNDI in
+ a managend environment and use a <literal>static</literal>
singleton otherwise.
+ To shield your application code from these details, we also recommend to
hide the
+ actual lookup code for a <literal>SessionFactory</literal> in
a helper class,
+ such as <literal>HibernateUtil.getSessionFactory()</literal>.
Note that such a
+ class is also a convenient way to startup Hibernate—see chapter
1.
+ </para>
+
+ </sect2>
+
+ <sect2 id="configuration-j2ee-currentsession"
revision="4">
+ <title>Current Session context management with JTA</title>
+
+ <para>
+ The easiest way to handle <literal>Session</literal>s and
transactions is
+ Hibernates automatic "current"
<literal>Session</literal> management.
+ See the discussion of <xref
linkend="architecture-current-session">current sessions</xref>.
+ Using the <literal>"jta"</literal> session context,
if there is no Hibernate
+ <literal>Session</literal> associated with the current JTA
transaction, one will
+ be started and associated with that JTA transaction the first time you call
+ <literal>sessionFactory.getCurrentSession()</literal>. The
<literal>Session</literal>s
+ retrieved via <literal>getCurrentSession()</literal> in
<literal>"jta"</literal> context
+ will be set to automatically flush before the transaction completes, close
+ after the transaction completes, and aggressively release JDBC connections
+ after each statement. This allows the
<literal>Session</literal>s to
+ be managed by the life cycle of the JTA transaction to which it is
associated,
+ keeping user code clean of such management concerns. Your code can either
use
+ JTA programmatically through <literal>UserTransaction</literal>,
or (recommended
+ for portable code) use the Hibernate
<literal>Transaction</literal> API to set
+ transaction boundaries. If you run in an EJB container, declarative
transaction
+ demarcation with CMT is preferred.
+ </para>
+
+ </sect2>
+
+ <sect2 id="configuration-j2ee-jmx" revision="1">
+ <title>JMX deployment</title>
+
+ <para>
+ The line <literal>cfg.buildSessionFactory()</literal> still
has to be executed
+ somewhere to get a <literal>SessionFactory</literal> into
JNDI. You can do this
+ either in a <literal>static</literal> initializer block (like
the one in
+ <literal>HibernateUtil</literal>) or you deploy Hibernate as
a <emphasis>managed
+ service</emphasis>.
+ </para>
+
+ <para>
+ Hibernate is distributed with
<literal>org.hibernate.jmx.HibernateService</literal>
+ for deployment on an application server with JMX capabilities, such as
JBoss AS.
+ The actual deployment and configuration is vendor specific. Here is an
example
+ <literal>jboss-service.xml</literal> for JBoss 4.0.x:
+ </para>
+
+ <programlisting><![CDATA[<?xml version="1.0"?>
+<server>
+
+<mbean code="org.hibernate.jmx.HibernateService"
+ name="jboss.jca:service=HibernateFactory,name=HibernateFactory">
+
+ <!-- Required services -->
+ <depends>jboss.jca:service=RARDeployer</depends>
+ <depends>jboss.jca:service=LocalTxCM,name=HsqlDS</depends>
+
+ <!-- Bind the Hibernate service to JNDI -->
+ <attribute
name="JndiName">java:/hibernate/SessionFactory</attribute>
+
+ <!-- Datasource settings -->
+ <attribute name="Datasource">java:HsqlDS</attribute>
+ <attribute
name="Dialect">org.hibernate.dialect.HSQLDialect</attribute>
+
+ <!-- Transaction integration -->
+ <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>
+
+ <!-- Fetching options -->
+ <attribute name="MaximumFetchDepth">5</attribute>
+
+ <!-- Second-level caching -->
+ <attribute name="SecondLevelCacheEnabled">true</attribute>
+ <attribute
name="CacheProviderClass">org.hibernate.cache.EhCacheProvider</attribute>
+ <attribute name="QueryCacheEnabled">true</attribute>
+
+ <!-- Logging -->
+ <attribute name="ShowSqlEnabled">true</attribute>
+
+ <!-- Mapping files -->
+ <attribute
name="MapResources">auction/Item.hbm.xml,auction/Category.hbm.xml</attribute>
+
+</mbean>
+
+</server>]]></programlisting>
+
+ <para>
+ This file is deployed in a directory called
<literal>META-INF</literal> and packaged
+ in a JAR file with the extension <literal>.sar</literal>
(service archive). You also need
+ to package Hibernate, its required third-party libraries, your compiled
persistent classes,
+ as well as your mapping files in the same archive. Your enterprise beans
(usually session
+ beans) may be kept in their own JAR file, but you may include this EJB
JAR file in the
+ main service archive to get a single (hot-)deployable unit. Consult the
JBoss AS
+ documentation for more information about JMX service and EJB deployment.
+ </para>
+
+ </sect2>
+
+ </sect1>
+
+</chapter>
+
Modified: core/trunk/documentation/manual/pt-BR/src/main/docbook/content/events.xml
===================================================================
--- core/trunk/documentation/manual/pt-BR/src/main/docbook/content/events.xml 2007-10-26
00:46:38 UTC (rev 14135)
+++ core/trunk/documentation/manual/pt-BR/src/main/docbook/content/events.xml 2007-10-26
00:48:48 UTC (rev 14136)
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="events">
+<chapter id="events">
<title>Interceptadores e Eventos</title>
<para>
Modified:
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/example_mappings.xml
===================================================================
---
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/example_mappings.xml 2007-10-26
00:46:38 UTC (rev 14135)
+++
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/example_mappings.xml 2007-10-26
00:48:48 UTC (rev 14136)
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="example-mappings">
+<chapter id="example-mappings">
<title>Exemplo: Vários Mapeamentos</title>
<para>
Modified:
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/example_parentchild.xml
===================================================================
---
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/example_parentchild.xml 2007-10-26
00:46:38 UTC (rev 14135)
+++
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/example_parentchild.xml 2007-10-26
00:48:48 UTC (rev 14136)
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="example-parentchild">
+<chapter id="example-parentchild">
<title>Example: Parent/Child</title>
<para>
Modified:
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/example_weblog.xml
===================================================================
---
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/example_weblog.xml 2007-10-26
00:46:38 UTC (rev 14135)
+++
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/example_weblog.xml 2007-10-26
00:48:48 UTC (rev 14136)
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="example-weblog">
+<chapter id="example-weblog">
<title>Example: Weblog Application</title>
<sect1 id="example-weblog-classes">
Modified: core/trunk/documentation/manual/pt-BR/src/main/docbook/content/filters.xml
===================================================================
--- core/trunk/documentation/manual/pt-BR/src/main/docbook/content/filters.xml 2007-10-26
00:46:38 UTC (rev 14135)
+++ core/trunk/documentation/manual/pt-BR/src/main/docbook/content/filters.xml 2007-10-26
00:48:48 UTC (rev 14136)
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="filters">
+<chapter id="filters">
<title>Filtrando dados</title>
<para>
Modified:
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/inheritance_mapping.xml
===================================================================
---
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/inheritance_mapping.xml 2007-10-26
00:46:38 UTC (rev 14135)
+++
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/inheritance_mapping.xml 2007-10-26
00:48:48 UTC (rev 14136)
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="inheritance">
+<chapter id="inheritance">
<title>Mapeamento de Herança</title>
<sect1 id="inheritance-strategies" revision="3">
Modified: core/trunk/documentation/manual/pt-BR/src/main/docbook/content/performance.xml
===================================================================
---
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/performance.xml 2007-10-26
00:46:38 UTC (rev 14135)
+++
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/performance.xml 2007-10-26
00:48:48 UTC (rev 14136)
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="performance">
+<chapter id="performance">
<title>Aumentando a performance</title>
<sect1 id="performance-fetching" revision="2">
Modified:
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/persistent_classes.xml
===================================================================
---
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/persistent_classes.xml 2007-10-26
00:46:38 UTC (rev 14135)
+++
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/persistent_classes.xml 2007-10-26
00:48:48 UTC (rev 14136)
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="persistent-classes" revision="2">
+<chapter id="persistent-classes" revision="2">
<title>Persistent Classes</title>
<para>
Modified: core/trunk/documentation/manual/pt-BR/src/main/docbook/content/preface.xml
===================================================================
--- core/trunk/documentation/manual/pt-BR/src/main/docbook/content/preface.xml 2007-10-26
00:46:38 UTC (rev 14135)
+++ core/trunk/documentation/manual/pt-BR/src/main/docbook/content/preface.xml 2007-10-26
00:48:48 UTC (rev 14136)
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding="UTF-8"?>
<!DOCTYPE preface PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<preface id="preface" revision="2">
+<preface id="preface" revision="2">
<title>Prefácio</title>
<para>
Modified:
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/query_criteria.xml
===================================================================
---
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/query_criteria.xml 2007-10-26
00:46:38 UTC (rev 14135)
+++
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/query_criteria.xml 2007-10-26
00:48:48 UTC (rev 14136)
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="querycriteria">
+<chapter id="querycriteria">
<title>Consultas por critérios</title>
<para>
Modified: core/trunk/documentation/manual/pt-BR/src/main/docbook/content/query_hql.xml
===================================================================
---
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/query_hql.xml 2007-10-26
00:46:38 UTC (rev 14135)
+++
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/query_hql.xml 2007-10-26
00:48:48 UTC (rev 14136)
@@ -1,1163 +1,1174 @@
<?xml version='1.0' encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="queryhql">
- <title>HQL: A linguagem de Queries do Hibernate</title>
-
- <para>
- O Hibernate vem com uma poderosa linguagem que é (intencionalmente) muito
parecida
- com o SQL. Mas não seja enganado pela sintaxe; a HQL é totalmente orientada à
objetos,
- requer conhecimentos de herança, polimorfismo e associações.
- </para>
-
- <sect1 id="queryhql-casesensitivity">
- <title>Case Sensitíve</title>
-
- <para>
- As Queries não são case-sensitive, exceto pelo nomes das classes e
propriedades Java.
- <literal>sELEct</literal> e o mesmo que
- <literal>SELECT</literal> mas
- <literal>org.hibernate.eg.FOO</literal> não é
- <literal>org.hibernate.eg.Foo</literal> e
- <literal>foo.barSet</literal> não é
- <literal>foo.BARSET</literal>.
-
- </para>
-
- <para>
- Esse manual usa as palavras chave HQL em letras minúsculas. Alguns usuários
acham que
- com letras maiúsculas as queries ficam mais legíveis, mas nós achamos essa
convenção feia
- dentro do código Java.
- </para>
-
- </sect1>
-
- <sect1 id="queryhql-from">
- <title>A clausula from</title>
-
- <para>
- A mais simples query possível do Hibernate é a assim:
- </para>
-
- <programlisting><![CDATA[from eg.Cat]]></programlisting>
-
- <para>
- Ela irá retornar todas as instancias da classe
<literal>eg.Cat</literal>.
- Necessariamente não precisamos qualificar o nome da classe, pois é realizado
- <literal>auto-import</literal> por padrão. Por isso na maior
parte do tempos
- nós simplesmente escrevemos:
- </para>
-
- <programlisting><![CDATA[from Cat]]></programlisting>
-
- <para>
- Na maior parte do tempo, você precisará atribuir um
<emphasis>alias</emphasis>,
- desde que você queira se referia ao <literal>Cat</literal> em
outras partes da
- query.
- </para>
-
- <programlisting><![CDATA[from Cat as cat]]></programlisting>
-
- <para>
- Essa query atribui um alias a <literal>cat</literal> para as
instancias de
- <literal>Cat</literal>, então nós podemos usar esse alias depois
na query.
- A palavra chave as é opcional; poderíamos escrever assim:
- </para>
-
- <programlisting><![CDATA[from Cat cat]]></programlisting>
-
- <para>
- Múltiplas classes pode ser envolvidas, resultando em um produto cartesiano ou
"cross" join.
- </para>
-
- <programlisting><![CDATA[from Formula,
Parameter]]></programlisting>
- <programlisting><![CDATA[from Formula as form, Parameter as
param]]></programlisting>
-
- <para>
- É considerada uma boa prática os nomes dos aliases começarem com letra
minúscula,
- aderente com os padrões Java para variáveis locais (ex:
<literal>domesticCat</literal>).
- </para>
-
- </sect1>
-
- <sect1 id="queryhql-joins" revision="2">
- <title>Associações e joins</title>
-
- <para>
- Nós também podemos querer atribuir aliases em uma entidade associada, ou
mesmo
- em elementos de uma coleção de valores, usando um
<literal>join</literal>.
- </para>
-
- <programlisting><![CDATA[from Cat as cat
- inner join cat.mate as mate
- left outer join cat.kittens as kitten]]></programlisting>
-
- <programlisting><![CDATA[from Cat as cat left join cat.mate.kittens as
kittens]]></programlisting>
-
- <programlisting><![CDATA[from Formula form full join form.parameter
param]]></programlisting>
-
- <para>
- Os tipos de joins suportados foram inspirados no SQL ANSI:
- </para>
-
- <itemizedlist spacing="compact">
- <listitem>
- <para>
- <literal>inner join</literal>
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>left outer join</literal>
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>right outer join</literal>
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>full join</literal> (geralmente não é útil)
- </para>
- </listitem>
- </itemizedlist>
-
- <para>
- The <literal>inner join</literal>, <literal>left outer
join</literal> and
- <literal>right outer join</literal> constructs may be
abbreviated.
- As construções <literal>inner join</literal>, <literal>left
outer join</literal> e
- <literal>right outer join</literal> podem ser abreviadas.
- </para>
-
- <programlisting><![CDATA[from Cat as cat
- join cat.mate as mate
- left join cat.kittens as kitten]]></programlisting>
-
- <para>
- Você pode fornecer condições extras de join usando a palavra
- chave do HQL <literal>with</literal>.
- </para>
-
- <programlisting><![CDATA[from Cat as cat
- left join cat.kittens as kitten
- <literal>with</literal> kitten.bodyWeight >
10.0]]></programlisting>
-
- <para>
- Adicionalmente, um "fetch" join permite que associações ou coleções
de valores
- sejam inicializadas junto com o objeto pai, usando apenas um select. Isso é
- muito útil no caso das coleções. Isso efetivamente sobre escreve as
declarações
- outer join e lazy do arquivo mapeamento para associações e coleções.
- Veja a seção <xref linkend="performance-fetching"/> para
mais informações.
- </para>
-
- <programlisting><![CDATA[from Cat as cat
- inner join <literal>fetch</literal>cat.mate
- left join
<literal>fetch</literal>cat.kittens]]></programlisting>
-
- <para>
- Usualmente, um <literal>fetch</literal>join não precisa atribuir
um alias, pois o objeto associado não
- deve ser usado na clausula <literal>where</literal> (ou em
qualquer outra clausula).
- Também, os objetos associados não são retornados diretamente nos resultados
da query.
- Ao invés disso, eles devem ser acessados usando o objeto pai. A única razão
que nós
- podemos necessitar de um alias é quando fazemos um fech join recursivamente
em uma
- coleção adicional:
- </para>
-
- <programlisting><![CDATA[from Cat as cat
- inner join <literal>fetch</literal>cat.mate
- left join <literal>fetch</literal>cat.kittens child
- left join
<literal>fetch</literal>child.kittens]]></programlisting>
-
- <para>
- Observe que a construção <literal>fetch</literal> não deve ser
usada em queries invocadas usando
- <literal>iterate()</literal> (embora possa ser usado com
<literal>scroll()</literal>). O
- <literal>fetch</literal> também não deve ser usado junto com o
<literal>setMaxResults()</literal> ou
- <literal>setFirstResult()</literal> pois essas operações são
baseadas nas linhas retornadas, que
- normalmente contem duplicidade devido ao fetching das coleções, então o
número de linhas pode não
- ser o que você espera.
-
- O <literal>fetch</literal> não deve ser usado junto com uma
condição <literal>with</literal> em
- uma condição <literal>with</literal> ad hoc. É possível que seja
criado um produto cartesiano pelo
- join fetching em mais do que uma coleção em uma query, então tome cuidado
nesses casos. Um join
- fetching em varias coleções pode trazer resultados inesperados para
mapeamentos do tipo bag, tome
- cuidado na hora de formular queries como essas. Finalmente, observe o
seguinte, o
- <literal>full join fetch</literal> e <literal>right join
fetch</literal> não são significativos.
- </para>
-
- <para>
-
- Se está usando o nível de propriedade lazy
(<literal>com</literal> instrumentação de bytecode), é possível
- forçar o Hibernate a <literal>buscar</literal> as propriedades
lazy imediatamente (na primeira query),
- usando <literal>fetch all properties </literal>.
- </para>
-
- <programlisting><![CDATA[from Document
<literal>fetch</literal>all properties order by
name]]></programlisting>
- <programlisting><![CDATA[from Document doc
<literal>fetch</literal>all properties where lower(doc.name) like
'%cats%']]></programlisting>
-
- </sect1>
-
- <sect1 id="queryhql-joins-forms">
- <title>Formas e sintaxe de joins</title>
-
- <para>
- O HQL suporta duas formas de associação para união:
<literal>implícita</literal> e <literal>explicita</literal>.
- </para>
-
- <para>
- As queries apresentadas na seção anterior usam a forma
<literal>explicita</literal>, onde a
- palavra chave "join" é explicitamente usada na clausula "from".
Essa é a forma recomendada.
- </para>
-
- <para>
- A forma <literal>implícita</literal> não usa a palavra chave
"join". Entretanto, as associações
- são diferenciadas usando pontuação ("." - dotnation). Uniões implícitas
podem aparecer em
- qualquer das clausulas HQL. A união <literal>implícita</literal>
resulta em declarações
- SQL que contem inner joins.
- </para>
-
- <programlisting><![CDATA[from Cat as cat where cat.mate.name like
'%s%']]></programlisting>
- </sect1>
-
- <sect1 id="queryhql-select">
- <title>Clausula select</title>
-
- <para>
- A clausula <literal>select</literal> seleciona quais obetos e
propriedades retornam
- no resultado da query. Considere:
- </para>
-
- <programlisting><![CDATA[select mate
-from Cat as cat
- inner join cat.mate as mate]]></programlisting>
-
- <para>
- A query selecionará <literal>mate</literal>s (companheiros), de
outros <literal>Cat</literal>s.
- Atualmente, podemos expressar a query de forma mais compacta como:
- </para>
-
- <programlisting><![CDATA[select cat.mate from Cat
cat]]></programlisting>
-
- <para>
- Queries podem retornar propriedades de qualquer tipo de valor, incluindo
propriedades de tipo de componente:
-
- </para>
-
- <programlisting><![CDATA[select cat.name from DomesticCat cat
-where cat.name like 'fri%']]></programlisting>
-
- <programlisting><![CDATA[select cust.name.firstName from Customer as
cust]]></programlisting>
-
- <para>
- Queries podem retornar múltiplos objetos e/ou propriedades como um array do
- tipo Object[],
- </para>
-
- <programlisting><![CDATA[select mother, offspr, mate.name
-from DomesticCat as mother
- inner join mother.mate as mate
- left outer join mother.kittens as offspr]]></programlisting>
-
- <para>
- ou como um <literal>List</literal>,
- </para>
-
- <programlisting><![CDATA[select new list(mother, offspr, mate.name)
-from DomesticCat as mother
- inner join mother.mate as mate
- left outer join mother.kittens as offspr]]></programlisting>
-
- <para>
- ou como um objeto Java typesafe,
- </para>
-
- <programlisting><![CDATA[select new Family(mother, mate, offspr)
-from DomesticCat as mother
- join mother.mate as mate
- left join mother.kittens as offspr]]></programlisting>
-
- <para>
- assumindo que a classe <literal>Family</literal> tenha um
construtor apropriado.
- </para>
-
- <para>
- Pode-se designar referencias a expressões selecionadas,
<literal>as</literal>:
- </para>
-
- <programlisting><![CDATA[select max(bodyWeight) as max, min(bodyWeight)
as min, count(*) as n
-from Cat cat]]></programlisting>
-
- <para>
- Isto é bem mais útil quando usado junto <literal>com</literal>
<literal>select new map</literal>:
- </para>
-
- <programlisting><![CDATA[select new map( max(bodyWeight) as max,
min(bodyWeight) as min, count(*) as n )
-from Cat cat]]></programlisting>
-
- <para>
- Esta query retorna um <literal>Map</literal> de referencias para
valores selecionados.
- </para>
-
- </sect1>
-
- <sect1 id="queryhql-aggregation">
- <title>Funções de agregação</title>
-
- <para>
- As queries HQL podem retornar o resultado de funções agregadas nas
propriedades.
- </para>
-
- <programlisting><![CDATA[select avg(cat.weight), sum(cat.weight),
max(cat.weight), count(cat)
-from Cat cat]]></programlisting>
-
-<!-- NO LONGER SUPPORTED
- <para>
- Collections may also appear inside aggregate functions in the
<literal>select</literal>
- clause.
- </para>
-
- <programlisting><![CDATA[select cat, count( elements(cat.kittens) )
-from Cat cat group by cat]]></programlisting>
--->
-
- <para>
- As funções agregadas suportadas são:
- </para>
-
- <itemizedlist spacing="compact">
- <listitem>
- <para>
- <literal>avg(...), sum(...), min(...),
max(...)</literal>
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>count(*)</literal>
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>count(...), count(distinct ...),
count(all...)</literal>
- </para>
- </listitem>
- </itemizedlist>
-
- <para>
- Pode-se usar operadores aritiméticos, concatenação e funções SQL
- reconhecidas na clausula select:
- </para>
-
- <programlisting><![CDATA[select cat.weight + sum(kitten.weight)
-from Cat cat
- join cat.kittens kitten
-group by cat.id, cat.weight]]></programlisting>
-
- <programlisting><![CDATA[select firstName||' '||initial||'
'||upper(lastName) from Person]]></programlisting>
-
- <para>
- As palavras <literal>distinct</literal> e
<literal>all</literal> podem ser usadas e têm
- a mesma semântica como no SQL.
- </para>
-
- <programlisting><![CDATA[select distinct cat.name from Cat cat
-
-select count(distinct cat.name), count(cat) from Cat cat]]></programlisting>
-
- </sect1>
-
- <sect1 id="queryhql-polymorphism">
- <title>Queries polimórficas</title>
-
- <para>
- A query:
- </para>
-
- <programlisting><![CDATA[from Cat as cat]]></programlisting>
-
- <para>
- retorna instancias não só de <literal>Cat</literal>, mas também
de subclasses como
- <literal>DomesticCat</literal>. As queries do Hibernate podem
nomear qualquer classe Java
- ou interface na clausula <literal>from</literal>. A query
retornará instancias de toda classe
- persistente que extenda a determinada classe ou implemente a determinada
interface. A query
- , a seguir, pode retornar todo objeto persistente:
- </para>
-
- <programlisting><![CDATA[from java.lang.Object
o]]></programlisting>
-
- <para>
- A interface <literal>Named</literal> pode ser implementada por
várias classes persistentes:
- </para>
-
- <programlisting><![CDATA[from Named n, Named m where n.name =
m.name]]></programlisting>
-
- <para>
- Note que as duas últimas queries requerem mais de um SQL SELECT . Isto
significa que a clausula
- <literal>order by</literal> não ordena corretamente todo o
resultado. (Isso também significa que
- você não pode chamar essas queries usando
<literal>Query.scroll()</literal>.)
- </para>
-
- </sect1>
-
- <sect1 id="queryhql-where">
- <title>A clausula where</title>
-
- <para>
- A clausula <literal>where</literal> permite estreitar a lista de
instancias retornada.
- Se não houver referencia alguma, pode-se referir a propriedades pelo nome:
- </para>
-
- <programlisting><![CDATA[from Cat where
name='Fritz']]></programlisting>
-
- <para>
- Se houver uma referência, use o nome da propriedade qualificada:
- </para>
-
- <programlisting><![CDATA[from Cat as cat where
cat.name='Fritz']]></programlisting>
-
- <para>
- retorna instancias de <literal>Cat</literal> com nome ‘Fritz’.
- </para>
-
- <programlisting><![CDATA[select foo
-from Foo foo, Bar bar
-where foo.startDate = bar.date]]></programlisting>
-
- <para>
- retornará todas as instancias de <literal>Foo</literal>, para
cada
- um que tiver uma instancia de <literal>bar</literal> com a
propriedade
- <literal>date</literal> igual a propriedade
- <literal>startDate</literal> de
- <literal>Foo</literal>. Expressões de filtro compostas fazem da
- clausula <literal>where</literal>, extremamente poderosa.
Consideremos:
- </para>
-
- <programlisting><![CDATA[from Cat cat where cat.mate.name is not
null]]></programlisting>
-
- <para>
- Esta query traduzida para uma query SQL <literal>com</literal>
uma tabela (inner) join. Se fosse
- escrever algo como:
- </para>
-
- <programlisting><![CDATA[from Foo foo
-where foo.bar.baz.customer.address.city is not null]]></programlisting>
-
- <para>
- Poderia-se terminar <literal>com</literal> uma query que
necessitasse de join de quatro tabelas,
- no SQL.
- </para>
-
- <para>
- O operador <literal>=</literal> pode ser uasdo para comparar não
apenas propriedades,
- mas também instancias:
- </para>
-
- <programlisting><![CDATA[from Cat cat, Cat rival where cat.mate =
rival.mate]]></programlisting>
-
- <programlisting><![CDATA[select cat, mate
-from Cat cat, Cat mate
-where cat.mate = mate]]></programlisting>
-
- <para>
- A propriedade especial (lowercase) <literal>id</literal> pode
ser usada para referenciar
- o identificador único de um objeto. (Pode-se usar também o nome de sua
propriedade)
- </para>
-
- <programlisting><![CDATA[from Cat as cat where cat.id = 123
-
-from Cat as cat where cat.mate.id = 69]]></programlisting>
-
- <para>
- A Segunda query é eficiente. Nenhuma união de tabelas é necessária!
- </para>
-
- <para>
- As propriedades de identificadores compostas também podem ser usadas. Suponha
que
- <literal>Person</literal> tenha um identificador composto que
consiste de
- <literal>country</literal> e
<literal>medicareNumber</literal>.
- </para>
-
- <programlisting><![CDATA[from bank.Person person
-where person.id.country = 'AU'
- and person.id.medicareNumber = 123456]]></programlisting>
-
- <programlisting><![CDATA[from bank.Account account
-where account.owner.id.country = 'AU'
- and account.owner.id.medicareNumber = 123456]]></programlisting>
-
- <para>
- Mais uma vez, a Segunda query não precisa de nenhum join de tabela.
- </para>
-
- <para>
- Assim mesmo, a propriedade especial <literal>class</literal>
acessa o valor discriminador da
- instancia, no caso de persistência polimórfica. O nome de uma classe Java
inclusa em uma
- clausula "where", será traduzida para seu valor descriminante.
- </para>
-
- <programlisting><![CDATA[from Cat cat where cat.class =
DomesticCat]]></programlisting>
-
- <para>
- Pode-se também especificar as propriedades dos components ou tipos de usuário
composto
- (e de componentes de componentes). Nunca tente usar uma expressão de filtro
que termine na propriedade
- de um tipo de componente (ao contrário de uma propriedade de um componente).
Por exemplo,
- se store.owner é uma entidade <literal>com</literal> um
componente <literal>address</literal>.
- </para>
-
- <programlisting><![CDATA[store.owner.address.city // okay
-store.owner.address // error!]]></programlisting>
-
- <para>
- Um tipo "any" tem as propriedades <literal>id</literal>
e <literal>class</literal> especiais,
- nôs permitindo expressar um join da seguinte forma (onde
<literal>AuditLog.item</literal> é
- uma propriedade mapeada <literal>com</literal>
<literal><any></literal>)
- </para>
-
- <programlisting><![CDATA[from AuditLog log, Payment payment
-where log.item.class = 'Payment' and log.item.id =
payment.id]]></programlisting>
-
- <para>
- Veja que <literal>log.item.class</literal> e
<literal>payment.class</literal> podem
- referir-se a valores de colunas de banco de dados completamente diferentes,
na query acima.
- </para>
-
- </sect1>
-
- <sect1 id="queryhql-expressions">
- <title>Expressões</title>
-
- <para>
- As expressões permitidas na cláusula <literal>where</literal>
inclui a maioria
- das coisas que você poderia escrever no SQL:
- </para>
-
- <itemizedlist spacing="compact">
- <listitem>
- <para>
- operadores matemáticos <literal>+, -, *, /</literal>
- </para>
- </listitem>
- <listitem>
- <para>
- operadores de comparação binários <literal>=, >=,
<=, <>, !=, like</literal>
- </para>
- </listitem>
- <listitem>
- <para>
- operadores lógicos <literal>and, or, not</literal>
- </para>
- </listitem>
- <listitem>
- <para>
- parenteses <literal>( )</literal>, indicating grouping
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>in</literal>,
- <literal>not in</literal>,
- <literal>between</literal>,
- <literal>is null</literal>,
- <literal>is not null</literal>,
- <literal>is empty</literal>,
- <literal>is not empty</literal>,
- <literal>member of</literal> and
- <literal>not member of</literal>
- </para>
- </listitem>
- <listitem>
- <para>
- case "simples" , <literal>case ... when ... then ...
else ... end</literal>, and
- "searched" case, <literal>case when ... then ... else
... end</literal>
- </para>
- </listitem>
- <listitem>
- <para>
- concatenação de string <literal>...||...</literal> ou
<literal>concat(...,...)</literal>
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>current_date()</literal>,
<literal>current_time()</literal>,
- <literal>current_timestamp()</literal>
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>second(...)</literal>,
<literal>minute(...)</literal>,
- <literal>hour(...)</literal>, <literal>day(...)</literal>,
- <literal>month(...)</literal>,
<literal>year(...)</literal>,
- </para>
- </listitem>
- <listitem>
- <para>
- qualquer funcao ou operador definida pela EJB-QL 3.0:
<literal>substring(), trim(),
- lower(), upper(), length(), locate(), abs(), sqrt(), bit_length(),
mod()</literal>
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>coalesce()</literal> and
<literal>nullif()</literal>
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>str()</literal> para converter valores numericos
ou temporais para string
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>cast(... as ...)</literal>, onde o segundo
argumento é o nome do tipo
- hibernate, e<literal>extract(... from ...)</literal> se
ANSI
- <literal>cast()</literal> e
<literal>extract()</literal> é suportado pele
- banco de dados usado
- </para>
- </listitem>
- <listitem>
- <para>
- A função HQL <literal>index()</literal> , que se aplicam
a referencias de
- coleçôes associadas e indexadas
- </para>
- </listitem>
- <listitem>
- <para>
- As funções hql que retornam expressões de coleções de valores:
- <literal>size(), minelement(), maxelement(), minindex(),
maxindex()</literal>,
- <literal>junto</literal> com o elemento especial,
<literal>elements()</literal>,
- e funções de <literal>índice</literal> que podem ser
quantificadas usando
- <literal>some, all, exists, any, in</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- Qualquer funçâo escalar pelo bando de dados como
<literal>sign()</literal>,
- <literal>trunc()</literal>,
<literal>rtrim()</literal>, <literal>sin()</literal>
- </para>
- </listitem>
- <listitem>
- <para>
- Parametros posicionais ao estilo JDBC
<literal>?</literal>
- </para>
- </listitem>
- <listitem>
- <para>
- Parametros nomeados <literal>:name</literal>,
<literal>:start_date</literal>, <literal>:x1</literal>
- </para>
- </listitem>
- <listitem>
- <para>
- Literais SQL <literal>'foo'</literal>,
<literal>69</literal>, <literal>6.66E+2</literal>,
- <literal>'1970-01-01 10:00:01.0'</literal>
- </para>
- </listitem>
- <listitem>
- <para>
- Constantes Java <literal>public static final</literal>
<literal>ex: Color.TABBY</literal>
- </para>
- </listitem>
- </itemizedlist>
-
- <para>
- <literal>in</literal> e <literal>between</literal>
podem ser usadas da seguinte maneira:
- </para>
-
- <programlisting><![CDATA[from DomesticCat cat where cat.name between
'A' and 'B']]></programlisting>
-
- <programlisting><![CDATA[from DomesticCat cat where cat.name in (
'Foo', 'Bar', 'Baz' )]]></programlisting>
-
- <para>
- e as formas negativas podem ser escritas
- </para>
-
- <programlisting><![CDATA[from DomesticCat cat where cat.name not between
'A' and 'B']]></programlisting>
-
- <programlisting><![CDATA[from DomesticCat cat where cat.name not in (
'Foo', 'Bar', 'Baz' )]]></programlisting>
-
- <para>
- Likewise, <literal>is null</literal> and <literal>is not
null</literal> may be used to test
- for null values.
- Assim mesmo, , <literal>is null</literal> e <literal>is not
null</literal> podem ser usados
- para testar valores nulos.
- </para>
-
- <para>
- Booleanos podem ser facilmente usados em expressões, declarando as
substituições da HQL query,
- na configuração do Hibernate
- </para>
-
- <programlisting><![CDATA[<property
name="hibernate.query.substitutions">true 1, false
0</property>]]></programlisting>
-
- <para>
- Isso irá substituir as palavras chave <literal>true</literal> e
<literal>false</literal>
- <literal>pelos</literal> literais
<literal>1</literal> e <literal>0</literal> na tradução do HQL
para SQL.
- </para>
-
- <programlisting><![CDATA[from Cat cat where cat.alive =
true]]></programlisting>
-
- <para>
- Pode-se testar o tamanho de uma coleção <literal>com</literal> a
propriedade especial <literal>size</literal>,
- ou a função especial <literal>size()</literal>.
- </para>
-
- <programlisting><![CDATA[from Cat cat where cat.kittens.size >
0]]></programlisting>
-
- <programlisting><![CDATA[from Cat cat where size(cat.kittens) >
0]]></programlisting>
-
- <para>
- Para coleções indexadas, você pode se referir aos índices máximo e mínimo,
usando
- as funções <literal>minindex</literal> e
<literal>maxindex</literal>. Similarmente,
- pode-se referir aos elementos máximo e mínimo de uma coleção de tipos básicos
usando
- as funções <literal>minelement</literal> e
<literal>maxelement</literal>.
- </para>
-
- <programlisting><![CDATA[from Calendar cal where
maxelement(cal.holidays) > current_date]]></programlisting>
-
- <programlisting><![CDATA[from Order order where maxindex(order.items)
> 100]]></programlisting>
-
- <programlisting><![CDATA[from Order order where minelement(order.items)
> 10000]]></programlisting>
-
- <para>
- As funções SQL <literal>any, some, all, exists, in</literal> são
suportadas quando passado o
- elemento ou o conjunto de índices de uma coleção
(<literal>elements</literal> e
- <literal>indices</literal> de funções), ou o resultado de uma
subquery (veja abaixo).
- </para>
-
- <programlisting><![CDATA[select mother from Cat as mother, Cat as kit
-where kit in elements(foo.kittens)]]></programlisting>
-
- <programlisting><![CDATA[select p from NameList list, Person p
-where p.name = some elements(list.names)]]></programlisting>
-
- <programlisting><![CDATA[from Cat cat where exists
elements(cat.kittens)]]></programlisting>
-
- <programlisting><![CDATA[from Player p where 3 > all
elements(p.scores)]]></programlisting>
-
- <programlisting><![CDATA[from Show show where 'fizard' in
indices(show.acts)]]></programlisting>
-
- <para>
- Note que essas construções - <literal>size</literal>,
<literal>elements</literal>,
- <literal>indices</literal>,
<literal>minindex</literal>, <literal>maxindex</literal>,
- <literal>minelement</literal>,
<literal>maxelement</literal>–
- só podem ser usados na clausula where do Hibernate3.
- </para>
-
- <para>
- Elementos de coleções com índice (arrays, lists, maps), podem ser
referenciadas
- pelo índice (apenas na clausula where):
- </para>
-
- <programlisting><![CDATA[from Order order where order.items[0].id =
1234]]></programlisting>
-
- <programlisting><![CDATA[select person from Person person, Calendar
calendar
-where calendar.holidays['national day'] = person.birthDay
- and person.nationality.calendar = calendar]]></programlisting>
-
- <programlisting><![CDATA[select item from Item item, Order order
-where order.items[ order.deliveredItemIndices[0] ] = item and order.id =
11]]></programlisting>
-
- <programlisting><![CDATA[select item from Item item, Order order
-where order.items[ maxindex(order.items) ] = item and order.id =
11]]></programlisting>
-
- <para>
- A expressão entre colchetes <literal>[]</literal>, pode ser até
uma expressão aritimética.
- </para>
-
- <programlisting><![CDATA[select item from Item item, Order order
-where order.items[ size(order.items) - 1 ] = item]]></programlisting>
-
- <para>
- O HQL também provê a função interna <literal>index()</literal>,
para elementos de
- associação um-pra-muitos ou coleção de valores.
- </para>
-
- <programlisting><![CDATA[select item, index(item) from Order order
- join order.items item
-where index(item) < 5]]></programlisting>
-
- <para>
- Funções escalares SQL, suportadas pelo banco de dados subjacente.
- </para>
-
- <programlisting><![CDATA[from DomesticCat cat where upper(cat.name) like
'FRI%']]></programlisting>
-
- <para>
- Se ainda ainda não está totalmente convencido, pense o quão maior e menos
legível poderia
- ser a query a seguir, em SQL:
- </para>
-
- <programlisting><![CDATA[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)]]></programlisting>
-
- <para>
- <emphasis>Hint:</emphasis> something like
- </para>
-
- <programlisting><![CDATA[SELECT cust.name, cust.address, cust.phone,
cust.id, cust.current_order
-FROM customers cust,
- stores store,
- locations loc,
- store_customers sc,
- product prod
-WHERE prod.name = 'widget'
- AND store.loc_id = loc.id
- AND loc.name IN ( 'Melbourne', 'Sydney' )
- AND sc.store_id = store.id
- AND sc.cust_id = cust.id
- AND prod.id = ALL(
- SELECT item.prod_id
- FROM line_items item, orders o
- WHERE item.order_id = o.id
- AND cust.current_order = o.id
- )]]></programlisting>
-
- </sect1>
-
- <sect1 id="queryhql-ordering">
- <title>A clausula order by</title>
-
- <para>
- A lista retornada pela query pode ser ordenada por qualquer propriedade da
classe ou componente retornado:
- </para>
-
- <programlisting><![CDATA[from DomesticCat cat
-order by cat.name asc, cat.weight desc, cat.birthdate]]></programlisting>
-
- <para>
- As opções <literal>asc</literal> ou
<literal>desc</literal> indicam ordem crescente ou decrescente,
- respectivamente.
- </para>
- </sect1>
-
- <sect1 id="queryhql-grouping">
- <title>A clausula group by</title>
-
- <para>
- Uma query que retorne valores agregados, podem ser agrupados por qualquer
propriedade de uma classe
- ou componente retornado:
- </para>
-
- <programlisting><![CDATA[select cat.color, sum(cat.weight), count(cat)
-from Cat cat
-group by cat.color]]></programlisting>
-
- <programlisting><![CDATA[select foo.id, avg(name), max(name)
-from Foo foo join foo.names name
-group by foo.id]]></programlisting>
-
- <para>
- Uma clausula <literal>having</literal> também é permitida.
- </para>
-
- <programlisting><![CDATA[select cat.color, sum(cat.weight), count(cat)
-from Cat cat
-group by cat.color
-having cat.color in (eg.Color.TABBY, eg.Color.BLACK)]]></programlisting>
-
- <para>
- Funções SQL e funções agregadas são permitidas nas clausulas
- <literal>having</literal> e <literal>order
by</literal>, se suportadas pelo banco
- de dados subjacente (ex: não no MySQL).
- </para>
-
- <programlisting><![CDATA[select cat
-from Cat cat
- join cat.kittens kitten
-group by cat
-having avg(kitten.weight) > 100
-order by count(kitten) asc, sum(kitten.weight) desc]]></programlisting>
-
- <para>
- Note que, nem a clausula <literal>group by</literal> ou
- <literal>order by</literal>, podem conter expressões
aritiméticas.
- </para>
-
- </sect1>
-
- <sect1 id="queryhql-subqueries" revision="2">
- <title>Subqueries</title>
-
- <para>
- Para bancos de dados que suportem subselects, o Hibernate suporta subqueries
dentro de queries.
- Uma subquery precisa estar entre parênteses (normalmente uma chamada de
função agregada SQL).
- Mesmo subqueries co-relacionadas (subqueries que fazem referência à alias de
outras queries),
- são aceitas.
- </para>
-
- <programlisting><![CDATA[from Cat as fatcat
-where fatcat.weight > (
- select avg(cat.weight) from DomesticCat cat
-)]]></programlisting>
-
- <programlisting><![CDATA[from DomesticCat as cat
-where cat.name = some (
- select name.nickName from Name as name
-)]]></programlisting>
-
- <programlisting><![CDATA[from Cat as cat
-where not exists (
- from Cat as mate where mate.mate = cat
-)]]></programlisting>
-
- <programlisting><![CDATA[from DomesticCat as cat
-where cat.name not in (
- select name.nickName from Name as name
-)]]></programlisting>
-
- <programlisting><![CDATA[select cat.id, (select max(kit.weight) from
cat.kitten kit)
-from Cat as cat]]></programlisting>
-
- <para>
- Note que HQL subqueries podem aparecer apenas dentro de clausulas select ou
where.
- </para>
-
- <para>
- Para subqueries <literal>com</literal> mais de uma expressão na
lista do select, pode-se usar um construtor
- de tuplas:
- </para>
-
- <programlisting><![CDATA[from Cat as cat
-where not ( cat.name, cat.color ) in (
- select cat.name, cat.color from DomesticCat cat
-)]]></programlisting>
-
- <para>
- Veja que em alguns bancos de dados (mas não o Oracle ou HSQL), pode-se usar
construtores
- de tuplas em outros contextos. Por exemplo quando buscando componentes ou
tipos de usuário composto.
- </para>
-
- <programlisting><![CDATA[from Person where name = ('Gavin',
'A', 'King')]]></programlisting>
-
- <para>
- Qual é equivalente ao mais verbalizado:
- </para>
-
- <programlisting><![CDATA[from Person where name.first = 'Gavin'
and name.initial = 'A' and name.last =
'King')]]></programlisting>
-
- <para>
- Há duas razões boas que você pode não querer fazer este tipo de coisa:
primeira, não
- é completamente portável entre plataformas de banco de dados; segunda, a
query agora é
- dependente da ordem de propriedades no documento de mapeamento.
- </para>
-
- </sect1>
-
- <sect1 id="queryhql-examples">
- <title>Exemplos de HQL</title>
-
- <para>
- As queries do Hibernate, podem ser muito poderosas e complexas. De fato, o
poder da linguagem de
- querie é um dos pontos principais na distribuição do Hibernate. Aqui temos
algumas queries de exemplo,
- muito similares a queries que usei em um projeto recente. Note que a maioria
das queries que você
- irá escrever, são mais simples que estas.
- </para>
-
- <para>
- A query a seguir retorna o id de order, numero de itens e o valor total do
order para todos os
- orders não pagos para um freguês particular e valor total mínimo dado,
ordenando os resultados por
- valor total. Ao determinar os preços, é usado o catalogo corrente. A query
SQL resultante,
- usando tabelas <literal>ORDER</literal>,
<literal>ORDER_LINE</literal>, <literal>PRODUCT</literal>,
- <literal>CATALOG</literal> e
<literal>PRICE</literal>, tem quatro inner joins e um
- (não correlacionado) subselect.
- </para>
-
- <programlisting><![CDATA[select order.id, sum(price.amount),
count(item)
-from Order as order
- join order.lineItems as item
- join item.product as product,
- Catalog as catalog
- join catalog.prices as price
-where order.paid = false
- and order.customer = :customer
- and price.product = product
- and catalog.effectiveDate < sysdate
- and catalog.effectiveDate >= all (
- select cat.effectiveDate
- from Catalog as cat
- where cat.effectiveDate < sysdate
- )
-group by order
-having sum(price.amount) > :minAmount
-order by sum(price.amount) desc]]></programlisting>
-
- <para>
- Que monstro! Atualmente, na vida real, eu não sou muito afeiçoado a
subqueries, então
- minha query seria mais parecida com isto:
- </para>
-
- <programlisting><![CDATA[select order.id, sum(price.amount),
count(item)
-from Order as order
- join order.lineItems as item
- join item.product as product,
- Catalog as catalog
- join catalog.prices as price
-where order.paid = false
- and order.customer = :customer
- and price.product = product
- and catalog = :currentCatalog
-group by order
-having sum(price.amount) > :minAmount
-order by sum(price.amount) desc]]></programlisting>
-
- <para>
- A próxima query conta o número de pagamentos em cada status, tirando todos os
pagamentos com
- status <literal>AWAITING_APPROVAL</literal>, onde a mais recente
mudança de status foi feita
- pelo usuário corrente. Traduz-se para uma query SQL
<literal>com</literal> dois inner joins e
- um subselect correlacionado, nas tabelas
<literal>PAYMENT</literal>,
- <literal>PAYMENT_STATUS</literal> e
<literal>PAYMENT_STATUS_CHANGE</literal> .
- </para>
-
- <programlisting><![CDATA[select count(payment), status.name
-from Payment as payment
- join payment.currentStatus as status
- join payment.statusChanges as statusChange
-where payment.status.name <> PaymentStatus.AWAITING_APPROVAL
- or (
- 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]]></programlisting>
-
- <para>
- Se eu tivesse mapeado a Collection
<literal>statusChanges</literal> como um List, ao invés de um
- Set, a query teria sido muito mais simples de escrever.
- </para>
-
- <programlisting><![CDATA[select count(payment), status.name
-from Payment as payment
- join payment.currentStatus as status
-where payment.status.name <> PaymentStatus.AWAITING_APPROVAL
- or payment.statusChanges[ maxIndex(payment.statusChanges) ].user <>
:currentUser
-group by status.name, status.sortOrder
-order by status.sortOrder]]></programlisting>
-
- <para>
- A próxima query usa a função <literal>isNull()</literal> do MS
SQL Server, para retornar
- todas as contas e pagamentos não pagos para a organização, para cada usuário
corrente
- pertencente. Traduz-se para uma query SQL <literal>com</literal>
três inner joins,
- um outer join e um subselect nas tabelas
<literal>ACCOUNT</literal>, <literal>PAYMENT</literal>,
-
<literal>PAYMENT_STATUS</literal>,<literal>ACCOUNT_TYPE</literal>,
- <literal>ORGANIZATION</literal> e
<literal>ORG_USER</literal> .
- </para>
-
- <programlisting><![CDATA[select account, payment
-from Account as account
- left outer join account.payments as payment
-where :currentUser in elements(account.holder.users)
- and PaymentStatus.UNPAID = isNull(payment.currentStatus.name, PaymentStatus.UNPAID)
-order by account.type.sortOrder, account.accountNumber,
payment.dueDate]]></programlisting>
-
- <para>
- Para alguns bancos de dados, precisaremos eleminar o subselect
(correlacionado).
- </para>
-
- <programlisting><![CDATA[select account, payment
-from Account as account
- join account.holder.users as user
- left outer join account.payments as payment
-where :currentUser = user
- and PaymentStatus.UNPAID = isNull(payment.currentStatus.name, PaymentStatus.UNPAID)
-order by account.type.sortOrder, account.accountNumber,
payment.dueDate]]></programlisting>
-
- </sect1>
-
- <sect1 id="queryhql-bulk" revision="2">
- <title>update e delete em lote</title>
-
- <para>
- Agora o HQL suporta declarações, <literal>update</literal>,
- <literal>delete</literal> e <literal>insert ... select
...</literal>
- Veja <xref linkend="batch-direct"/>, para mais detalhes.
- </para>
- </sect1>
-
- <sect1 id="queryhql-tipstricks">
- <title>Dicas e Truques</title>
-
- <para>
- Pode-se contar o número de resultados da query, sem realmente retorna-los.
- </para>
-
- <programlisting><![CDATA[( (Integer) session.createQuery("select
count(*) from ....").iterate().next() ).intValue()]]></programlisting>
-
- <para>
- Para ordenar um resultado pelo tamanho de uma Collection, use a query a
seguir.
- </para>
-
- <programlisting><![CDATA[select usr.id, usr.name
-from User as usr
- left join usr.messages as msg
-group by usr.id, usr.name
-order by count(msg)]]></programlisting>
-
- <para>
- Se seu banco de dados suporta subselects, pode-se colocar uma condição sobre
- tamanho de seleção na cláusula where da sua query:
- </para>
-
- <programlisting><![CDATA[from User usr where size(usr.messages) >=
1]]></programlisting>
-
- <para>
- Se seu banco de dados não suporta subselects, use a query a seguir:
- </para>
-
- <programlisting><![CDATA[select usr.id, usr.name
-from User usr.name
- join usr.messages msg
-group by usr.id, usr.name
-having count(msg) >= 1]]></programlisting>
-
- <para>
- Com essa solução não se pode retornar um <literal>User</literal>
<literal>com</literal> sem
- nenhuma menssagem, por causa do "inner join", a forma a seguir
também é útil.
- </para>
-
- <programlisting><![CDATA[select usr.id, usr.name
-from User as usr
- left join usr.messages as msg
-group by usr.id, usr.name
-having count(msg) = 0]]></programlisting>
-
- <para>
- As propriedades de um JavaBean podem ser limitadas à parâmetros nomeados da
query:
- </para>
-
- <programlisting><![CDATA[Query q = s.createQuery("from foo Foo as
foo where foo.name=:name and foo.size=:size");
-q.setProperties(fooBean); // fooBean has getName() and getSize()
-List foos = q.list();]]></programlisting>
-
- <para>
- As Collections são paginaveis, usando a interface
<literal>Query</literal> <literal>com</literal> um filtro:
- </para>
-
- <programlisting><![CDATA[Query q = s.createFilter( collection,
"" ); // the trivial filter
-q.setMaxResults(PAGE_SIZE);
-q.setFirstResult(PAGE_SIZE * pageNumber);
-List page = q.list();]]></programlisting>
-
- <para>
- Os elementos da Collection podem ser ordenados ou agrupados
- usando um filtro de query:
- </para>
-
- <programlisting><![CDATA[Collection orderedCollection = s.filter(
collection, "order by this.amount" );
-Collection counts = s.filter( collection, "select this.type, count(this) group by
this.type" );]]></programlisting>
-
- <para>
- Pode-se achar o tamanho de uma Collection sem inicializa-la:
- </para>
-
- <programlisting><![CDATA[( (Integer) session.createQuery("select
count(*) from ....").iterate().next() ).intValue();]]></programlisting>
-
- </sect1>
-
-</chapter>
-
+<chapter id="queryhql">
+ <title>HQL: A linguagem de Queries do Hibernate</title>
+
+ <para>
+ O Hibernate vem com uma poderosa linguagem que é (intencionalmente) muito
parecida
+ com o SQL. Mas não seja enganado pela sintaxe; a HQL é totalmente orientada à
objetos,
+ requer conhecimentos de herança, polimorfismo e associações.
+ </para>
+
+ <sect1 id="queryhql-casesensitivity">
+ <title>Case Sensitíve</title>
+
+ <para>
+ As Queries não são case-sensitive, exceto pelo nomes das classes e
propriedades Java.
+ <literal>sELEct</literal> e o mesmo que
+ <literal>SELECT</literal> mas
+ <literal>org.hibernate.eg.FOO</literal> não é
+ <literal>org.hibernate.eg.Foo</literal> e
+ <literal>foo.barSet</literal> não é
+ <literal>foo.BARSET</literal>.
+
+ </para>
+
+ <para>
+ Esse manual usa as palavras chave HQL em letras minúsculas. Alguns usuários
acham que
+ com letras maiúsculas as queries ficam mais legíveis, mas nós achamos essa
convenção feia
+ dentro do código Java.
+ </para>
+
+ </sect1>
+
+ <sect1 id="queryhql-from">
+ <title>A clausula from</title>
+
+ <para>
+ A mais simples query possível do Hibernate é a assim:
+ </para>
+
+ <programlisting><![CDATA[from eg.Cat]]></programlisting>
+
+ <para>
+ Ela irá retornar todas as instancias da classe
<literal>eg.Cat</literal>.
+ Necessariamente não precisamos qualificar o nome da classe, pois é realizado
+ <literal>auto-import</literal> por padrão. Por isso na maior
parte do tempos
+ nós simplesmente escrevemos:
+ </para>
+
+ <programlisting><![CDATA[from Cat]]></programlisting>
+
+ <para>
+ Na maior parte do tempo, você precisará atribuir um
<emphasis>alias</emphasis>,
+ desde que você queira se referia ao <literal>Cat</literal> em
outras partes da
+ query.
+ </para>
+
+ <programlisting><![CDATA[from Cat as cat]]></programlisting>
+
+ <para>
+ Essa query atribui um alias a <literal>cat</literal> para as
instancias de
+ <literal>Cat</literal>, então nós podemos usar esse alias depois
na query.
+ A palavra chave as é opcional; poderíamos escrever assim:
+ </para>
+
+ <programlisting><![CDATA[from Cat cat]]></programlisting>
+
+ <para>
+ Múltiplas classes pode ser envolvidas, resultando em um produto cartesiano ou
"cross" join.
+ </para>
+
+ <programlisting><![CDATA[from Formula,
Parameter]]></programlisting>
+ <programlisting><![CDATA[from Formula as form, Parameter as
param]]></programlisting>
+
+ <para>
+ É considerada uma boa prática os nomes dos aliases começarem com letra
minúscula,
+ aderente com os padrões Java para variáveis locais (ex:
<literal>domesticCat</literal>).
+ </para>
+
+ </sect1>
+
+ <sect1 id="queryhql-joins" revision="2">
+ <title>Associações e joins</title>
+
+ <para>
+ Nós também podemos querer atribuir aliases em uma entidade associada, ou
mesmo
+ em elementos de uma coleção de valores, usando um
<literal>join</literal>.
+ </para>
+
+ <programlisting><![CDATA[from Cat as cat
+ inner join cat.mate as mate
+ left outer join cat.kittens as kitten]]></programlisting>
+
+ <programlisting><![CDATA[from Cat as cat left join cat.mate.kittens as
kittens]]></programlisting>
+
+ <programlisting><![CDATA[from Formula form full join form.parameter
param]]></programlisting>
+
+ <para>
+ Os tipos de joins suportados foram inspirados no SQL ANSI:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ <literal>inner join</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>left outer join</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>right outer join</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>full join</literal> (geralmente não é útil)
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ The <literal>inner join</literal>, <literal>left outer
join</literal> and
+ <literal>right outer join</literal> constructs may be
abbreviated.
+ As construções <literal>inner join</literal>, <literal>left
outer join</literal> e
+ <literal>right outer join</literal> podem ser abreviadas.
+ </para>
+
+ <programlisting><![CDATA[from Cat as cat
+ join cat.mate as mate
+ left join cat.kittens as kitten]]></programlisting>
+
+ <para>
+ Você pode fornecer condições extras de join usando a palavra
+ chave do HQL <literal>with</literal>.
+ </para>
+
+ <programlisting><![CDATA[from Cat as cat
+ left join cat.kittens as kitten
+ <literal>with</literal> kitten.bodyWeight >
10.0]]></programlisting>
+
+ <para>
+ Adicionalmente, um "fetch" join permite que associações ou coleções
de valores
+ sejam inicializadas junto com o objeto pai, usando apenas um select. Isso é
+ muito útil no caso das coleções. Isso efetivamente sobre escreve as
declarações
+ outer join e lazy do arquivo mapeamento para associações e coleções.
+ Veja a seção <xref linkend="performance-fetching"/> para
mais informações.
+ </para>
+
+ <programlisting><![CDATA[from Cat as cat
+ inner join <literal>fetch</literal>cat.mate
+ left join
<literal>fetch</literal>cat.kittens]]></programlisting>
+
+ <para>
+ Usualmente, um <literal>fetch</literal>join não precisa atribuir
um alias, pois o objeto associado não
+ deve ser usado na clausula <literal>where</literal> (ou em
qualquer outra clausula).
+ Também, os objetos associados não são retornados diretamente nos resultados
da query.
+ Ao invés disso, eles devem ser acessados usando o objeto pai. A única razão
que nós
+ podemos necessitar de um alias é quando fazemos um fech join recursivamente
em uma
+ coleção adicional:
+ </para>
+
+ <programlisting><![CDATA[from Cat as cat
+ inner join <literal>fetch</literal>cat.mate
+ left join <literal>fetch</literal>cat.kittens child
+ left join
<literal>fetch</literal>child.kittens]]></programlisting>
+
+ <para>
+ Observe que a construção <literal>fetch</literal> não deve ser
usada em queries invocadas usando
+ <literal>iterate()</literal> (embora possa ser usado com
<literal>scroll()</literal>). O
+ <literal>fetch</literal> também não deve ser usado junto com o
<literal>setMaxResults()</literal> ou
+ <literal>setFirstResult()</literal> pois essas operações são
baseadas nas linhas retornadas, que
+ normalmente contem duplicidade devido ao fetching das coleções, então o
número de linhas pode não
+ ser o que você espera.
+
+ O <literal>fetch</literal> não deve ser usado junto com uma
condição <literal>with</literal> em
+ uma condição <literal>with</literal> ad hoc. É possível que seja
criado um produto cartesiano pelo
+ join fetching em mais do que uma coleção em uma query, então tome cuidado
nesses casos. Um join
+ fetching em varias coleções pode trazer resultados inesperados para
mapeamentos do tipo bag, tome
+ cuidado na hora de formular queries como essas. Finalmente, observe o
seguinte, o
+ <literal>full join fetch</literal> e <literal>right join
fetch</literal> não são significativos.
+ </para>
+
+ <para>
+
+ Se está usando o nível de propriedade lazy
(<literal>com</literal> instrumentação de bytecode), é possível
+ forçar o Hibernate a <literal>buscar</literal> as propriedades
lazy imediatamente (na primeira query),
+ usando <literal>fetch all properties </literal>.
+ </para>
+
+ <programlisting><![CDATA[from Document
<literal>fetch</literal>all properties order by
name]]></programlisting>
+ <programlisting><![CDATA[from Document doc
<literal>fetch</literal>all properties where lower(doc.name) like
'%cats%']]></programlisting>
+
+ </sect1>
+
+ <sect1 id="queryhql-joins-forms">
+ <title>Formas e sintaxe de joins</title>
+
+ <para>
+ O HQL suporta duas formas de associação para união:
<literal>implícita</literal> e <literal>explicita</literal>.
+ </para>
+
+ <para>
+ As queries apresentadas na seção anterior usam a forma
<literal>explicita</literal>, onde a
+ palavra chave "join" é explicitamente usada na clausula "from".
Essa é a forma recomendada.
+ </para>
+
+ <para>
+ A forma <literal>implícita</literal> não usa a palavra chave
"join". Entretanto, as associações
+ são diferenciadas usando pontuação ("." - dotnation). Uniões implícitas
podem aparecer em
+ qualquer das clausulas HQL. A união <literal>implícita</literal>
resulta em declarações
+ SQL que contem inner joins.
+ </para>
+
+ <programlisting><![CDATA[from Cat as cat where cat.mate.name like
'%s%']]></programlisting>
+ </sect1>
+
+ <sect1 id="queryhql-identifier-property">
+ <title>Refering to identifier property</title>
+
+ <para>
+ There are, generally speaking, 2 ways to refer to an entity's identifier
property:
+ </para>
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ The special property (lowercase) <literal>id</literal> may be used to
reference the identifier
+ property of an entity <emphasis>provided that entity does not define a
non-identifier property
+ named id</emphasis>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If the entity defines a named identifier property, you may use that property name.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ References to composite identifier properties follow the same naming rules. If the
+ entity has a non-identifier property named id, the composite identifier property can
only
+ be referenced by its defined named; otherwise, the special
<literal>id</literal> property
+ can be used to rerference the identifier property.
+ </para>
+
+ <para>
+ Note: this has changed significantly starting in version 3.2.2. In previous
versions,
+ <literal>id</literal> <emphasis>always</emphasis> referred to
the identifier property no
+ matter what its actual name. A ramification of that decision was that non-identifier
+ properties named <literal>id</literal> could never be referenced in
Hibernate queries.
+ </para>
+ </sect1>
+
+ <sect1 id="queryhql-select">
+ <title>Clausula select</title>
+
+ <para>
+ A clausula <literal>select</literal> seleciona quais obetos e
propriedades retornam
+ no resultado da query. Considere:
+ </para>
+
+ <programlisting><![CDATA[select mate
+from Cat as cat
+ inner join cat.mate as mate]]></programlisting>
+
+ <para>
+ A query selecionará <literal>mate</literal>s (companheiros), de
outros <literal>Cat</literal>s.
+ Atualmente, podemos expressar a query de forma mais compacta como:
+ </para>
+
+ <programlisting><![CDATA[select cat.mate from Cat
cat]]></programlisting>
+
+ <para>
+ Queries podem retornar propriedades de qualquer tipo de valor, incluindo
propriedades de tipo de componente:
+
+ </para>
+
+ <programlisting><![CDATA[select cat.name from DomesticCat cat
+where cat.name like 'fri%']]></programlisting>
+
+ <programlisting><![CDATA[select cust.name.firstName from Customer as
cust]]></programlisting>
+
+ <para>
+ Queries podem retornar múltiplos objetos e/ou propriedades como um array do
+ tipo Object[],
+ </para>
+
+ <programlisting><![CDATA[select mother, offspr, mate.name
+from DomesticCat as mother
+ inner join mother.mate as mate
+ left outer join mother.kittens as offspr]]></programlisting>
+
+ <para>
+ ou como um <literal>List</literal>,
+ </para>
+
+ <programlisting><![CDATA[select new list(mother, offspr, mate.name)
+from DomesticCat as mother
+ inner join mother.mate as mate
+ left outer join mother.kittens as offspr]]></programlisting>
+
+ <para>
+ ou como um objeto Java typesafe,
+ </para>
+
+ <programlisting><![CDATA[select new Family(mother, mate, offspr)
+from DomesticCat as mother
+ join mother.mate as mate
+ left join mother.kittens as offspr]]></programlisting>
+
+ <para>
+ assumindo que a classe <literal>Family</literal> tenha um
construtor apropriado.
+ </para>
+
+ <para>
+ Pode-se designar referencias a expressões selecionadas,
<literal>as</literal>:
+ </para>
+
+ <programlisting><![CDATA[select max(bodyWeight) as max, min(bodyWeight)
as min, count(*) as n
+from Cat cat]]></programlisting>
+
+ <para>
+ Isto é bem mais útil quando usado junto <literal>com</literal>
<literal>select new map</literal>:
+ </para>
+
+ <programlisting><![CDATA[select new map( max(bodyWeight) as max,
min(bodyWeight) as min, count(*) as n )
+from Cat cat]]></programlisting>
+
+ <para>
+ Esta query retorna um <literal>Map</literal> de referencias para
valores selecionados.
+ </para>
+
+ </sect1>
+
+ <sect1 id="queryhql-aggregation">
+ <title>Funções de agregação</title>
+
+ <para>
+ As queries HQL podem retornar o resultado de funções agregadas nas
propriedades.
+ </para>
+
+ <programlisting><![CDATA[select avg(cat.weight), sum(cat.weight),
max(cat.weight), count(cat)
+from Cat cat]]></programlisting>
+
+<!-- NO LONGER SUPPORTED
+ <para>
+ Collections may also appear inside aggregate functions in the
<literal>select</literal>
+ clause.
+ </para>
+
+ <programlisting><![CDATA[select cat, count( elements(cat.kittens) )
+from Cat cat group by cat]]></programlisting>
+-->
+
+ <para>
+ As funções agregadas suportadas são:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ <literal>avg(...), sum(...), min(...),
max(...)</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>count(*)</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>count(...), count(distinct ...),
count(all...)</literal>
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Pode-se usar operadores aritiméticos, concatenação e funções SQL
+ reconhecidas na clausula select:
+ </para>
+
+ <programlisting><![CDATA[select cat.weight + sum(kitten.weight)
+from Cat cat
+ join cat.kittens kitten
+group by cat.id, cat.weight]]></programlisting>
+
+ <programlisting><![CDATA[select firstName||' '||initial||'
'||upper(lastName) from Person]]></programlisting>
+
+ <para>
+ As palavras <literal>distinct</literal> e
<literal>all</literal> podem ser usadas e têm
+ a mesma semântica como no SQL.
+ </para>
+
+ <programlisting><![CDATA[select distinct cat.name from Cat cat
+
+select count(distinct cat.name), count(cat) from Cat cat]]></programlisting>
+
+ </sect1>
+
+ <sect1 id="queryhql-polymorphism">
+ <title>Queries polimórficas</title>
+
+ <para>
+ A query:
+ </para>
+
+ <programlisting><![CDATA[from Cat as cat]]></programlisting>
+
+ <para>
+ retorna instancias não só de <literal>Cat</literal>, mas também
de subclasses como
+ <literal>DomesticCat</literal>. As queries do Hibernate podem
nomear qualquer classe Java
+ ou interface na clausula <literal>from</literal>. A query
retornará instancias de toda classe
+ persistente que extenda a determinada classe ou implemente a determinada
interface. A query
+ , a seguir, pode retornar todo objeto persistente:
+ </para>
+
+ <programlisting><![CDATA[from java.lang.Object
o]]></programlisting>
+
+ <para>
+ A interface <literal>Named</literal> pode ser implementada por
várias classes persistentes:
+ </para>
+
+ <programlisting><![CDATA[from Named n, Named m where n.name =
m.name]]></programlisting>
+
+ <para>
+ Note que as duas últimas queries requerem mais de um SQL SELECT . Isto
significa que a clausula
+ <literal>order by</literal> não ordena corretamente todo o
resultado. (Isso também significa que
+ você não pode chamar essas queries usando
<literal>Query.scroll()</literal>.)
+ </para>
+
+ </sect1>
+
+ <sect1 id="queryhql-where">
+ <title>A clausula where</title>
+
+ <para>
+ A clausula <literal>where</literal> permite estreitar a lista de
instancias retornada.
+ Se não houver referencia alguma, pode-se referir a propriedades pelo nome:
+ </para>
+
+ <programlisting><![CDATA[from Cat where
name='Fritz']]></programlisting>
+
+ <para>
+ Se houver uma referência, use o nome da propriedade qualificada:
+ </para>
+
+ <programlisting><![CDATA[from Cat as cat where
cat.name='Fritz']]></programlisting>
+
+ <para>
+ retorna instancias de <literal>Cat</literal> com nome ‘Fritz’.
+ </para>
+
+ <programlisting><![CDATA[select foo
+from Foo foo, Bar bar
+where foo.startDate = bar.date]]></programlisting>
+
+ <para>
+ retornará todas as instancias de <literal>Foo</literal>, para
cada
+ um que tiver uma instancia de <literal>bar</literal> com a
propriedade
+ <literal>date</literal> igual a propriedade
+ <literal>startDate</literal> de
+ <literal>Foo</literal>. Expressões de filtro compostas fazem da
+ clausula <literal>where</literal>, extremamente poderosa.
Consideremos:
+ </para>
+
+ <programlisting><![CDATA[from Cat cat where cat.mate.name is not
null]]></programlisting>
+
+ <para>
+ Esta query traduzida para uma query SQL <literal>com</literal>
uma tabela (inner) join. Se fosse
+ escrever algo como:
+ </para>
+
+ <programlisting><![CDATA[from Foo foo
+where foo.bar.baz.customer.address.city is not null]]></programlisting>
+
+ <para>
+ Poderia-se terminar <literal>com</literal> uma query que
necessitasse de join de quatro tabelas,
+ no SQL.
+ </para>
+
+ <para>
+ O operador <literal>=</literal> pode ser uasdo para comparar não
apenas propriedades,
+ mas também instancias:
+ </para>
+
+ <programlisting><![CDATA[from Cat cat, Cat rival where cat.mate =
rival.mate]]></programlisting>
+
+ <programlisting><![CDATA[select cat, mate
+from Cat cat, Cat mate
+where cat.mate = mate]]></programlisting>
+
+ <para>
+ A propriedade especial (lowercase) <literal>id</literal> pode
ser usada para referenciar
+ o identificador único de um objeto. (Pode-se usar também o nome de sua
propriedade)
+ </para>
+
+ <programlisting><![CDATA[from Cat as cat where cat.id = 123
+
+from Cat as cat where cat.mate.id = 69]]></programlisting>
+
+ <para>
+ A Segunda query é eficiente. Nenhuma união de tabelas é necessária!
+ </para>
+
+ <para>
+ As propriedades de identificadores compostas também podem ser usadas. Suponha
que
+ <literal>Person</literal> tenha um identificador composto que
consiste de
+ <literal>country</literal> e
<literal>medicareNumber</literal>.
+ </para>
+
+ <programlisting><![CDATA[from bank.Person person
+where person.id.country = 'AU'
+ and person.id.medicareNumber = 123456]]></programlisting>
+
+ <programlisting><![CDATA[from bank.Account account
+where account.owner.id.country = 'AU'
+ and account.owner.id.medicareNumber = 123456]]></programlisting>
+
+ <para>
+ Mais uma vez, a Segunda query não precisa de nenhum join de tabela.
+ </para>
+
+ <para>
+ Assim mesmo, a propriedade especial <literal>class</literal>
acessa o valor discriminador da
+ instancia, no caso de persistência polimórfica. O nome de uma classe Java
inclusa em uma
+ clausula "where", será traduzida para seu valor descriminante.
+ </para>
+
+ <programlisting><![CDATA[from Cat cat where cat.class =
DomesticCat]]></programlisting>
+
+ <para>
+ Pode-se também especificar as propriedades dos components ou tipos de usuário
composto
+ (e de componentes de componentes). Nunca tente usar uma expressão de filtro
que termine na propriedade
+ de um tipo de componente (ao contrário de uma propriedade de um componente).
Por exemplo,
+ se store.owner é uma entidade <literal>com</literal> um
componente <literal>address</literal>.
+ </para>
+
+ <programlisting><![CDATA[store.owner.address.city // okay
+store.owner.address // error!]]></programlisting>
+
+ <para>
+ Um tipo "any" tem as propriedades <literal>id</literal>
e <literal>class</literal> especiais,
+ nôs permitindo expressar um join da seguinte forma (onde
<literal>AuditLog.item</literal> é
+ uma propriedade mapeada <literal>com</literal>
<literal><any></literal>)
+ </para>
+
+ <programlisting><![CDATA[from AuditLog log, Payment payment
+where log.item.class = 'Payment' and log.item.id =
payment.id]]></programlisting>
+
+ <para>
+ Veja que <literal>log.item.class</literal> e
<literal>payment.class</literal> podem
+ referir-se a valores de colunas de banco de dados completamente diferentes,
na query acima.
+ </para>
+
+ </sect1>
+
+ <sect1 id="queryhql-expressions">
+ <title>Expressões</title>
+
+ <para>
+ As expressões permitidas na cláusula <literal>where</literal>
inclui a maioria
+ das coisas que você poderia escrever no SQL:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ operadores matemáticos <literal>+, -, *, /</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ operadores de comparação binários <literal>=, >=,
<=, <>, !=, like</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ operadores lógicos <literal>and, or, not</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ parenteses <literal>( )</literal>, indicating grouping
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>in</literal>,
+ <literal>not in</literal>,
+ <literal>between</literal>,
+ <literal>is null</literal>,
+ <literal>is not null</literal>,
+ <literal>is empty</literal>,
+ <literal>is not empty</literal>,
+ <literal>member of</literal> and
+ <literal>not member of</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ case "simples" , <literal>case ... when ... then ...
else ... end</literal>, and
+ "searched" case, <literal>case when ... then ... else
... end</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ concatenação de string <literal>...||...</literal> ou
<literal>concat(...,...)</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>current_date()</literal>,
<literal>current_time()</literal>,
+ <literal>current_timestamp()</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>second(...)</literal>,
<literal>minute(...)</literal>,
+ <literal>hour(...)</literal>, <literal>day(...)</literal>,
+ <literal>month(...)</literal>,
<literal>year(...)</literal>,
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ qualquer funcao ou operador definida pela EJB-QL 3.0:
<literal>substring(), trim(),
+ lower(), upper(), length(), locate(), abs(), sqrt(), bit_length(),
mod()</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>coalesce()</literal> and
<literal>nullif()</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>str()</literal> para converter valores numericos
ou temporais para string
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>cast(... as ...)</literal>, onde o segundo
argumento é o nome do tipo
+ hibernate, e<literal>extract(... from ...)</literal> se
ANSI
+ <literal>cast()</literal> e
<literal>extract()</literal> é suportado pele
+ banco de dados usado
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ A função HQL <literal>index()</literal> , que se aplicam
a referencias de
+ coleçôes associadas e indexadas
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ As funções hql que retornam expressões de coleções de valores:
+ <literal>size(), minelement(), maxelement(), minindex(),
maxindex()</literal>,
+ <literal>junto</literal> com o elemento especial,
<literal>elements()</literal>,
+ e funções de <literal>índice</literal> que podem ser
quantificadas usando
+ <literal>some, all, exists, any, in</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Qualquer funçâo escalar pelo bando de dados como
<literal>sign()</literal>,
+ <literal>trunc()</literal>,
<literal>rtrim()</literal>, <literal>sin()</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Parametros posicionais ao estilo JDBC
<literal>?</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Parametros nomeados <literal>:name</literal>,
<literal>:start_date</literal>, <literal>:x1</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Literais SQL <literal>'foo'</literal>,
<literal>69</literal>, <literal>6.66E+2</literal>,
+ <literal>'1970-01-01 10:00:01.0'</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Constantes Java <literal>public static final</literal>
<literal>ex: Color.TABBY</literal>
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ <literal>in</literal> e <literal>between</literal>
podem ser usadas da seguinte maneira:
+ </para>
+
+ <programlisting><![CDATA[from DomesticCat cat where cat.name between
'A' and 'B']]></programlisting>
+
+ <programlisting><![CDATA[from DomesticCat cat where cat.name in (
'Foo', 'Bar', 'Baz' )]]></programlisting>
+
+ <para>
+ e as formas negativas podem ser escritas
+ </para>
+
+ <programlisting><![CDATA[from DomesticCat cat where cat.name not between
'A' and 'B']]></programlisting>
+
+ <programlisting><![CDATA[from DomesticCat cat where cat.name not in (
'Foo', 'Bar', 'Baz' )]]></programlisting>
+
+ <para>
+ Likewise, <literal>is null</literal> and <literal>is not
null</literal> may be used to test
+ for null values.
+ Assim mesmo, , <literal>is null</literal> e <literal>is not
null</literal> podem ser usados
+ para testar valores nulos.
+ </para>
+
+ <para>
+ Booleanos podem ser facilmente usados em expressões, declarando as
substituições da HQL query,
+ na configuração do Hibernate
+ </para>
+
+ <programlisting><![CDATA[<property
name="hibernate.query.substitutions">true 1, false
0</property>]]></programlisting>
+
+ <para>
+ Isso irá substituir as palavras chave <literal>true</literal> e
<literal>false</literal>
+ <literal>pelos</literal> literais
<literal>1</literal> e <literal>0</literal> na tradução do HQL
para SQL.
+ </para>
+
+ <programlisting><![CDATA[from Cat cat where cat.alive =
true]]></programlisting>
+
+ <para>
+ Pode-se testar o tamanho de uma coleção <literal>com</literal> a
propriedade especial <literal>size</literal>,
+ ou a função especial <literal>size()</literal>.
+ </para>
+
+ <programlisting><![CDATA[from Cat cat where cat.kittens.size >
0]]></programlisting>
+
+ <programlisting><![CDATA[from Cat cat where size(cat.kittens) >
0]]></programlisting>
+
+ <para>
+ Para coleções indexadas, você pode se referir aos índices máximo e mínimo,
usando
+ as funções <literal>minindex</literal> e
<literal>maxindex</literal>. Similarmente,
+ pode-se referir aos elementos máximo e mínimo de uma coleção de tipos básicos
usando
+ as funções <literal>minelement</literal> e
<literal>maxelement</literal>.
+ </para>
+
+ <programlisting><![CDATA[from Calendar cal where
maxelement(cal.holidays) > current_date]]></programlisting>
+
+ <programlisting><![CDATA[from Order order where maxindex(order.items)
> 100]]></programlisting>
+
+ <programlisting><![CDATA[from Order order where minelement(order.items)
> 10000]]></programlisting>
+
+ <para>
+ As funções SQL <literal>any, some, all, exists, in</literal> são
suportadas quando passado o
+ elemento ou o conjunto de índices de uma coleção
(<literal>elements</literal> e
+ <literal>indices</literal> de funções), ou o resultado de uma
subquery (veja abaixo).
+ </para>
+
+ <programlisting><![CDATA[select mother from Cat as mother, Cat as kit
+where kit in elements(foo.kittens)]]></programlisting>
+
+ <programlisting><![CDATA[select p from NameList list, Person p
+where p.name = some elements(list.names)]]></programlisting>
+
+ <programlisting><![CDATA[from Cat cat where exists
elements(cat.kittens)]]></programlisting>
+
+ <programlisting><![CDATA[from Player p where 3 > all
elements(p.scores)]]></programlisting>
+
+ <programlisting><![CDATA[from Show show where 'fizard' in
indices(show.acts)]]></programlisting>
+
+ <para>
+ Note que essas construções - <literal>size</literal>,
<literal>elements</literal>,
+ <literal>indices</literal>,
<literal>minindex</literal>, <literal>maxindex</literal>,
+ <literal>minelement</literal>,
<literal>maxelement</literal>–
+ só podem ser usados na clausula where do Hibernate3.
+ </para>
+
+ <para>
+ Elementos de coleções com índice (arrays, lists, maps), podem ser
referenciadas
+ pelo índice (apenas na clausula where):
+ </para>
+
+ <programlisting><![CDATA[from Order order where order.items[0].id =
1234]]></programlisting>
+
+ <programlisting><![CDATA[select person from Person person, Calendar
calendar
+where calendar.holidays['national day'] = person.birthDay
+ and person.nationality.calendar = calendar]]></programlisting>
+
+ <programlisting><![CDATA[select item from Item item, Order order
+where order.items[ order.deliveredItemIndices[0] ] = item and order.id =
11]]></programlisting>
+
+ <programlisting><![CDATA[select item from Item item, Order order
+where order.items[ maxindex(order.items) ] = item and order.id =
11]]></programlisting>
+
+ <para>
+ A expressão entre colchetes <literal>[]</literal>, pode ser até
uma expressão aritimética.
+ </para>
+
+ <programlisting><![CDATA[select item from Item item, Order order
+where order.items[ size(order.items) - 1 ] = item]]></programlisting>
+
+ <para>
+ O HQL também provê a função interna <literal>index()</literal>,
para elementos de
+ associação um-pra-muitos ou coleção de valores.
+ </para>
+
+ <programlisting><![CDATA[select item, index(item) from Order order
+ join order.items item
+where index(item) < 5]]></programlisting>
+
+ <para>
+ Funções escalares SQL, suportadas pelo banco de dados subjacente.
+ </para>
+
+ <programlisting><![CDATA[from DomesticCat cat where upper(cat.name) like
'FRI%']]></programlisting>
+
+ <para>
+ Se ainda ainda não está totalmente convencido, pense o quão maior e menos
legível poderia
+ ser a query a seguir, em SQL:
+ </para>
+
+ <programlisting><![CDATA[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)]]></programlisting>
+
+ <para>
+ <emphasis>Hint:</emphasis> something like
+ </para>
+
+ <programlisting><![CDATA[SELECT cust.name, cust.address, cust.phone,
cust.id, cust.current_order
+FROM customers cust,
+ stores store,
+ locations loc,
+ store_customers sc,
+ product prod
+WHERE prod.name = 'widget'
+ AND store.loc_id = loc.id
+ AND loc.name IN ( 'Melbourne', 'Sydney' )
+ AND sc.store_id = store.id
+ AND sc.cust_id = cust.id
+ AND prod.id = ALL(
+ SELECT item.prod_id
+ FROM line_items item, orders o
+ WHERE item.order_id = o.id
+ AND cust.current_order = o.id
+ )]]></programlisting>
+
+ </sect1>
+
+ <sect1 id="queryhql-ordering">
+ <title>A clausula order by</title>
+
+ <para>
+ A lista retornada pela query pode ser ordenada por qualquer propriedade da
classe ou componente retornado:
+ </para>
+
+ <programlisting><![CDATA[from DomesticCat cat
+order by cat.name asc, cat.weight desc, cat.birthdate]]></programlisting>
+
+ <para>
+ As opções <literal>asc</literal> ou
<literal>desc</literal> indicam ordem crescente ou decrescente,
+ respectivamente.
+ </para>
+ </sect1>
+
+ <sect1 id="queryhql-grouping">
+ <title>A clausula group by</title>
+
+ <para>
+ Uma query que retorne valores agregados, podem ser agrupados por qualquer
propriedade de uma classe
+ ou componente retornado:
+ </para>
+
+ <programlisting><![CDATA[select cat.color, sum(cat.weight), count(cat)
+from Cat cat
+group by cat.color]]></programlisting>
+
+ <programlisting><![CDATA[select foo.id, avg(name), max(name)
+from Foo foo join foo.names name
+group by foo.id]]></programlisting>
+
+ <para>
+ Uma clausula <literal>having</literal> também é permitida.
+ </para>
+
+ <programlisting><![CDATA[select cat.color, sum(cat.weight), count(cat)
+from Cat cat
+group by cat.color
+having cat.color in (eg.Color.TABBY, eg.Color.BLACK)]]></programlisting>
+
+ <para>
+ Funções SQL e funções agregadas são permitidas nas clausulas
+ <literal>having</literal> e <literal>order
by</literal>, se suportadas pelo banco
+ de dados subjacente (ex: não no MySQL).
+ </para>
+
+ <programlisting><![CDATA[select cat
+from Cat cat
+ join cat.kittens kitten
+group by cat
+having avg(kitten.weight) > 100
+order by count(kitten) asc, sum(kitten.weight) desc]]></programlisting>
+
+ <para>
+ Note que, nem a clausula <literal>group by</literal> ou
+ <literal>order by</literal>, podem conter expressões
aritiméticas.
+ </para>
+
+ </sect1>
+
+ <sect1 id="queryhql-subqueries" revision="2">
+ <title>Subqueries</title>
+
+ <para>
+ Para bancos de dados que suportem subselects, o Hibernate suporta subqueries
dentro de queries.
+ Uma subquery precisa estar entre parênteses (normalmente uma chamada de
função agregada SQL).
+ Mesmo subqueries co-relacionadas (subqueries que fazem referência à alias de
outras queries),
+ são aceitas.
+ </para>
+
+ <programlisting><![CDATA[from Cat as fatcat
+where fatcat.weight > (
+ select avg(cat.weight) from DomesticCat cat
+)]]></programlisting>
+
+ <programlisting><![CDATA[from DomesticCat as cat
+where cat.name = some (
+ select name.nickName from Name as name
+)]]></programlisting>
+
+ <programlisting><![CDATA[from Cat as cat
+where not exists (
+ from Cat as mate where mate.mate = cat
+)]]></programlisting>
+
+ <programlisting><![CDATA[from DomesticCat as cat
+where cat.name not in (
+ select name.nickName from Name as name
+)]]></programlisting>
+
+ <programlisting><![CDATA[select cat.id, (select max(kit.weight) from
cat.kitten kit)
+from Cat as cat]]></programlisting>
+
+ <para>
+ Note que HQL subqueries podem aparecer apenas dentro de clausulas select ou
where.
+ </para>
+
+ <para>
+ Note that subqueries can also utilize <literal>row value
constructor</literal> syntax. See
+ <xref linkend="queryhql-tuple"/> for more details.
+ </para>
+ </sect1>
+
+ <sect1 id="queryhql-examples">
+ <title>Exemplos de HQL</title>
+
+ <para>
+ As queries do Hibernate, podem ser muito poderosas e complexas. De fato, o
poder da linguagem de
+ querie é um dos pontos principais na distribuição do Hibernate. Aqui temos
algumas queries de exemplo,
+ muito similares a queries que usei em um projeto recente. Note que a maioria
das queries que você
+ irá escrever, são mais simples que estas.
+ </para>
+
+ <para>
+ A query a seguir retorna o id de order, numero de itens e o valor total do
order para todos os
+ orders não pagos para um freguês particular e valor total mínimo dado,
ordenando os resultados por
+ valor total. Ao determinar os preços, é usado o catalogo corrente. A query
SQL resultante,
+ usando tabelas <literal>ORDER</literal>,
<literal>ORDER_LINE</literal>, <literal>PRODUCT</literal>,
+ <literal>CATALOG</literal> e
<literal>PRICE</literal>, tem quatro inner joins e um
+ (não correlacionado) subselect.
+ </para>
+
+ <programlisting><![CDATA[select order.id, sum(price.amount),
count(item)
+from Order as order
+ join order.lineItems as item
+ join item.product as product,
+ Catalog as catalog
+ join catalog.prices as price
+where order.paid = false
+ and order.customer = :customer
+ and price.product = product
+ and catalog.effectiveDate < sysdate
+ and catalog.effectiveDate >= all (
+ select cat.effectiveDate
+ from Catalog as cat
+ where cat.effectiveDate < sysdate
+ )
+group by order
+having sum(price.amount) > :minAmount
+order by sum(price.amount) desc]]></programlisting>
+
+ <para>
+ Que monstro! Atualmente, na vida real, eu não sou muito afeiçoado a
subqueries, então
+ minha query seria mais parecida com isto:
+ </para>
+
+ <programlisting><![CDATA[select order.id, sum(price.amount),
count(item)
+from Order as order
+ join order.lineItems as item
+ join item.product as product,
+ Catalog as catalog
+ join catalog.prices as price
+where order.paid = false
+ and order.customer = :customer
+ and price.product = product
+ and catalog = :currentCatalog
+group by order
+having sum(price.amount) > :minAmount
+order by sum(price.amount) desc]]></programlisting>
+
+ <para>
+ A próxima query conta o número de pagamentos em cada status, tirando todos os
pagamentos com
+ status <literal>AWAITING_APPROVAL</literal>, onde a mais recente
mudança de status foi feita
+ pelo usuário corrente. Traduz-se para uma query SQL
<literal>com</literal> dois inner joins e
+ um subselect correlacionado, nas tabelas
<literal>PAYMENT</literal>,
+ <literal>PAYMENT_STATUS</literal> e
<literal>PAYMENT_STATUS_CHANGE</literal> .
+ </para>
+
+ <programlisting><![CDATA[select count(payment), status.name
+from Payment as payment
+ join payment.currentStatus as status
+ join payment.statusChanges as statusChange
+where payment.status.name <> PaymentStatus.AWAITING_APPROVAL
+ or (
+ 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]]></programlisting>
+
+ <para>
+ Se eu tivesse mapeado a Collection
<literal>statusChanges</literal> como um List, ao invés de um
+ Set, a query teria sido muito mais simples de escrever.
+ </para>
+
+ <programlisting><![CDATA[select count(payment), status.name
+from Payment as payment
+ join payment.currentStatus as status
+where payment.status.name <> PaymentStatus.AWAITING_APPROVAL
+ or payment.statusChanges[ maxIndex(payment.statusChanges) ].user <>
:currentUser
+group by status.name, status.sortOrder
+order by status.sortOrder]]></programlisting>
+
+ <para>
+ A próxima query usa a função <literal>isNull()</literal> do MS
SQL Server, para retornar
+ todas as contas e pagamentos não pagos para a organização, para cada usuário
corrente
+ pertencente. Traduz-se para uma query SQL <literal>com</literal>
três inner joins,
+ um outer join e um subselect nas tabelas
<literal>ACCOUNT</literal>, <literal>PAYMENT</literal>,
+
<literal>PAYMENT_STATUS</literal>,<literal>ACCOUNT_TYPE</literal>,
+ <literal>ORGANIZATION</literal> e
<literal>ORG_USER</literal> .
+ </para>
+
+ <programlisting><![CDATA[select account, payment
+from Account as account
+ left outer join account.payments as payment
+where :currentUser in elements(account.holder.users)
+ and PaymentStatus.UNPAID = isNull(payment.currentStatus.name, PaymentStatus.UNPAID)
+order by account.type.sortOrder, account.accountNumber,
payment.dueDate]]></programlisting>
+
+ <para>
+ Para alguns bancos de dados, precisaremos eleminar o subselect
(correlacionado).
+ </para>
+
+ <programlisting><![CDATA[select account, payment
+from Account as account
+ join account.holder.users as user
+ left outer join account.payments as payment
+where :currentUser = user
+ and PaymentStatus.UNPAID = isNull(payment.currentStatus.name, PaymentStatus.UNPAID)
+order by account.type.sortOrder, account.accountNumber,
payment.dueDate]]></programlisting>
+
+ </sect1>
+
+ <sect1 id="queryhql-bulk" revision="2">
+ <title>update e delete em lote</title>
+
+ <para>
+ Agora o HQL suporta declarações, <literal>update</literal>,
+ <literal>delete</literal> e <literal>insert ... select
...</literal>
+ Veja <xref linkend="batch-direct"/>, para mais detalhes.
+ </para>
+ </sect1>
+
+ <sect1 id="queryhql-tipstricks">
+ <title>Dicas e Truques</title>
+
+ <para>
+ Pode-se contar o número de resultados da query, sem realmente retorna-los.
+ </para>
+
+ <programlisting><![CDATA[( (Integer) session.createQuery("select
count(*) from ....").iterate().next() ).intValue()]]></programlisting>
+
+ <para>
+ Para ordenar um resultado pelo tamanho de uma Collection, use a query a
seguir.
+ </para>
+
+ <programlisting><![CDATA[select usr.id, usr.name
+from User as usr
+ left join usr.messages as msg
+group by usr.id, usr.name
+order by count(msg)]]></programlisting>
+
+ <para>
+ Se seu banco de dados suporta subselects, pode-se colocar uma condição sobre
+ tamanho de seleção na cláusula where da sua query:
+ </para>
+
+ <programlisting><![CDATA[from User usr where size(usr.messages) >=
1]]></programlisting>
+
+ <para>
+ Se seu banco de dados não suporta subselects, use a query a seguir:
+ </para>
+
+ <programlisting><![CDATA[select usr.id, usr.name
+from User usr.name
+ join usr.messages msg
+group by usr.id, usr.name
+having count(msg) >= 1]]></programlisting>
+
+ <para>
+ Com essa solução não se pode retornar um <literal>User</literal>
<literal>com</literal> sem
+ nenhuma menssagem, por causa do "inner join", a forma a seguir
também é útil.
+ </para>
+
+ <programlisting><![CDATA[select usr.id, usr.name
+from User as usr
+ left join usr.messages as msg
+group by usr.id, usr.name
+having count(msg) = 0]]></programlisting>
+
+ <para>
+ As propriedades de um JavaBean podem ser limitadas à parâmetros nomeados da
query:
+ </para>
+
+ <programlisting><![CDATA[Query q = s.createQuery("from foo Foo as
foo where foo.name=:name and foo.size=:size");
+q.setProperties(fooBean); // fooBean has getName() and getSize()
+List foos = q.list();]]></programlisting>
+
+ <para>
+ As Collections são paginaveis, usando a interface
<literal>Query</literal> <literal>com</literal> um filtro:
+ </para>
+
+ <programlisting><![CDATA[Query q = s.createFilter( collection,
"" ); // the trivial filter
+q.setMaxResults(PAGE_SIZE);
+q.setFirstResult(PAGE_SIZE * pageNumber);
+List page = q.list();]]></programlisting>
+
+ <para>
+ Os elementos da Collection podem ser ordenados ou agrupados
+ usando um filtro de query:
+ </para>
+
+ <programlisting><![CDATA[Collection orderedCollection = s.filter(
collection, "order by this.amount" );
+Collection counts = s.filter( collection, "select this.type, count(this) group by
this.type" );]]></programlisting>
+
+ <para>
+ Pode-se achar o tamanho de uma Collection sem inicializa-la:
+ </para>
+
+ <programlisting><![CDATA[( (Integer) session.createQuery("select
count(*) from ....").iterate().next() ).intValue();]]></programlisting>
+
+ </sect1>
+
+</chapter>
+
Modified: core/trunk/documentation/manual/pt-BR/src/main/docbook/content/query_sql.xml
===================================================================
---
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/query_sql.xml 2007-10-26
00:46:38 UTC (rev 14135)
+++
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/query_sql.xml 2007-10-26
00:48:48 UTC (rev 14136)
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="querysql" revision="2">
+<chapter id="querysql" revision="2">
<title>Native SQL</title>
<para>You may also express queries in the native SQL dialect of your
Modified: core/trunk/documentation/manual/pt-BR/src/main/docbook/content/session_api.xml
===================================================================
---
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/session_api.xml 2007-10-26
00:46:38 UTC (rev 14135)
+++
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/session_api.xml 2007-10-26
00:48:48 UTC (rev 14136)
@@ -1,1248 +1,1270 @@
<?xml version='1.0' encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="objectstate">
- <title>Trabalhando com objetos</title>
-
- <para>
- O Hibernate é uma solução completa de mapeamento objeto/relacional que não apenas
- poupa o desenvolvedor dos detalhes de baixo nível do sistema de gerenciamento do
- banco de dados, mas também oferece um <emphasis>gerenciamento de estado
</emphasis>
- para objetos. Isto é, ao contrário do gerenciamento de <literal>instruções
</literal>
- SQL em camadas de persistência JDBC/SQL comuns, uma visão natural da persistência
- orientada a objetos em aplicações Java.
- </para>
-
- <para>
- Em outras palavras, desenvolvedores de aplicações Hibernate podem sempre pensar
em
- relação ao <emphasis>estado</emphasis> de seus objetos, e não
necessariamente em
- relação a execução de instruções SQL. Este parte é responsabilidade do Hibernate
e
- é relevante aos desenvolvedores de aplicações apenas quando estão ajustando
- a performance do sistema.
- </para>
-
- <sect1 id="objectstate-overview">
- <title>Estado dos objetos no Hibernate</title>
-
- <para>
- O Hibernate define e suporta os seguintes estados de um objetos:
- </para>
-
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>Transient</emphasis> - um objeto é transiente
se ele foi instanciando
- usando apenas o operador <literal>new</literal>, e não
foi associado com uma
- <literal>Session</literal> do Hibernate. Ele não terá uma
representação
- persistente no banco de dados e nenhum identificador será atribuído
para ele.
- Instâncias transientes serão destruídas pelo coletor de lixo se a
aplicação
- não manter sua referência. Use uma
<literal>Session</literal> do Hibernate
- para tornar o objeto persistente ( e deixe o Hibernate gerenciar as
- instruções SQL que serão necessárias para executar esta transição).
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>Persistent</emphasis> -– uma instância
persistente possui uma
- representação no banco de dados e um identificador. Ele pode ter sido
salvo
- ou carregado, assim, ele está por definição no escopo de uma
- <literal>Session</literal>. O Hibernate irá detectar
qualquer mudança feita a
- um objeto persistente e sincronizar o seu estado com o banco de dados
quando
- completar a unidade de trabalho. Desenvolvedores não executam
instruções manuais
- de <literal>UPDATE</literal>, ou instruções de
<literal>DELETE</literal>
- quando o objeto deve ser passado para transiente.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>Detached</emphasis> – uma instância desaclopada
é um objeto que
- foi persistido, mas sua <literal>Session</literal> foi
fechada. A referência
- ao objeto continua válida, é claro, e a instância destacada
desaclopada pode
- ser acoplada a uma nova <literal>Session</literal> no
futuro, fazendo-o
- ( e todas as modificações sofridas) persistente novamente. Essa
característica
- possibilita um modelo de programação para unidades de trabalho que
rodam
- durante muito tempo que requer um pensamento por tempo do usuário.
Podemos
- chamar-las de <emphasis>transações da
aplicação</emphasis>, i.e. uma unidade
- de trabalho do ponto de vista do usuário.
- </para>
- </listitem>
- </itemizedlist>
-
- <para>
- Agora iremos discutir os estados e suas transições ( e os métodos do
Hibernate que
- disparam uma transição) em mais detalhes.
- </para>
-
- </sect1>
-
- <sect1 id="objectstate-makingpersistent" revision="1">
- <title>Tornando os objetos persistentes</title>
-
- <para>
- Instâncias recentemente instanciadas de uma classe persistente são
- consideradas <emphasis>transientes </emphasis> pelo Hibernate.
- Podemos tornar uma instância transiente em
<emphasis>persistente</emphasis>
- associando-a a uma sessão:
- </para>
-
- <programlisting><![CDATA[DomesticCat fritz = new DomesticCat();
-fritz.setColor(Color.GINGER);
-fritz.setSex('M');
-fritz.setName("Fritz");
-Long generatedId = (Long) sess.save(fritz);]]></programlisting>
-
- <para>
- Se <literal>Cat</literal> possui um identificador gerado, o
identificador
- é gerado e atribuído a <literal>cat</literal> quando
<literal>save()</literal>
- for chamada. Se <literal>Cat</literal> possuir um identificador
- <literal>Associado</literal>, ou uma chave composta, o
identificador deve ser
- atribuído à instância de <literal>cat</literal> antes que
<literal>save()</literal>
- seja chamado. Pode-se usar também <literal>persist()</literal>
ao invés de
- <literal>save()</literal>, com a semântica definada no novo
esboço do EJB3.
- </para>
-
- <para>
- Alternativamente, pode-se atribuir o identificador usando uma versão
- sobrecarregada de <literal>save()</literal>.
- </para>
-
-<programlisting><![CDATA[DomesticCat pk = new DomesticCat();
-pk.setColor(Color.TABBY);
-pk.setSex('F');
-pk.setName("PK");
-pk.setKittens( new HashSet() );
-pk.addKitten(fritz);
-sess.save( pk, new Long(1234) );]]></programlisting>
-
- <para>
- Se o objeto persistido possuir objetos associados (e.g. a coleção
- <literal>kittens</literal> no exemplo anterior), esses objetos
podem ser
- tornar persistente em qualquer ordem que se queira ao menos que se tenha uma
- restrição <literal>NOT NULL</literal> em uma coluna de chave
estrangeira.
- Nunca há risco de violação de restrições de chave estrangeira. Assim,
- pode-se violar uma restrição <literal>NOT NULL</literal> se
- <literal>save()</literal> for usada nos objetos em uma ordem
errada.
- </para>
-
- <para>
- Geralmente você não deve se importar com esses detalhes, muito provavelmente
se
- usará a característica de <emphasis>persistência transitiva
</emphasis> do Hibernate
- para salvar os objetos associados automaticamente. Então, enquanto uma
restrição
- <literal>NOT NULL</literal> não ocorrer – Hibernate tomará conta
de tudo.
- Persistência transitiva será discutida futuramente nesse capítulo.
- </para>
-
- </sect1>
-
- <sect1 id="objectstate-loading">
- <title>Carregando o objetos</title>
-
- <para>
- O método <literal>load()</literal> de uma <literal>
Session</literal> nos
- fornece um meio para recuperar uma instância persistente se o identificador
- for conhecido. <literal>load()</literal> recebe uma classe do
objeto e carregará
- o estado em uma instância mais recente dessa classe, no estado persistente.
- </para>
-
- <programlisting><![CDATA[Cat fritz = (Cat) sess.load(Cat.class,
generatedId);]]></programlisting>
-
-<programlisting><![CDATA[// you need to wrap primitive identifiers
-long id = 1234;
-DomesticCat pk = (DomesticCat) sess.load( DomesticCat.class, new Long(id)
);]]></programlisting>
-
- <para>
- Alternatively, you can load state into a given instance:
-Alternativamente, pode-se carregar um estado em uma instância dada:
- </para>
-
-<programlisting><![CDATA[Cat cat = new DomesticCat();
-// load pk's state into cat
-sess.load( cat, new Long(pkId) );
-Set kittens = cat.getKittens();]]></programlisting>
-
- <para>
- Repare que <literal>load()</literal> irá lançar uma exceção
irrecuperável
- se não houver na tabela no banco de dados um registro que combine.
- Se a classe for mapeada com um proxy, <literal>load()</literal>
- simplesmente retorna um proxy não inicializado e realmente não chamará
- o banco de dados até que um método do proxy seja invocado.
- Esse comportamento é muito útil se deseja-se criar uma associação
- com um objeto sem que realmente o carregue do bando de dados.
- Isto também permite que sejam carregadas múltiplas instâncias como um
- grupo se <literal>batch-size</literal> estiver para o mapeamento
da
- classe.
- </para>
-
- <para>
- Se você não tiver certeza da existencia do registro no banco, você deve
- usar o metodo <literal>get()</literal>, que consulta o banco
- imediantamente e retorna um null se não existir o registro.
- </para>
-
- <programlisting><![CDATA[Cat cat = (Cat) sess.get(Cat.class, id);
-if (cat==null) {
- cat = new Cat();
- sess.save(cat, id);
-}
-return cat;]]></programlisting>
-
- <para>
- Também pode-se carregar um objeto usando <literal>SELECT ... FOR
UPDATE</literal>,
- usando um <literal>LockMode</literal>. Veja a documentação da API
para maiores
- informações.
- </para>
-
- <programlisting><![CDATA[Cat cat = (Cat) sess.get(Cat.class, id,
LockMode.UPGRADE);]]></programlisting>
-
- <para>
- Note that any associated instances or contained collections are
- <emphasis>not</emphasis> selected <literal>FOR
UPDATE</literal>, unless you decide
- to specify <literal>lock</literal> or
<literal>all</literal> as a
- cascade style for the association.
- </para>
-
- <para>
- O recarregamento de um objeto e todas as suas coleções é possível a qualquer
momento,
- usando o método <literal>refresh()</literal>. Util quando as
triggers do banco de
- dados são usados para inicializar algumas propriedades do objeto.
- </para>
-
- <programlisting><![CDATA[sess.save(cat);
-sess.flush(); //force the SQL INSERT
-sess.refresh(cat); //re-read the state (after the trigger
executes)]]></programlisting>
-
- <para>
- Uma importante questão geralmente aparece neste ponto: O quanto Hibernate
carrega
- do banco de dados e quantos SQL <literal>SELECT</literal> ele
irá usar? Isto
- depende da estratégia de <emphasis>recuperação</emphasis>usada e
explicada na
- <xref linkend="performance-fetching"/>.
- </para>
-
- </sect1>
-
- <sect1 id="objectstate-querying" revision="1">
- <title>Consultando</title>
-
- <para>
- Se o identificador do objeto que se está buscando não for conhecido,
- uma consulta será necessária. O Hibernate suporta uma linguagem de consulta
- (HQL) orientada a objetos fácil mas poderosa. Para criação via programação
- de consultas, o Hibernate suporta características sofisticadas de consulta
- por Critério e Exemplo (QBCe QBE). Pode-se também expressar a consulta
- por meio de SQL nativa do banco de dados, com suporte opcional do Hibernate
- para conversão do conjunto de reultados em objetos.
- </para>
-
- <sect2 id="objectstate-querying-executing"
revision="1">
- <title>Executando consultas</title>
-
- <para>
- Consultas HQL e SQL nativa são representadas por uma instância de
<literal>org.hibernate.Query</literal>.
- Esta interface oferece métodos para associação de parâmetros, tratamento
de conjunto de resultados,
- e para a execução de consultas reais. Você pode obter uma
<literal>Query</literal> usando a
- <literal>Session</literal> atual:
- </para>
-
- <programlisting><![CDATA[List cats = session.createQuery(
- "from Cat as cat where cat.birthdate < ?")
- .setDate(0, date)
- .list();
-
-List mothers = session.createQuery(
- "select mother from Cat as cat join cat.mother as mother where cat.name =
?")
- .setString(0, name)
- .list();
-
-List kittens = session.createQuery(
- "from Cat as cat where cat.mother = ?")
- .setEntity(0, pk)
- .list();
-
-Cat mother = (Cat) session.createQuery(
- "select cat.mother from Cat as cat where cat = ?")
- .setEntity(0, izi)
- .uniqueResult();]]
-
-Query mothersWithKittens = (Cat) session.createQuery(
- "select mother from Cat as mother left join fetch mother.kittens");
-Set uniqueMothers = new HashSet(mothersWithKittens.list());]]></programlisting>
-
- <para>
- Geralmente uma consulta é executada ao invocar
<literal>list()</literal>,
- o resultado da consulta será carregado completamente em uma coleção na
memória.
- Instâncias de entidades recuperadas por uma consulta estão no estado
persistente.
- O <literal>uniqueResult()</literal> oferece um atalho se você
souber de
- previamente que a consulta retornará apenas um único objeto. Repare que
consultas
- que fazem uso de buscas de coleções de forma ansiosa (eager) geralmente
retornam
- duplicatas dos objetos raiz ( mas com suas coleções inicializadas ).
Pode-se
- filtrar estas duplicatas através de um simples
<literal>Set</literal>.
- </para>
-
- <sect3 id="objectstate-querying-executing-iterate">
- <title>Interagindo com resultados</title>
-
- <para>
- Ocasionalmente, deves-se ser capaz de atingir performances melhores
com
- a execução de consultas usando o método
<literal>iterate()</literal>.
- Geralmente isso será o caso esperado apenas se as instâncias dos
entidades
- reais retornadas pela consulta já estiverem na sessão ou no caché de
segundo
- nível. Caso elas ainda não tenham sido armazenadas,
<literal>iterate()</literal>
- será mais devagar do que <literal>list()</literal> e pode
ser necessário vários
- acessos ao banco de dados para um simples consulta, geralmente
<emphasis>1</emphasis>
- para a seleção inicial que retorna apenas identificadores, e
<emphasis>n</emphasis>
- consultas adicionais para inicializar as instâncias reais.
- </para>
-
- <programlisting><![CDATA[// 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;
- }
-}]]></programlisting>
- </sect3>
-
- <sect3 id="objectstate-querying-executing-tuples">
- <title>Consultas que retornam tuplas</title>
-
- <para>
- Algumas vezes as consultas do Hibernate retornam tuplas de objetos,
nesse caso
- cada tupla é retornada como um array:
- </para>
-
- <programlisting><![CDATA[Iterator kittensAndMothers =
sess.createQuery(
- "select kitten, mother from Cat kitten join kitten.mother mother")
- .list()
- .iterator();
-
-while ( kittensAndMothers.hasNext() ) {
- Object[] tuple = (Object[]) kittensAndMothers.next();
- Cat kitten = (Cat) tuple[0];
- Cat mother = (Cat) tuple[1];
- ....
-}]]></programlisting>
-
- </sect3>
-
- <sect3 id="objectstate-querying-executing-scalar"
revision="1">
- <title>Resultados escalares</title>
-
- <para>
- Consultas devem especificar uma propriedade da classe na clausula
- <literal>select</literal>. Elas também podem chamar
funções SQL de agregaçãos.
- Propriedades ou agregações são considerados resultados agregados
- ( e não entidades no estado persistente).
- </para>
-
- <programlisting><![CDATA[Iterator results = sess.createQuery(
- "select cat.color, min(cat.birthdate), count(cat) from Cat cat " +
- "group by cat.color")
- .list()
- .iterator();
-
-while ( results.hasNext() ) {
- Object[] row = (Object[]) results.next();
- Color type = (Color) row[0];
- Date oldest = (Date) row[1];
- Integer count = (Integer) row[2];
- .....
-}]]></programlisting>
-
- </sect3>
-
- <sect3 id="objectstate-querying-executing-parameters">
- <title>Bind parameters</title>
-
- <para>
- Methods on <literal>Query</literal> are provided for
binding values to
- named parameters or JDBC-style <literal>?</literal>
parameters.
- <emphasis>Contrary to JDBC, Hibernate numbers parameters from
zero.</emphasis>
- Named parameters are identifiers of the form
<literal>:name</literal> in
- the query string. The advantages of named parameters are:
- </para>
-
- <itemizedlist spacing="compact">
- <listitem>
- <para>
- named parameters are insensitive to the order they occur in
the
- query string
- </para>
- </listitem>
- <listitem>
- <para>
- they may occur multiple times in the same query
- </para>
- </listitem>
- <listitem>
- <para>
- they are self-documenting
- </para>
- </listitem>
- </itemizedlist>
-
- <programlisting><![CDATA[//named parameter (preferred)
-Query q = sess.createQuery("from DomesticCat cat where cat.name = :name");
-q.setString("name", "Fritz");
-Iterator cats = q.iterate();]]></programlisting>
-
- <programlisting><![CDATA[//positional parameter
-Query q = sess.createQuery("from DomesticCat cat where cat.name = ?");
-q.setString(0, "Izi");
-Iterator cats = q.iterate();]]></programlisting>
-
- <programlisting><![CDATA[//named parameter list
-List names = new ArrayList();
-names.add("Izi");
-names.add("Fritz");
-Query q = sess.createQuery("from DomesticCat cat where cat.name in
(:namesList)");
-q.setParameterList("namesList", names);
-List cats = q.list();]]></programlisting>
-
- </sect3>
-
- <sect3 id="objectstate-querying-executing-pagination">
- <title>Pagination</title>
-
- <para>
- If you need to specify bounds upon your result set (the maximum
number of rows
- you want to retrieve and / or the first row you want to retrieve) you
should
- use methods of the <literal>Query</literal> interface:
- </para>
-
- <programlisting><![CDATA[Query q = sess.createQuery("from
DomesticCat cat");
-q.setFirstResult(20);
-q.setMaxResults(10);
-List cats = q.list();]]></programlisting>
-
- <para>
- Hibernate knows how to translate this limit query into the native
- SQL of your DBMS.
- </para>
-
- </sect3>
-
- <sect3 id="objectstate-querying-executing-scrolling">
- <title>Scrollable iteration</title>
-
- <para>
- If your JDBC driver supports scrollable
<literal>ResultSet</literal>s, the
- <literal>Query</literal> interface may be used to obtain
a
- <literal>ScrollableResults</literal> object, which allows
flexible
- navigation of the query results.
- </para>
-
- <programlisting><![CDATA[Query q = sess.createQuery("select
cat.name, cat from DomesticCat cat " +
- "order by cat.name");
-ScrollableResults cats = q.scroll();
-if ( cats.first() ) {
-
- // 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) );
-
- // Now get the first page of cats
- pageOfCats = new ArrayList();
- cats.beforeFirst();
- int i=0;
- while( ( PAGE_SIZE > i++ ) && cats.next() ) pageOfCats.add( cats.get(1)
);
-
-}
-cats.close()]]></programlisting>
-
- <para>
- Note that an open database connection (and cursor) is required for
this
- functionality, use
<literal>setMaxResult()</literal>/<literal>setFirstResult()</literal>
- if you need offline pagination functionality.
- </para>
-
- </sect3>
-
- <sect3 id="objectstate-querying-executing-named"
revision="1">
- <title>Externalizing named queries</title>
-
- <para>
- You may also define named queries in the mapping document. (Remember
to use a
- <literal>CDATA</literal> section if your query contains
characters that could
- be interpreted as markup.)
- </para>
-
- <programlisting><![CDATA[<query
name="ByNameAndMaximumWeight"><![CDATA[
- from eg.DomesticCat as cat
- where cat.name = ?
- and cat.weight > ?
-] ]></query>]]></programlisting>
-
- <para>
- Parameter binding and executing is done programatically:
- </para>
-
- <programlisting><![CDATA[Query q =
sess.getNamedQuery("ByNameAndMaximumWeight");
-q.setString(0, name);
-q.setInt(1, minWeight);
-List cats = q.list();]]></programlisting>
-
- <para>
- Note that the actual program code is independent of the query
language that
- is used, you may also define native SQL queries in metadata, or
migrate
- existing queries to Hibernate by placing them in mapping files.
- </para>
-
- <para>
- Also note that a query declaration inside a
<literal><hibernate-mapping></literal>
- element requires a global unique name for the query, while a query
declaration inside a
- <literal><class></literal> element is made
unique automatically by prepending the
- fully qualified name of the class, for example
- <literal>eg.Cat.ByNameAndMaximumWeight</literal>.
- </para>
-
- </sect3>
-
- </sect2>
-
- <sect2 id="objectstate-filtering" revision="1">
- <title>Filtering collections</title>
- <para>
- A collection <emphasis>filter</emphasis> is a special type of
query that may be applied to
- a persistent collection or array. The query string may refer to
<literal>this</literal>,
- meaning the current collection element.
- </para>
-
- <programlisting><![CDATA[Collection blackKittens =
session.createFilter(
- pk.getKittens(),
- "where this.color = ?")
- .setParameter( Color.BLACK, Hibernate.custom(ColorUserType.class) )
- .list()
-);]]></programlisting>
-
- <para>
- The returned collection is considered a bag, and it's a copy of the
given
- collection. The original collection is not modified (this is contrary to
- the implication of the name "filter", but consistent with
expected behavior).
- </para>
-
- <para>
- Observe that filters do not require a <literal>from</literal>
clause (though they may have
- one if required). Filters are not limited to returning the collection
elements themselves.
- </para>
-
- <programlisting><![CDATA[Collection blackKittenMates =
session.createFilter(
- pk.getKittens(),
- "select this.mate where this.color = eg.Color.BLACK.intValue")
- .list();]]></programlisting>
-
- <para>
- Even an empty filter query is useful, e.g. to load a subset of elements
in a
- huge collection:
- </para>
-
- <programlisting><![CDATA[Collection tenKittens =
session.createFilter(
- mother.getKittens(), "")
- .setFirstResult(0).setMaxResults(10)
- .list();]]></programlisting>
-
- </sect2>
-
- <sect2 id="objecstate-querying-criteria" revision="1">
- <title>Criteria queries</title>
-
- <para>
- HQL is extremely powerful but some developers prefer to build queries
dynamically,
- using an object-oriented API, rather than building query strings.
Hibernate provides
- an intuitive <literal>Criteria</literal> query API for these
cases:
- </para>
-
- <programlisting><![CDATA[Criteria crit =
session.createCriteria(Cat.class);
-crit.add( Restrictions.eq( "color", eg.Color.BLACK ) );
-crit.setMaxResults(10);
-List cats = crit.list();]]></programlisting>
-
- <para>
- The <literal>Criteria</literal> and the associated
<literal>Example</literal>
- API are discussed in more detail in <xref
linkend="querycriteria"/>.
- </para>
-
- </sect2>
-
- <sect2 id="objectstate-querying-nativesql"
revision="2">
- <title>Queries in native SQL</title>
-
- <para>
- You may express a query in SQL, using
<literal>createSQLQuery()</literal> and
- let Hibernate take care of the mapping from result sets to objects. Note
- that you may at any time call
<literal>session.connection()</literal> and
- use the JDBC <literal>Connection</literal> directly. If you
chose to use the
- Hibernate API, you must enclose SQL aliases in braces:
- </para>
-
- <programlisting><![CDATA[List cats =
session.createSQLQuery("SELECT {cat.*} FROM CAT {cat} WHERE ROWNUM<10")
- .addEntity("cat", Cat.class)
-.list();]]></programlisting>
-
- <programlisting><![CDATA[List cats = session.createSQLQuery(
- "SELECT {cat}.ID AS {cat.id}, {cat}.SEX AS {cat.sex}, " +
- "{cat}.MATE AS {cat.mate}, {cat}.SUBCLASS AS {cat.class}, ... " +
- "FROM CAT {cat} WHERE ROWNUM<10")
- .addEntity("cat", Cat.class)
-.list()]]></programlisting>
-
- <para>
- SQL queries may contain named and positional parameters, just like
Hibernate queries.
- More information about native SQL queries in Hibernate can be found in
- <xref linkend="querysql"/>.
- </para>
-
- </sect2>
-
- </sect1>
-
- <sect1 id="objectstate-modifying" revision="1">
- <title>Modifying persistent objects</title>
-
- <para>
- <emphasis>Transactional persistent instances</emphasis> (ie.
objects loaded, saved, created or
- queried by the <literal>Session</literal>) may be manipulated by
the application
- and any changes to persistent state will be persisted when the
<literal>Session</literal>
- is <emphasis>flushed</emphasis> (discussed later in this
chapter). There is no need
- to call a particular method (like <literal>update()</literal>,
which has a different
- purpose) to make your modifications persistent. So the most straightforward
way to update
- the state of an object is to <literal>load()</literal> it,
- and then manipulate it directly, while the
<literal>Session</literal> is open:
- </para>
-
- <programlisting><![CDATA[DomesticCat cat = (DomesticCat) sess.load(
Cat.class, new Long(69) );
-cat.setName("PK");
-sess.flush(); // changes to cat are automatically detected and
persisted]]></programlisting>
-
- <para>
- Sometimes this programming model is inefficient since it would require both
an SQL
- <literal>SELECT</literal> (to load an object) and an SQL
<literal>UPDATE</literal>
- (to persist its updated state) in the same session. Therefore Hibernate
offers an
- alternate approach, using detached instances.
- </para>
-
- <para>
- <emphasis>Note that Hibernate does not offer its own API for direct
execution of
- <literal>UPDATE</literal> or
<literal>DELETE</literal> statements. Hibernate is a
- <emphasis>state management</emphasis> service, you don't have
to think in
- <emphasis>statements</emphasis> to use it. JDBC is a perfect API
for executing
- SQL statements, you can get a JDBC <literal>Connection</literal>
at any time
- by calling <literal>session.connection()</literal>. Furthermore,
the notion
- of mass operations conflicts with object/relational mapping for online
- transaction processing-oriented applications. Future versions of Hibernate
- may however provide special mass operation functions. See <xref
linkend="batch"/>
- for some possible batch operation tricks.</emphasis>
- </para>
-
- </sect1>
-
- <sect1 id="objectstate-detached" revision="2">
- <title>Modifying detached objects</title>
-
- <para>
- Many applications need to retrieve an object in one transaction, send it to
the
- UI layer for manipulation, then save the changes in a new transaction.
- Applications that use this kind of approach in a high-concurrency
environment
- usually use versioned data to ensure isolation for the "long" unit
of work.
- </para>
-
- <para>
- Hibernate supports this model by providing for reattachment of detached
instances
- using the <literal>Session.update()</literal> or
<literal>Session.merge()</literal>
- methods:
- </para>
-
- <programlisting><![CDATA[// in the first session
-Cat cat = (Cat) firstSession.load(Cat.class, catId);
-Cat potentialMate = new Cat();
-firstSession.save(potentialMate);
-
-// in a higher layer of the application
-cat.setMate(potentialMate);
-
-// later, in a new session
-secondSession.update(cat); // update cat
-secondSession.update(mate); // update mate]]></programlisting>
-
- <para>
- If the <literal>Cat</literal> with identifier
<literal>catId</literal> had already
- been loaded by <literal>secondSession</literal> when the
application tried to
- reattach it, an exception would have been thrown.
- </para>
-
- <para>
- Use <literal>update()</literal> if you are sure that the session
does
- not contain an already persistent instance with the same identifier, and
- <literal>merge()</literal> if you want to merge your
modifications at any time
- without consideration of the state of the session. In other words,
<literal>update()</literal>
- is usually the first method you would call in a fresh session, ensuring that
- reattachment of your detached instances is the first operation that is
executed.
- </para>
-
- <para>
- The application should individually <literal>update()</literal>
detached instances
- reachable from the given detached instance if and
<emphasis>only</emphasis> if it wants
- their state also updated. This can be automated of course, using
<emphasis>transitive
- persistence</emphasis>, see <xref
linkend="objectstate-transitive"/>.
- </para>
-
- <para>
- The <literal>lock()</literal> method also allows an application
to reassociate
- an object with a new session. However, the detached instance has to be
unmodified!
- </para>
-
- <programlisting><![CDATA[//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);]]></programlisting>
-
- <para>
- Note that <literal>lock()</literal> can be used with various
- <literal>LockMode</literal>s, see the API documentation and the
- chapter on transaction handling for more information. Reattachment is not
- the only usecase for <literal>lock()</literal>.
- </para>
-
- <para>
- Other models for long units of work are discussed in <xref
linkend="transactions-optimistic"/>.
- </para>
-
- </sect1>
-
- <sect1 id="objectstate-saveorupdate">
- <title>Automatic state detection</title>
-
- <para>
- Hibernate users have requested a general purpose method that either saves a
- transient instance by generating a new identifier or updates/reattaches
- the detached instances associated with its current identifier.
- The <literal>saveOrUpdate()</literal> method implements this
functionality.
- </para>
-
- <programlisting><![CDATA[// in the first session
-Cat cat = (Cat) firstSession.load(Cat.class, catID);
-
-// in a higher tier of the application
-Cat mate = new Cat();
-cat.setMate(mate);
-
-// later, in a new session
-secondSession.saveOrUpdate(cat); // update existing state (cat has a non-null id)
-secondSession.saveOrUpdate(mate); // save the new instance (mate has a null
id)]]></programlisting>
-
- <para>
- The usage and semantics of <literal>saveOrUpdate()</literal>
seems to be confusing
- for new users. Firstly, so long as you are not trying to use instances from
one session
- in another new session, you should not need to use
<literal>update()</literal>,
- <literal>saveOrUpdate()</literal>, or
<literal>merge()</literal>. Some whole
- applications will never use either of these methods.
- </para>
-
- <para>
- Usually <literal>update()</literal> or
<literal>saveOrUpdate()</literal> are used in
- the following scenario:
- </para>
-
- <itemizedlist spacing="compact">
- <listitem>
- <para>
- the application loads an object in the first session
- </para>
- </listitem>
- <listitem>
- <para>
- the object is passed up to the UI tier
- </para>
- </listitem>
- <listitem>
- <para>
- some modifications are made to the object
- </para>
- </listitem>
- <listitem>
- <para>
- the object is passed back down to the business logic tier
- </para>
- </listitem>
- <listitem>
- <para>
- the application persists these modifications by calling
- <literal>update()</literal> in a second session
- </para>
- </listitem>
- </itemizedlist>
-
- <para>
- <literal>saveOrUpdate()</literal> does the following:
- </para>
-
- <itemizedlist spacing="compact">
- <listitem>
- <para>
- if the object is already persistent in this session, do nothing
- </para>
- </listitem>
- <listitem>
- <para>
- if another object associated with the session has the same
identifier,
- throw an exception
- </para>
- </listitem>
- <listitem>
- <para>
- if the object has no identifier property,
<literal>save()</literal> it
- </para>
- </listitem>
- <listitem>
- <para>
- if the object's identifier has the value assigned to a newly
instantiated
- object, <literal>save()</literal> it
- </para>
- </listitem>
- <listitem>
- <para>
- if the object is versioned (by a
<literal><version></literal> or
- <literal><timestamp></literal>), and the
version property value
- is the same value assigned to a newly instantiated object,
- <literal>save()</literal> it
- </para>
- </listitem>
- <listitem>
- <para>
- otherwise <literal>update()</literal> the object
- </para>
- </listitem>
- </itemizedlist>
-
- <para>
- and <literal>merge()</literal> is very different:
- </para>
-
- <itemizedlist spacing="compact">
- <listitem>
- <para>
- if there is a persistent instance with the same identifier currently
- associated with the session, copy the state of the given object onto
- the persistent instance
- </para>
- </listitem>
- <listitem>
- <para>
- if there is no persistent instance currently associated with the
session,
- try to load it from the database, or create a new persistent
instance
- </para>
- </listitem>
- <listitem>
- <para>
- the persistent instance is returned
- </para>
- </listitem>
- <listitem>
- <para>
- the given instance does not become associated with the session, it
- remains detached
- </para>
- </listitem>
- </itemizedlist>
-
- </sect1>
-
- <sect1 id="objectstate-deleting" revision="1">
- <title>Deleting persistent objects</title>
-
- <para>
- <literal>Session.delete()</literal> will remove an object's
state from the database.
- Of course, your application might still hold a reference to a deleted
object.
- It's best to think of <literal>delete()</literal> as making a
persistent instance
- transient.
- </para>
-
- <programlisting><![CDATA[sess.delete(cat);]]></programlisting>
-
- <para>
- You may delete objects in any order you like, without risk of foreign key
- constraint violations. It is still possible to violate a <literal>NOT
- NULL</literal> constraint on a foreign key column by deleting objects
in
- the wrong order, e.g. if you delete the parent, but forget to delete the
- children.
- </para>
-
- </sect1>
-
- <sect1 id="objectstate-replicating" revision="1">
- <title>Replicating object between two different datastores</title>
-
- <para>
- It is occasionally useful to be able to take a graph of persistent instances
- and make them persistent in a different datastore, without regenerating
identifier
- values.
- </para>
-
- <programlisting><![CDATA[//retrieve a cat from one database
-Session session1 = factory1.openSession();
-Transaction tx1 = session1.beginTransaction();
-Cat cat = session1.get(Cat.class, catId);
-tx1.commit();
-session1.close();
-
-//reconcile with a second database
-Session session2 = factory2.openSession();
-Transaction tx2 = session2.beginTransaction();
-session2.replicate(cat, ReplicationMode.LATEST_VERSION);
-tx2.commit();
-session2.close();]]></programlisting>
-
- <para>
- The <literal>ReplicationMode</literal> determines how
<literal>replicate()</literal>
- will deal with conflicts with existing rows in the database.
- </para>
-
- <itemizedlist spacing="compact">
- <listitem>
- <para>
- <literal>ReplicationMode.IGNORE</literal> - ignore the
object when there is
- an existing database row with the same identifier
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>ReplicationMode.OVERWRITE</literal> - overwrite
any existing database
- row with the same identifier
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>ReplicationMode.EXCEPTION</literal> - throw an
exception if there is
- an existing database row with the same identifier
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>ReplicationMode.LATEST_VERSION</literal> -
overwrite the row if its
- version number is earlier than the version number of the object, or
ignore
- the object otherwise
- </para>
- </listitem>
- </itemizedlist>
-
- <para>
- Usecases for this feature include reconciling data entered into different
database
- instances, upgrading system configuration information during product
upgrades,
- rolling back changes made during non-ACID transactions and more.
- </para>
-
- </sect1>
-
- <sect1 id="objectstate-flushing">
- <title>Flushing the Session</title>
-
- <para>
- From time to time the <literal>Session</literal> will execute the
SQL statements
- needed to synchronize the JDBC connection's state with the state of
objects held in
- memory. This process, <emphasis>flush</emphasis>, occurs by
default at the following
- points
- </para>
-
- <itemizedlist spacing="compact">
- <listitem>
- <para>
- before some query executions
- </para>
- </listitem>
- <listitem>
- <para>
- from
<literal>org.hibernate.Transaction.commit()</literal>
- </para>
- </listitem>
- <listitem>
- <para>
- from <literal>Session.flush()</literal>
- </para>
- </listitem>
- </itemizedlist>
-
- <para>
- The SQL statements are issued in the following order
- </para>
-
- <orderedlist spacing="compact">
- <listitem>
- <para>
- all entity insertions, in the same order the corresponding objects
- were saved using <literal>Session.save()</literal>
- </para>
- </listitem>
- <listitem>
- <para>
- all entity updates
- </para>
- </listitem>
- <listitem>
- <para>
- all collection deletions
- </para>
- </listitem>
- <listitem>
- <para>
- all collection element deletions, updates and insertions
- </para>
- </listitem>
- <listitem>
- <para>
- all collection insertions
- </para>
- </listitem>
- <listitem>
- <para>
- all entity deletions, in the same order the corresponding objects
- were deleted using <literal>Session.delete()</literal>
- </para>
- </listitem>
- </orderedlist>
-
- <para>
- (An exception is that objects using <literal>native</literal> ID
generation are
- inserted when they are saved.)
- </para>
-
- <para>
- Except when you explicity <literal>flush()</literal>, there are
absolutely no
- guarantees about <emphasis>when</emphasis> the
<literal>Session</literal> executes
- the JDBC calls, only the <emphasis>order</emphasis> in which they
are executed.
- However, Hibernate does guarantee that the
<literal>Query.list(..)</literal>
- will never return stale data; nor will they return the wrong data.
- </para>
-
- <para>
- It is possible to change the default behavior so that flush occurs less
frequently.
- The <literal>FlushMode</literal> class defines three different
modes: only flush
- at commit time (and only when the Hibernate
<literal>Transaction</literal> API
- is used), flush automatically using the explained routine, or never flush
unless
- <literal>flush()</literal> is called explicitly. The last mode is
useful for long running
- units of work, where a <literal>Session</literal> is kept open
and disconnected for
- a long time (see <xref
linkend="transactions-optimistic-longsession"/>).
- </para>
-
- <programlisting><![CDATA[sess = sf.openSession();
-Transaction tx = sess.beginTransaction();
-sess.setFlushMode(FlushMode.COMMIT); // allow queries to return stale state
-
-Cat izi = (Cat) sess.load(Cat.class, id);
-izi.setName(iznizi);
-
-// might return stale data
-sess.find("from Cat as cat left outer join cat.kittens kitten");
-
-// change to izi is not flushed!
-...
-tx.commit(); // flush occurs
-sess.close();]]></programlisting>
-
- <para>
- 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 <xref linkend="transactions"/>.
- </para>
-
- </sect1>
-
- <sect1 id="objectstate-transitive" revision="1">
- <title>Transitive persistence</title>
-
- <para>
- It is quite cumbersome to save, delete, or reattach individual objects,
- especially if you deal with a graph of associated objects. A common case is
- a parent/child relationship. Consider the following example:
- </para>
-
- <para>
- If the children in a parent/child relationship would be value typed (e.g. a
collection
- of addresses or strings), their life cycle would depend on the parent and no
- further action would be required for convenient "cascading" of
state changes.
- When the parent is saved, the value-typed child objects are saved as
- well, when the parent is deleted, the children will be deleted, etc. This
- even works for operations such as the removal of a child from the
collection;
- Hibernate will detect this and, since value-typed objects can't have
shared
- references, delete the child from the database.
- </para>
-
- <para>
- Now consider the same scenario with parent and child objects being entities,
- not value-types (e.g. categories and items, or parent and child cats).
Entities
- have their own life cycle, support shared references (so removing an entity
from
- the collection does not mean it can be deleted), and there is by default no
- cascading of state from one entity to any other associated entities.
Hibernate
- does not implement <emphasis>persistence by
reachability</emphasis> by default.
- </para>
-
- <para>
- For each basic operation of the Hibernate session - including
<literal>persist(), merge(),
- saveOrUpdate(), delete(), lock(), refresh(), evict(),
replicate()</literal> - there is a
- corresponding cascade style. Respectively, the cascade styles are named
<literal>create,
- merge, save-update, delete, lock, refresh, evict, replicate</literal>.
If you want an
- operation to be cascaded along an association, you must indicate that in the
mapping
- document. For example:
- </para>
-
- <programlisting><![CDATA[<one-to-one name="person"
cascade="persist"/>]]></programlisting>
-
- <para>
- Cascade styles my be combined:
- </para>
-
- <programlisting><![CDATA[<one-to-one name="person"
cascade="persist,delete,lock"/>]]></programlisting>
-
- <para>
- You may even use <literal>cascade="all"</literal> to
specify that <emphasis>all</emphasis>
- operations should be cascaded along the association. The default
<literal>cascade="none"</literal>
- specifies that no operations are to be cascaded.
- </para>
-
- <para>
- A special cascade style, <literal>delete-orphan</literal>,
applies only to one-to-many
- associations, and indicates that the <literal>delete()</literal>
operation should
- be applied to any child object that is removed from the association.
- </para>
-
-
- <para>
- Recommendations:
- </para>
-
- <itemizedlist spacing="compact">
- <listitem>
- <para>
- It doesn't usually make sense to enable cascade on a
<literal><many-to-one></literal>
- or <literal><many-to-many></literal>
association. Cascade is often useful for
- <literal><one-to-one></literal> and
<literal><one-to-many></literal>
- associations.
- </para>
- </listitem>
- <listitem>
- <para>
- If the child object's lifespan is bounded by the lifespan of the
parent
- object, make it a <emphasis>life cycle object</emphasis>
by specifying
-
<literal>cascade="all,delete-orphan"</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- Otherwise, you might not need cascade at all. But if you think that
you will often be
- working with the parent and children together in the same
transaction, and you want to save
- yourself some typing, consider using
<literal>cascade="persist,merge,save-update"</literal>.
- </para>
- </listitem>
- </itemizedlist>
-
- <para>
- Mapping an association (either a single valued association, or a collection)
with
- <literal>cascade="all"</literal> marks the association
as a
- <emphasis>parent/child</emphasis> style relationship where
save/update/delete of the
- parent results in save/update/delete of the child or children.
- </para>
- <para>
- Futhermore, a mere reference to a child from a persistent parent will result
in
- save/update of the child. This metaphor is incomplete, however. A child which
becomes
- unreferenced by its parent is <emphasis>not</emphasis>
automatically deleted, except
- in the case of a <literal><one-to-many></literal>
association mapped with
- <literal>cascade="delete-orphan"</literal>. The precise
semantics of cascading
- operations for a parent/child relationship are as follows:
- </para>
-
- <itemizedlist spacing="compact">
- <listitem>
- <para>
- If a parent is passed to <literal>persist()</literal>,
all children are passed to
- <literal>persist()</literal>
- </para>
- </listitem>
- <listitem>
- <para>
- If a parent is passed to <literal>merge()</literal>, all
children are passed to
- <literal>merge()</literal>
- </para>
- </listitem>
- <listitem>
- <para>
- If a parent is passed to <literal>save()</literal>,
<literal>update()</literal> or
- <literal>saveOrUpdate()</literal>, all children are
passed to <literal>saveOrUpdate()</literal>
- </para>
- </listitem>
- <listitem>
- <para>
- If a transient or detached child becomes referenced by a persistent
parent,
- it is passed to <literal>saveOrUpdate()</literal>
- </para>
- </listitem>
- <listitem>
- <para>
- If a parent is deleted, all children are passed to
<literal>delete()</literal>
- </para>
- </listitem>
- <listitem>
- <para>
- If a child is dereferenced by a persistent parent,
<emphasis>nothing
- special happens</emphasis> - the application should explicitly
delete
- the child if necessary - unless
<literal>cascade="delete-orphan"</literal>,
- in which case the "orphaned" child is deleted.
- </para>
- </listitem>
- </itemizedlist>
-
- <para>
- Finally, note that cascading of operations can be applied to an object graph
at
- <emphasis>call time</emphasis> or at <emphasis>flush
time</emphasis>. All operations,
- if enabled, are cascaded to associated entities reachable when the operation
is
- executed. However, <literal>save-upate</literal> and
<literal>delete-orphan</literal>
- are transitive for all associated entities reachable during flush of the
- <literal>Session</literal>.
- </para>
-
- </sect1>
-
- <sect1 id="objectstate-metadata">
- <title>Usando metadados</title>
-
- <para>
- O Hibernate requer um modelo muito rico a nível de metadados de todas as
entidades e tipos de
- valores. De tempos em tempos, este modelo é muito útil à própria aplicação.
Por exemplo, a
- aplicação pode usar o metadados do Hibernate que executa um algoritmo
"inteligente" que
- compreende quais objetos podem ser copiados (por exemplo, tipos de valores
mutáveis) ou
- não (por exemplo, tipos de valores imutáveis e, possivelmente, entidades
associadas).
- </para>
- <para>
- O Hibernate expõe o metadados via interfaces
<literal>ClassMetadata</literal>
- e <literal>CollectionMetadata</literal> e pela hierarquia
<literal>Type</literal>.
- Instâncias das interfaces de metadados podem ser obtidas a partir do
- <literal>SessionFactory</literal>.
- </para>
-
- <programlisting><![CDATA[Cat fritz = ......;
-ClassMetadata catMeta = sessionfactory.getClassMetadata(Cat.class);
-
-Object[] propertyValues = catMeta.getPropertyValues(fritz);
-String[] propertyNames = catMeta.getPropertyNames();
-Type[] propertyTypes = catMeta.getPropertyTypes();
-
-// get a Map of all properties which are not collections or associations
-Map namedValues = new HashMap();
-for ( int i=0; i<propertyNames.length; i++ ) {
- if ( !propertyTypes[i].isEntityType() && !propertyTypes[i].isCollectionType()
) {
- namedValues.put( propertyNames[i], propertyValues[i] );
- }
-}]]></programlisting>
-
- </sect1>
-
-</chapter>
-
+<chapter id="objectstate">
+ <title>Trabalhando com objetos</title>
+
+ <para>
+ O Hibernate é uma solução completa de mapeamento objeto/relacional que não apenas
+ poupa o desenvolvedor dos detalhes de baixo nível do sistema de gerenciamento do
+ banco de dados, mas também oferece um <emphasis>gerenciamento de estado
</emphasis>
+ para objetos. Isto é, ao contrário do gerenciamento de <literal>instruções
</literal>
+ SQL em camadas de persistência JDBC/SQL comuns, uma visão natural da persistência
+ orientada a objetos em aplicações Java.
+ </para>
+
+ <para>
+ Em outras palavras, desenvolvedores de aplicações Hibernate podem sempre pensar
em
+ relação ao <emphasis>estado</emphasis> de seus objetos, e não
necessariamente em
+ relação a execução de instruções SQL. Este parte é responsabilidade do Hibernate
e
+ é relevante aos desenvolvedores de aplicações apenas quando estão ajustando
+ a performance do sistema.
+ </para>
+
+ <sect1 id="objectstate-overview">
+ <title>Estado dos objetos no Hibernate</title>
+
+ <para>
+ O Hibernate define e suporta os seguintes estados de um objetos:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis>Transient</emphasis> - um objeto é transiente
se ele foi instanciando
+ usando apenas o operador <literal>new</literal>, e não
foi associado com uma
+ <literal>Session</literal> do Hibernate. Ele não terá uma
representação
+ persistente no banco de dados e nenhum identificador será atribuído
para ele.
+ Instâncias transientes serão destruídas pelo coletor de lixo se a
aplicação
+ não manter sua referência. Use uma
<literal>Session</literal> do Hibernate
+ para tornar o objeto persistente ( e deixe o Hibernate gerenciar as
+ instruções SQL que serão necessárias para executar esta transição).
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Persistent</emphasis> -– uma instância
persistente possui uma
+ representação no banco de dados e um identificador. Ele pode ter sido
salvo
+ ou carregado, assim, ele está por definição no escopo de uma
+ <literal>Session</literal>. O Hibernate irá detectar
qualquer mudança feita a
+ um objeto persistente e sincronizar o seu estado com o banco de dados
quando
+ completar a unidade de trabalho. Desenvolvedores não executam
instruções manuais
+ de <literal>UPDATE</literal>, ou instruções de
<literal>DELETE</literal>
+ quando o objeto deve ser passado para transiente.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Detached</emphasis> – uma instância desaclopada
é um objeto que
+ foi persistido, mas sua <literal>Session</literal> foi
fechada. A referência
+ ao objeto continua válida, é claro, e a instância destacada
desaclopada pode
+ ser acoplada a uma nova <literal>Session</literal> no
futuro, fazendo-o
+ ( e todas as modificações sofridas) persistente novamente. Essa
característica
+ possibilita um modelo de programação para unidades de trabalho que
rodam
+ durante muito tempo que requer um pensamento por tempo do usuário.
Podemos
+ chamar-las de <emphasis>transações da
aplicação</emphasis>, i.e. uma unidade
+ de trabalho do ponto de vista do usuário.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Agora iremos discutir os estados e suas transições ( e os métodos do
Hibernate que
+ disparam uma transição) em mais detalhes.
+ </para>
+
+ </sect1>
+
+ <sect1 id="objectstate-makingpersistent" revision="1">
+ <title>Tornando os objetos persistentes</title>
+
+ <para>
+ Instâncias recentemente instanciadas de uma classe persistente são
+ consideradas <emphasis>transientes </emphasis> pelo Hibernate.
+ Podemos tornar uma instância transiente em
<emphasis>persistente</emphasis>
+ associando-a a uma sessão:
+ </para>
+
+ <programlisting><![CDATA[DomesticCat fritz = new DomesticCat();
+fritz.setColor(Color.GINGER);
+fritz.setSex('M');
+fritz.setName("Fritz");
+Long generatedId = (Long) sess.save(fritz);]]></programlisting>
+
+ <para>
+ Se <literal>Cat</literal> possui um identificador gerado, o
identificador
+ é gerado e atribuído a <literal>cat</literal> quando
<literal>save()</literal>
+ for chamada. Se <literal>Cat</literal> possuir um identificador
+ <literal>Associado</literal>, ou uma chave composta, o
identificador deve ser
+ atribuído à instância de <literal>cat</literal> antes que
<literal>save()</literal>
+ seja chamado. Pode-se usar também <literal>persist()</literal>
ao invés de
+ <literal>save()</literal>, com a semântica definada no novo
esboço do EJB3.
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ <literal>persist()</literal> makes a transient instance persistent.
+ However, it doesn't guarantee that the identifier value will be assigned to
+ the persistent instance immediately, the assignment might happen at flush time.
+ <literal>persist()</literal> also guarantees that it will not execute an
+ <literal>INSERT</literal> statement if it is called outside of
transaction
+ boundaries. This is useful in long-running conversations with an extended
+ Session/persistence context.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>save()</literal> does guarantee to return an identifier. If an
INSERT
+ has to be executed to get the identifier ( e.g. "identity" generator, not
+ "sequence"), this INSERT happens immediately, no matter if you are inside
or
+ outside of a transaction. This is problematic in a long-running conversation
+ with an extended Session/persistence context.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Alternativamente, pode-se atribuir o identificador usando uma versão
+ sobrecarregada de <literal>save()</literal>.
+ </para>
+
+<programlisting><![CDATA[DomesticCat pk = new DomesticCat();
+pk.setColor(Color.TABBY);
+pk.setSex('F');
+pk.setName("PK");
+pk.setKittens( new HashSet() );
+pk.addKitten(fritz);
+sess.save( pk, new Long(1234) );]]></programlisting>
+
+ <para>
+ Se o objeto persistido possuir objetos associados (e.g. a coleção
+ <literal>kittens</literal> no exemplo anterior), esses objetos
podem ser
+ tornar persistente em qualquer ordem que se queira ao menos que se tenha uma
+ restrição <literal>NOT NULL</literal> em uma coluna de chave
estrangeira.
+ Nunca há risco de violação de restrições de chave estrangeira. Assim,
+ pode-se violar uma restrição <literal>NOT NULL</literal> se
+ <literal>save()</literal> for usada nos objetos em uma ordem
errada.
+ </para>
+
+ <para>
+ Geralmente você não deve se importar com esses detalhes, muito provavelmente
se
+ usará a característica de <emphasis>persistência transitiva
</emphasis> do Hibernate
+ para salvar os objetos associados automaticamente. Então, enquanto uma
restrição
+ <literal>NOT NULL</literal> não ocorrer – Hibernate tomará conta
de tudo.
+ Persistência transitiva será discutida futuramente nesse capítulo.
+ </para>
+
+ </sect1>
+
+ <sect1 id="objectstate-loading">
+ <title>Carregando o objetos</title>
+
+ <para>
+ O método <literal>load()</literal> de uma <literal>
Session</literal> nos
+ fornece um meio para recuperar uma instância persistente se o identificador
+ for conhecido. <literal>load()</literal> recebe uma classe do
objeto e carregará
+ o estado em uma instância mais recente dessa classe, no estado persistente.
+ </para>
+
+ <programlisting><![CDATA[Cat fritz = (Cat) sess.load(Cat.class,
generatedId);]]></programlisting>
+
+<programlisting><![CDATA[// you need to wrap primitive identifiers
+long id = 1234;
+DomesticCat pk = (DomesticCat) sess.load( DomesticCat.class, new Long(id)
);]]></programlisting>
+
+ <para>
+ Alternatively, you can load state into a given instance:
+Alternativamente, pode-se carregar um estado em uma instância dada:
+ </para>
+
+<programlisting><![CDATA[Cat cat = new DomesticCat();
+// load pk's state into cat
+sess.load( cat, new Long(pkId) );
+Set kittens = cat.getKittens();]]></programlisting>
+
+ <para>
+ Repare que <literal>load()</literal> irá lançar uma exceção
irrecuperável
+ se não houver na tabela no banco de dados um registro que combine.
+ Se a classe for mapeada com um proxy, <literal>load()</literal>
+ simplesmente retorna um proxy não inicializado e realmente não chamará
+ o banco de dados até que um método do proxy seja invocado.
+ Esse comportamento é muito útil se deseja-se criar uma associação
+ com um objeto sem que realmente o carregue do bando de dados.
+ Isto também permite que sejam carregadas múltiplas instâncias como um
+ grupo se <literal>batch-size</literal> estiver para o mapeamento
da
+ classe.
+ </para>
+
+ <para>
+ Se você não tiver certeza da existencia do registro no banco, você deve
+ usar o metodo <literal>get()</literal>, que consulta o banco
+ imediantamente e retorna um null se não existir o registro.
+ </para>
+
+ <programlisting><![CDATA[Cat cat = (Cat) sess.get(Cat.class, id);
+if (cat==null) {
+ cat = new Cat();
+ sess.save(cat, id);
+}
+return cat;]]></programlisting>
+
+ <para>
+ Também pode-se carregar um objeto usando <literal>SELECT ... FOR
UPDATE</literal>,
+ usando um <literal>LockMode</literal>. Veja a documentação da API
para maiores
+ informações.
+ </para>
+
+ <programlisting><![CDATA[Cat cat = (Cat) sess.get(Cat.class, id,
LockMode.UPGRADE);]]></programlisting>
+
+ <para>
+ Note that any associated instances or contained collections are
+ <emphasis>not</emphasis> selected <literal>FOR
UPDATE</literal>, unless you decide
+ to specify <literal>lock</literal> or
<literal>all</literal> as a
+ cascade style for the association.
+ </para>
+
+ <para>
+ O recarregamento de um objeto e todas as suas coleções é possível a qualquer
momento,
+ usando o método <literal>refresh()</literal>. Util quando as
triggers do banco de
+ dados são usados para inicializar algumas propriedades do objeto.
+ </para>
+
+ <programlisting><![CDATA[sess.save(cat);
+sess.flush(); //force the SQL INSERT
+sess.refresh(cat); //re-read the state (after the trigger
executes)]]></programlisting>
+
+ <para>
+ Uma importante questão geralmente aparece neste ponto: O quanto Hibernate
carrega
+ do banco de dados e quantos SQL <literal>SELECT</literal> ele
irá usar? Isto
+ depende da estratégia de <emphasis>recuperação</emphasis>usada e
explicada na
+ <xref linkend="performance-fetching"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="objectstate-querying" revision="1">
+ <title>Consultando</title>
+
+ <para>
+ Se o identificador do objeto que se está buscando não for conhecido,
+ uma consulta será necessária. O Hibernate suporta uma linguagem de consulta
+ (HQL) orientada a objetos fácil mas poderosa. Para criação via programação
+ de consultas, o Hibernate suporta características sofisticadas de consulta
+ por Critério e Exemplo (QBCe QBE). Pode-se também expressar a consulta
+ por meio de SQL nativa do banco de dados, com suporte opcional do Hibernate
+ para conversão do conjunto de reultados em objetos.
+ </para>
+
+ <sect2 id="objectstate-querying-executing"
revision="1">
+ <title>Executando consultas</title>
+
+ <para>
+ Consultas HQL e SQL nativa são representadas por uma instância de
<literal>org.hibernate.Query</literal>.
+ Esta interface oferece métodos para associação de parâmetros, tratamento
de conjunto de resultados,
+ e para a execução de consultas reais. Você pode obter uma
<literal>Query</literal> usando a
+ <literal>Session</literal> atual:
+ </para>
+
+ <programlisting><![CDATA[List cats = session.createQuery(
+ "from Cat as cat where cat.birthdate < ?")
+ .setDate(0, date)
+ .list();
+
+List mothers = session.createQuery(
+ "select mother from Cat as cat join cat.mother as mother where cat.name =
?")
+ .setString(0, name)
+ .list();
+
+List kittens = session.createQuery(
+ "from Cat as cat where cat.mother = ?")
+ .setEntity(0, pk)
+ .list();
+
+Cat mother = (Cat) session.createQuery(
+ "select cat.mother from Cat as cat where cat = ?")
+ .setEntity(0, izi)
+ .uniqueResult();]]
+
+Query mothersWithKittens = (Cat) session.createQuery(
+ "select mother from Cat as mother left join fetch mother.kittens");
+Set uniqueMothers = new HashSet(mothersWithKittens.list());]]></programlisting>
+
+ <para>
+ Geralmente uma consulta é executada ao invocar
<literal>list()</literal>,
+ o resultado da consulta será carregado completamente em uma coleção na
memória.
+ Instâncias de entidades recuperadas por uma consulta estão no estado
persistente.
+ O <literal>uniqueResult()</literal> oferece um atalho se você
souber de
+ previamente que a consulta retornará apenas um único objeto. Repare que
consultas
+ que fazem uso de buscas de coleções de forma ansiosa (eager) geralmente
retornam
+ duplicatas dos objetos raiz ( mas com suas coleções inicializadas ).
Pode-se
+ filtrar estas duplicatas através de um simples
<literal>Set</literal>.
+ </para>
+
+ <sect3 id="objectstate-querying-executing-iterate">
+ <title>Interagindo com resultados</title>
+
+ <para>
+ Ocasionalmente, deves-se ser capaz de atingir performances melhores
com
+ a execução de consultas usando o método
<literal>iterate()</literal>.
+ Geralmente isso será o caso esperado apenas se as instâncias dos
entidades
+ reais retornadas pela consulta já estiverem na sessão ou no caché de
segundo
+ nível. Caso elas ainda não tenham sido armazenadas,
<literal>iterate()</literal>
+ será mais devagar do que <literal>list()</literal> e pode
ser necessário vários
+ acessos ao banco de dados para um simples consulta, geralmente
<emphasis>1</emphasis>
+ para a seleção inicial que retorna apenas identificadores, e
<emphasis>n</emphasis>
+ consultas adicionais para inicializar as instâncias reais.
+ </para>
+
+ <programlisting><![CDATA[// 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;
+ }
+}]]></programlisting>
+ </sect3>
+
+ <sect3 id="objectstate-querying-executing-tuples">
+ <title>Consultas que retornam tuplas</title>
+
+ <para>
+ Algumas vezes as consultas do Hibernate retornam tuplas de objetos,
nesse caso
+ cada tupla é retornada como um array:
+ </para>
+
+ <programlisting><![CDATA[Iterator kittensAndMothers =
sess.createQuery(
+ "select kitten, mother from Cat kitten join kitten.mother mother")
+ .list()
+ .iterator();
+
+while ( kittensAndMothers.hasNext() ) {
+ Object[] tuple = (Object[]) kittensAndMothers.next();
+ Cat kitten = (Cat) tuple[0];
+ Cat mother = (Cat) tuple[1];
+ ....
+}]]></programlisting>
+
+ </sect3>
+
+ <sect3 id="objectstate-querying-executing-scalar"
revision="1">
+ <title>Resultados escalares</title>
+
+ <para>
+ Consultas devem especificar uma propriedade da classe na clausula
+ <literal>select</literal>. Elas também podem chamar
funções SQL de agregaçãos.
+ Propriedades ou agregações são considerados resultados agregados
+ ( e não entidades no estado persistente).
+ </para>
+
+ <programlisting><![CDATA[Iterator results = sess.createQuery(
+ "select cat.color, min(cat.birthdate), count(cat) from Cat cat " +
+ "group by cat.color")
+ .list()
+ .iterator();
+
+while ( results.hasNext() ) {
+ Object[] row = (Object[]) results.next();
+ Color type = (Color) row[0];
+ Date oldest = (Date) row[1];
+ Integer count = (Integer) row[2];
+ .....
+}]]></programlisting>
+
+ </sect3>
+
+ <sect3 id="objectstate-querying-executing-parameters">
+ <title>Bind parameters</title>
+
+ <para>
+ Methods on <literal>Query</literal> are provided for
binding values to
+ named parameters or JDBC-style <literal>?</literal>
parameters.
+ <emphasis>Contrary to JDBC, Hibernate numbers parameters from
zero.</emphasis>
+ Named parameters are identifiers of the form
<literal>:name</literal> in
+ the query string. The advantages of named parameters are:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ named parameters are insensitive to the order they occur in
the
+ query string
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ they may occur multiple times in the same query
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ they are self-documenting
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <programlisting><![CDATA[//named parameter (preferred)
+Query q = sess.createQuery("from DomesticCat cat where cat.name = :name");
+q.setString("name", "Fritz");
+Iterator cats = q.iterate();]]></programlisting>
+
+ <programlisting><![CDATA[//positional parameter
+Query q = sess.createQuery("from DomesticCat cat where cat.name = ?");
+q.setString(0, "Izi");
+Iterator cats = q.iterate();]]></programlisting>
+
+ <programlisting><![CDATA[//named parameter list
+List names = new ArrayList();
+names.add("Izi");
+names.add("Fritz");
+Query q = sess.createQuery("from DomesticCat cat where cat.name in
(:namesList)");
+q.setParameterList("namesList", names);
+List cats = q.list();]]></programlisting>
+
+ </sect3>
+
+ <sect3 id="objectstate-querying-executing-pagination">
+ <title>Pagination</title>
+
+ <para>
+ If you need to specify bounds upon your result set (the maximum
number of rows
+ you want to retrieve and / or the first row you want to retrieve) you
should
+ use methods of the <literal>Query</literal> interface:
+ </para>
+
+ <programlisting><![CDATA[Query q = sess.createQuery("from
DomesticCat cat");
+q.setFirstResult(20);
+q.setMaxResults(10);
+List cats = q.list();]]></programlisting>
+
+ <para>
+ Hibernate knows how to translate this limit query into the native
+ SQL of your DBMS.
+ </para>
+
+ </sect3>
+
+ <sect3 id="objectstate-querying-executing-scrolling">
+ <title>Scrollable iteration</title>
+
+ <para>
+ If your JDBC driver supports scrollable
<literal>ResultSet</literal>s, the
+ <literal>Query</literal> interface may be used to obtain
a
+ <literal>ScrollableResults</literal> object, which allows
flexible
+ navigation of the query results.
+ </para>
+
+ <programlisting><![CDATA[Query q = sess.createQuery("select
cat.name, cat from DomesticCat cat " +
+ "order by cat.name");
+ScrollableResults cats = q.scroll();
+if ( cats.first() ) {
+
+ // 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) );
+
+ // Now get the first page of cats
+ pageOfCats = new ArrayList();
+ cats.beforeFirst();
+ int i=0;
+ while( ( PAGE_SIZE > i++ ) && cats.next() ) pageOfCats.add( cats.get(1)
);
+
+}
+cats.close()]]></programlisting>
+
+ <para>
+ Note that an open database connection (and cursor) is required for
this
+ functionality, use
<literal>setMaxResult()</literal>/<literal>setFirstResult()</literal>
+ if you need offline pagination functionality.
+ </para>
+
+ </sect3>
+
+ <sect3 id="objectstate-querying-executing-named"
revision="1">
+ <title>Externalizing named queries</title>
+
+ <para>
+ You may also define named queries in the mapping document. (Remember
to use a
+ <literal>CDATA</literal> section if your query contains
characters that could
+ be interpreted as markup.)
+ </para>
+
+ <programlisting><![CDATA[<query
name="ByNameAndMaximumWeight"><![CDATA[
+ from eg.DomesticCat as cat
+ where cat.name = ?
+ and cat.weight > ?
+] ]></query>]]></programlisting>
+
+ <para>
+ Parameter binding and executing is done programatically:
+ </para>
+
+ <programlisting><![CDATA[Query q =
sess.getNamedQuery("ByNameAndMaximumWeight");
+q.setString(0, name);
+q.setInt(1, minWeight);
+List cats = q.list();]]></programlisting>
+
+ <para>
+ Note that the actual program code is independent of the query
language that
+ is used, you may also define native SQL queries in metadata, or
migrate
+ existing queries to Hibernate by placing them in mapping files.
+ </para>
+
+ <para>
+ Also note that a query declaration inside a
<literal><hibernate-mapping></literal>
+ element requires a global unique name for the query, while a query
declaration inside a
+ <literal><class></literal> element is made
unique automatically by prepending the
+ fully qualified name of the class, for example
+ <literal>eg.Cat.ByNameAndMaximumWeight</literal>.
+ </para>
+
+ </sect3>
+
+ </sect2>
+
+ <sect2 id="objectstate-filtering" revision="1">
+ <title>Filtering collections</title>
+ <para>
+ A collection <emphasis>filter</emphasis> is a special type of
query that may be applied to
+ a persistent collection or array. The query string may refer to
<literal>this</literal>,
+ meaning the current collection element.
+ </para>
+
+ <programlisting><![CDATA[Collection blackKittens =
session.createFilter(
+ pk.getKittens(),
+ "where this.color = ?")
+ .setParameter( Color.BLACK, Hibernate.custom(ColorUserType.class) )
+ .list()
+);]]></programlisting>
+
+ <para>
+ The returned collection is considered a bag, and it's a copy of the
given
+ collection. The original collection is not modified (this is contrary to
+ the implication of the name "filter", but consistent with
expected behavior).
+ </para>
+
+ <para>
+ Observe that filters do not require a <literal>from</literal>
clause (though they may have
+ one if required). Filters are not limited to returning the collection
elements themselves.
+ </para>
+
+ <programlisting><![CDATA[Collection blackKittenMates =
session.createFilter(
+ pk.getKittens(),
+ "select this.mate where this.color = eg.Color.BLACK.intValue")
+ .list();]]></programlisting>
+
+ <para>
+ Even an empty filter query is useful, e.g. to load a subset of elements
in a
+ huge collection:
+ </para>
+
+ <programlisting><![CDATA[Collection tenKittens =
session.createFilter(
+ mother.getKittens(), "")
+ .setFirstResult(0).setMaxResults(10)
+ .list();]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="objecstate-querying-criteria" revision="1">
+ <title>Criteria queries</title>
+
+ <para>
+ HQL is extremely powerful but some developers prefer to build queries
dynamically,
+ using an object-oriented API, rather than building query strings.
Hibernate provides
+ an intuitive <literal>Criteria</literal> query API for these
cases:
+ </para>
+
+ <programlisting><![CDATA[Criteria crit =
session.createCriteria(Cat.class);
+crit.add( Restrictions.eq( "color", eg.Color.BLACK ) );
+crit.setMaxResults(10);
+List cats = crit.list();]]></programlisting>
+
+ <para>
+ The <literal>Criteria</literal> and the associated
<literal>Example</literal>
+ API are discussed in more detail in <xref
linkend="querycriteria"/>.
+ </para>
+
+ </sect2>
+
+ <sect2 id="objectstate-querying-nativesql"
revision="2">
+ <title>Queries in native SQL</title>
+
+ <para>
+ You may express a query in SQL, using
<literal>createSQLQuery()</literal> and
+ let Hibernate take care of the mapping from result sets to objects. Note
+ that you may at any time call
<literal>session.connection()</literal> and
+ use the JDBC <literal>Connection</literal> directly. If you
chose to use the
+ Hibernate API, you must enclose SQL aliases in braces:
+ </para>
+
+ <programlisting><![CDATA[List cats =
session.createSQLQuery("SELECT {cat.*} FROM CAT {cat} WHERE ROWNUM<10")
+ .addEntity("cat", Cat.class)
+.list();]]></programlisting>
+
+ <programlisting><![CDATA[List cats = session.createSQLQuery(
+ "SELECT {cat}.ID AS {cat.id}, {cat}.SEX AS {cat.sex}, " +
+ "{cat}.MATE AS {cat.mate}, {cat}.SUBCLASS AS {cat.class}, ... " +
+ "FROM CAT {cat} WHERE ROWNUM<10")
+ .addEntity("cat", Cat.class)
+.list()]]></programlisting>
+
+ <para>
+ SQL queries may contain named and positional parameters, just like
Hibernate queries.
+ More information about native SQL queries in Hibernate can be found in
+ <xref linkend="querysql"/>.
+ </para>
+
+ </sect2>
+
+ </sect1>
+
+ <sect1 id="objectstate-modifying" revision="1">
+ <title>Modifying persistent objects</title>
+
+ <para>
+ <emphasis>Transactional persistent instances</emphasis> (ie.
objects loaded, saved, created or
+ queried by the <literal>Session</literal>) may be manipulated by
the application
+ and any changes to persistent state will be persisted when the
<literal>Session</literal>
+ is <emphasis>flushed</emphasis> (discussed later in this
chapter). There is no need
+ to call a particular method (like <literal>update()</literal>,
which has a different
+ purpose) to make your modifications persistent. So the most straightforward
way to update
+ the state of an object is to <literal>load()</literal> it,
+ and then manipulate it directly, while the
<literal>Session</literal> is open:
+ </para>
+
+ <programlisting><![CDATA[DomesticCat cat = (DomesticCat) sess.load(
Cat.class, new Long(69) );
+cat.setName("PK");
+sess.flush(); // changes to cat are automatically detected and
persisted]]></programlisting>
+
+ <para>
+ Sometimes this programming model is inefficient since it would require both
an SQL
+ <literal>SELECT</literal> (to load an object) and an SQL
<literal>UPDATE</literal>
+ (to persist its updated state) in the same session. Therefore Hibernate
offers an
+ alternate approach, using detached instances.
+ </para>
+
+ <para>
+ <emphasis>Note that Hibernate does not offer its own API for direct
execution of
+ <literal>UPDATE</literal> or
<literal>DELETE</literal> statements. Hibernate is a
+ <emphasis>state management</emphasis> service, you don't have
to think in
+ <emphasis>statements</emphasis> to use it. JDBC is a perfect API
for executing
+ SQL statements, you can get a JDBC <literal>Connection</literal>
at any time
+ by calling <literal>session.connection()</literal>. Furthermore,
the notion
+ of mass operations conflicts with object/relational mapping for online
+ transaction processing-oriented applications. Future versions of Hibernate
+ may however provide special mass operation functions. See <xref
linkend="batch"/>
+ for some possible batch operation tricks.</emphasis>
+ </para>
+
+ </sect1>
+
+ <sect1 id="objectstate-detached" revision="2">
+ <title>Modifying detached objects</title>
+
+ <para>
+ Many applications need to retrieve an object in one transaction, send it to
the
+ UI layer for manipulation, then save the changes in a new transaction.
+ Applications that use this kind of approach in a high-concurrency
environment
+ usually use versioned data to ensure isolation for the "long" unit
of work.
+ </para>
+
+ <para>
+ Hibernate supports this model by providing for reattachment of detached
instances
+ using the <literal>Session.update()</literal> or
<literal>Session.merge()</literal>
+ methods:
+ </para>
+
+ <programlisting><![CDATA[// in the first session
+Cat cat = (Cat) firstSession.load(Cat.class, catId);
+Cat potentialMate = new Cat();
+firstSession.save(potentialMate);
+
+// in a higher layer of the application
+cat.setMate(potentialMate);
+
+// later, in a new session
+secondSession.update(cat); // update cat
+secondSession.update(mate); // update mate]]></programlisting>
+
+ <para>
+ If the <literal>Cat</literal> with identifier
<literal>catId</literal> had already
+ been loaded by <literal>secondSession</literal> when the
application tried to
+ reattach it, an exception would have been thrown.
+ </para>
+
+ <para>
+ Use <literal>update()</literal> if you are sure that the session
does
+ not contain an already persistent instance with the same identifier, and
+ <literal>merge()</literal> if you want to merge your
modifications at any time
+ without consideration of the state of the session. In other words,
<literal>update()</literal>
+ is usually the first method you would call in a fresh session, ensuring that
+ reattachment of your detached instances is the first operation that is
executed.
+ </para>
+
+ <para>
+ The application should individually <literal>update()</literal>
detached instances
+ reachable from the given detached instance if and
<emphasis>only</emphasis> if it wants
+ their state also updated. This can be automated of course, using
<emphasis>transitive
+ persistence</emphasis>, see <xref
linkend="objectstate-transitive"/>.
+ </para>
+
+ <para>
+ The <literal>lock()</literal> method also allows an application
to reassociate
+ an object with a new session. However, the detached instance has to be
unmodified!
+ </para>
+
+ <programlisting><![CDATA[//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);]]></programlisting>
+
+ <para>
+ Note that <literal>lock()</literal> can be used with various
+ <literal>LockMode</literal>s, see the API documentation and the
+ chapter on transaction handling for more information. Reattachment is not
+ the only usecase for <literal>lock()</literal>.
+ </para>
+
+ <para>
+ Other models for long units of work are discussed in <xref
linkend="transactions-optimistic"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="objectstate-saveorupdate">
+ <title>Automatic state detection</title>
+
+ <para>
+ Hibernate users have requested a general purpose method that either saves a
+ transient instance by generating a new identifier or updates/reattaches
+ the detached instances associated with its current identifier.
+ The <literal>saveOrUpdate()</literal> method implements this
functionality.
+ </para>
+
+ <programlisting><![CDATA[// in the first session
+Cat cat = (Cat) firstSession.load(Cat.class, catID);
+
+// in a higher tier of the application
+Cat mate = new Cat();
+cat.setMate(mate);
+
+// later, in a new session
+secondSession.saveOrUpdate(cat); // update existing state (cat has a non-null id)
+secondSession.saveOrUpdate(mate); // save the new instance (mate has a null
id)]]></programlisting>
+
+ <para>
+ The usage and semantics of <literal>saveOrUpdate()</literal>
seems to be confusing
+ for new users. Firstly, so long as you are not trying to use instances from
one session
+ in another new session, you should not need to use
<literal>update()</literal>,
+ <literal>saveOrUpdate()</literal>, or
<literal>merge()</literal>. Some whole
+ applications will never use either of these methods.
+ </para>
+
+ <para>
+ Usually <literal>update()</literal> or
<literal>saveOrUpdate()</literal> are used in
+ the following scenario:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ the application loads an object in the first session
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ the object is passed up to the UI tier
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ some modifications are made to the object
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ the object is passed back down to the business logic tier
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ the application persists these modifications by calling
+ <literal>update()</literal> in a second session
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ <literal>saveOrUpdate()</literal> does the following:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ if the object is already persistent in this session, do nothing
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ if another object associated with the session has the same
identifier,
+ throw an exception
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ if the object has no identifier property,
<literal>save()</literal> it
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ if the object's identifier has the value assigned to a newly
instantiated
+ object, <literal>save()</literal> it
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ if the object is versioned (by a
<literal><version></literal> or
+ <literal><timestamp></literal>), and the
version property value
+ is the same value assigned to a newly instantiated object,
+ <literal>save()</literal> it
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ otherwise <literal>update()</literal> the object
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ and <literal>merge()</literal> is very different:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ if there is a persistent instance with the same identifier currently
+ associated with the session, copy the state of the given object onto
+ the persistent instance
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ if there is no persistent instance currently associated with the
session,
+ try to load it from the database, or create a new persistent
instance
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ the persistent instance is returned
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ the given instance does not become associated with the session, it
+ remains detached
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ </sect1>
+
+ <sect1 id="objectstate-deleting" revision="1">
+ <title>Deleting persistent objects</title>
+
+ <para>
+ <literal>Session.delete()</literal> will remove an object's
state from the database.
+ Of course, your application might still hold a reference to a deleted
object.
+ It's best to think of <literal>delete()</literal> as making a
persistent instance
+ transient.
+ </para>
+
+ <programlisting><![CDATA[sess.delete(cat);]]></programlisting>
+
+ <para>
+ You may delete objects in any order you like, without risk of foreign key
+ constraint violations. It is still possible to violate a <literal>NOT
+ NULL</literal> constraint on a foreign key column by deleting objects
in
+ the wrong order, e.g. if you delete the parent, but forget to delete the
+ children.
+ </para>
+
+ </sect1>
+
+ <sect1 id="objectstate-replicating" revision="1">
+ <title>Replicating object between two different datastores</title>
+
+ <para>
+ It is occasionally useful to be able to take a graph of persistent instances
+ and make them persistent in a different datastore, without regenerating
identifier
+ values.
+ </para>
+
+ <programlisting><![CDATA[//retrieve a cat from one database
+Session session1 = factory1.openSession();
+Transaction tx1 = session1.beginTransaction();
+Cat cat = session1.get(Cat.class, catId);
+tx1.commit();
+session1.close();
+
+//reconcile with a second database
+Session session2 = factory2.openSession();
+Transaction tx2 = session2.beginTransaction();
+session2.replicate(cat, ReplicationMode.LATEST_VERSION);
+tx2.commit();
+session2.close();]]></programlisting>
+
+ <para>
+ The <literal>ReplicationMode</literal> determines how
<literal>replicate()</literal>
+ will deal with conflicts with existing rows in the database.
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ <literal>ReplicationMode.IGNORE</literal> - ignore the
object when there is
+ an existing database row with the same identifier
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>ReplicationMode.OVERWRITE</literal> - overwrite
any existing database
+ row with the same identifier
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>ReplicationMode.EXCEPTION</literal> - throw an
exception if there is
+ an existing database row with the same identifier
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>ReplicationMode.LATEST_VERSION</literal> -
overwrite the row if its
+ version number is earlier than the version number of the object, or
ignore
+ the object otherwise
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Usecases for this feature include reconciling data entered into different
database
+ instances, upgrading system configuration information during product
upgrades,
+ rolling back changes made during non-ACID transactions and more.
+ </para>
+
+ </sect1>
+
+ <sect1 id="objectstate-flushing">
+ <title>Flushing the Session</title>
+
+ <para>
+ From time to time the <literal>Session</literal> will execute the
SQL statements
+ needed to synchronize the JDBC connection's state with the state of
objects held in
+ memory. This process, <emphasis>flush</emphasis>, occurs by
default at the following
+ points
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ before some query executions
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ from
<literal>org.hibernate.Transaction.commit()</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ from <literal>Session.flush()</literal>
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ The SQL statements are issued in the following order
+ </para>
+
+ <orderedlist spacing="compact">
+ <listitem>
+ <para>
+ all entity insertions, in the same order the corresponding objects
+ were saved using <literal>Session.save()</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ all entity updates
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ all collection deletions
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ all collection element deletions, updates and insertions
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ all collection insertions
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ all entity deletions, in the same order the corresponding objects
+ were deleted using <literal>Session.delete()</literal>
+ </para>
+ </listitem>
+ </orderedlist>
+
+ <para>
+ (An exception is that objects using <literal>native</literal> ID
generation are
+ inserted when they are saved.)
+ </para>
+
+ <para>
+ Except when you explicity <literal>flush()</literal>, there are
absolutely no
+ guarantees about <emphasis>when</emphasis> the
<literal>Session</literal> executes
+ the JDBC calls, only the <emphasis>order</emphasis> in which they
are executed.
+ However, Hibernate does guarantee that the
<literal>Query.list(..)</literal>
+ will never return stale data; nor will they return the wrong data.
+ </para>
+
+ <para>
+ It is possible to change the default behavior so that flush occurs less
frequently.
+ The <literal>FlushMode</literal> class defines three different
modes: only flush
+ at commit time (and only when the Hibernate
<literal>Transaction</literal> API
+ is used), flush automatically using the explained routine, or never flush
unless
+ <literal>flush()</literal> is called explicitly. The last mode is
useful for long running
+ units of work, where a <literal>Session</literal> is kept open
and disconnected for
+ a long time (see <xref
linkend="transactions-optimistic-longsession"/>).
+ </para>
+
+ <programlisting><![CDATA[sess = sf.openSession();
+Transaction tx = sess.beginTransaction();
+sess.setFlushMode(FlushMode.COMMIT); // allow queries to return stale state
+
+Cat izi = (Cat) sess.load(Cat.class, id);
+izi.setName(iznizi);
+
+// might return stale data
+sess.find("from Cat as cat left outer join cat.kittens kitten");
+
+// change to izi is not flushed!
+...
+tx.commit(); // flush occurs
+sess.close();]]></programlisting>
+
+ <para>
+ 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 <xref linkend="transactions"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="objectstate-transitive" revision="1">
+ <title>Transitive persistence</title>
+
+ <para>
+ It is quite cumbersome to save, delete, or reattach individual objects,
+ especially if you deal with a graph of associated objects. A common case is
+ a parent/child relationship. Consider the following example:
+ </para>
+
+ <para>
+ If the children in a parent/child relationship would be value typed (e.g. a
collection
+ of addresses or strings), their life cycle would depend on the parent and no
+ further action would be required for convenient "cascading" of
state changes.
+ When the parent is saved, the value-typed child objects are saved as
+ well, when the parent is deleted, the children will be deleted, etc. This
+ even works for operations such as the removal of a child from the
collection;
+ Hibernate will detect this and, since value-typed objects can't have
shared
+ references, delete the child from the database.
+ </para>
+
+ <para>
+ Now consider the same scenario with parent and child objects being entities,
+ not value-types (e.g. categories and items, or parent and child cats).
Entities
+ have their own life cycle, support shared references (so removing an entity
from
+ the collection does not mean it can be deleted), and there is by default no
+ cascading of state from one entity to any other associated entities.
Hibernate
+ does not implement <emphasis>persistence by
reachability</emphasis> by default.
+ </para>
+
+ <para>
+ For each basic operation of the Hibernate session - including
<literal>persist(), merge(),
+ saveOrUpdate(), delete(), lock(), refresh(), evict(),
replicate()</literal> - there is a
+ corresponding cascade style. Respectively, the cascade styles are named
<literal>create,
+ merge, save-update, delete, lock, refresh, evict, replicate</literal>.
If you want an
+ operation to be cascaded along an association, you must indicate that in the
mapping
+ document. For example:
+ </para>
+
+ <programlisting><![CDATA[<one-to-one name="person"
cascade="persist"/>]]></programlisting>
+
+ <para>
+ Cascade styles my be combined:
+ </para>
+
+ <programlisting><![CDATA[<one-to-one name="person"
cascade="persist,delete,lock"/>]]></programlisting>
+
+ <para>
+ You may even use <literal>cascade="all"</literal> to
specify that <emphasis>all</emphasis>
+ operations should be cascaded along the association. The default
<literal>cascade="none"</literal>
+ specifies that no operations are to be cascaded.
+ </para>
+
+ <para>
+ A special cascade style, <literal>delete-orphan</literal>,
applies only to one-to-many
+ associations, and indicates that the <literal>delete()</literal>
operation should
+ be applied to any child object that is removed from the association.
+ </para>
+
+
+ <para>
+ Recommendations:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ It doesn't usually make sense to enable cascade on a
<literal><many-to-one></literal>
+ or <literal><many-to-many></literal>
association. Cascade is often useful for
+ <literal><one-to-one></literal> and
<literal><one-to-many></literal>
+ associations.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If the child object's lifespan is bounded by the lifespan of the
parent
+ object, make it a <emphasis>life cycle object</emphasis>
by specifying
+
<literal>cascade="all,delete-orphan"</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Otherwise, you might not need cascade at all. But if you think that
you will often be
+ working with the parent and children together in the same
transaction, and you want to save
+ yourself some typing, consider using
<literal>cascade="persist,merge,save-update"</literal>.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Mapping an association (either a single valued association, or a collection)
with
+ <literal>cascade="all"</literal> marks the association
as a
+ <emphasis>parent/child</emphasis> style relationship where
save/update/delete of the
+ parent results in save/update/delete of the child or children.
+ </para>
+ <para>
+ Futhermore, a mere reference to a child from a persistent parent will result
in
+ save/update of the child. This metaphor is incomplete, however. A child which
becomes
+ unreferenced by its parent is <emphasis>not</emphasis>
automatically deleted, except
+ in the case of a <literal><one-to-many></literal>
association mapped with
+ <literal>cascade="delete-orphan"</literal>. The precise
semantics of cascading
+ operations for a parent/child relationship are as follows:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ If a parent is passed to <literal>persist()</literal>,
all children are passed to
+ <literal>persist()</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If a parent is passed to <literal>merge()</literal>, all
children are passed to
+ <literal>merge()</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If a parent is passed to <literal>save()</literal>,
<literal>update()</literal> or
+ <literal>saveOrUpdate()</literal>, all children are
passed to <literal>saveOrUpdate()</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If a transient or detached child becomes referenced by a persistent
parent,
+ it is passed to <literal>saveOrUpdate()</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If a parent is deleted, all children are passed to
<literal>delete()</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If a child is dereferenced by a persistent parent,
<emphasis>nothing
+ special happens</emphasis> - the application should explicitly
delete
+ the child if necessary - unless
<literal>cascade="delete-orphan"</literal>,
+ in which case the "orphaned" child is deleted.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Finally, note that cascading of operations can be applied to an object graph
at
+ <emphasis>call time</emphasis> or at <emphasis>flush
time</emphasis>. All operations,
+ if enabled, are cascaded to associated entities reachable when the operation
is
+ executed. However, <literal>save-upate</literal> and
<literal>delete-orphan</literal>
+ are transitive for all associated entities reachable during flush of the
+ <literal>Session</literal>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="objectstate-metadata">
+ <title>Usando metadados</title>
+
+ <para>
+ O Hibernate requer um modelo muito rico a nível de metadados de todas as
entidades e tipos de
+ valores. De tempos em tempos, este modelo é muito útil à própria aplicação.
Por exemplo, a
+ aplicação pode usar o metadados do Hibernate que executa um algoritmo
"inteligente" que
+ compreende quais objetos podem ser copiados (por exemplo, tipos de valores
mutáveis) ou
+ não (por exemplo, tipos de valores imutáveis e, possivelmente, entidades
associadas).
+ </para>
+ <para>
+ O Hibernate expõe o metadados via interfaces
<literal>ClassMetadata</literal>
+ e <literal>CollectionMetadata</literal> e pela hierarquia
<literal>Type</literal>.
+ Instâncias das interfaces de metadados podem ser obtidas a partir do
+ <literal>SessionFactory</literal>.
+ </para>
+
+ <programlisting><![CDATA[Cat fritz = ......;
+ClassMetadata catMeta = sessionfactory.getClassMetadata(Cat.class);
+
+Object[] propertyValues = catMeta.getPropertyValues(fritz);
+String[] propertyNames = catMeta.getPropertyNames();
+Type[] propertyTypes = catMeta.getPropertyTypes();
+
+// get a Map of all properties which are not collections or associations
+Map namedValues = new HashMap();
+for ( int i=0; i<propertyNames.length; i++ ) {
+ if ( !propertyTypes[i].isEntityType() && !propertyTypes[i].isCollectionType()
) {
+ namedValues.put( propertyNames[i], propertyValues[i] );
+ }
+}]]></programlisting>
+
+ </sect1>
+
+</chapter>
+
Modified:
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/toolset_guide.xml
===================================================================
---
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/toolset_guide.xml 2007-10-26
00:46:38 UTC (rev 14135)
+++
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/toolset_guide.xml 2007-10-26
00:48:48 UTC (rev 14136)
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="toolsetguide" revision="2">
+<chapter id="toolsetguide" revision="2">
<title>Toolset Guide</title>
<para>
Modified: core/trunk/documentation/manual/pt-BR/src/main/docbook/content/transactions.xml
===================================================================
---
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/transactions.xml 2007-10-26
00:46:38 UTC (rev 14135)
+++
core/trunk/documentation/manual/pt-BR/src/main/docbook/content/transactions.xml 2007-10-26
00:48:48 UTC (rev 14136)
@@ -1,1150 +1,1148 @@
<?xml version='1.0' encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="transactions" revision="2">
- <title>Transações e Concorrência</title>
-
- <para>
- O ponto o mais importante sobre o Hibernate e o controle de concorrência é que é
muito
- fácil de ser compreendido. O Hibernate usa diretamente conexões de JDBC e
recursos de
- JTA sem adicionar nenhum comportamento de bloqueio a mais. Nós altamente
recomendamos
- que você gaste algum tempo com o JDBC, o ANSI e a especificação de isolamento de
transação
- de seu sistema de gerência da base de dados.
- </para>
-
- <para>
- O Hibernate não bloqueia objetos na memória. Sua aplicação pode esperar o
comportamento
- tal qual definido pelo nível de isolamento de suas transações de banco de dados.
- Note que graças ao <literal>Session</literal>, que também é um cache
de escopo de
- transação, o Hibernate fornece leituras repetíveis para procurar por
identificadores
- e consultas de entidade (não pesquisas de relatórios que retornam valores
escalares).
- </para>
-
- <para>
- Além do versionamento para o controle automático de concorrência otimista, o
Hibernate
- oferece também uma API (menor) para bloqueio pessimista de linhas usando a
sintaxe
- <literal>SELECT FOR UPDATE</literal>. O controle de concorrência
otimista e esta
- API são discutidos mais tarde neste capítulo.
- </para>
-
- <para>
- Nós começamos a discussão do controle de concorrência no Hibernate com a
granularidade
- do <literal>Configuration</literal>,
<literal>SessionFactory</literal>, e
- <literal>Session</literal>, além de transações de base de dados e
conversações longas.
- </para>
-
- <sect1 id="transactions-basics" revision="1">
- <title>Session e escopos de transações</title>
-
- <para>
- Um <literal>SessionFactory</literal> é objeto threadsafe
compartilhado por
- todas as threads da aplicação que consome muitos recursos na sua criação.
- É criado uma unica vez no inicio da execução da aplicação a partir da
- instância de uma <literal>Configuration</literal>.
- </para>
-
- <para>
- Uma <literal>Session</literal> é um objeto de baixo custo de
criação, não é threadsafe,
- deve ser usado uma vez, para uma única requisição, uma conversação, uma única
unidade
- do trabalho e então deve ser descartado. Um
<literal>Session</literal> não obterá um
- JDBC <literal>Connection</literal> (ou um
<literal>Datasource</literal>) a menos que
- necessite, conseqüentemente não consome nenhum recurso até ser usado.
- </para>
-
- <para>
- Para completar, você também tem que pensar sobre as transações de base de
dados.
- Uma transação tem que ser tão curta quanto possível, para reduzir a disputa
pelo
- bloqueio na base de dados. Transações longas impedirão que sua aplicação
escale a
- carga altamente concorrente. Por isso, em um projeto raramente é para manter
- uma transação de base de dados aberta durante o tempo que o usuário pensa,
- até que a unidade do trabalho esteja completa.
- </para>
-
- <para>
- Qual é o escopo de uma unidade de trabalho? Pode uma únicoa
<literal>Session</literal>
- do Hibernate gerenciar diversas transações ou é esta um o relacionamento
um-para-um dos
- escopos? Quando deve você abrir e fechar uma
<literal>Session</literal> e como você
- demarca os limites da transação?
- </para>
-
- <sect2 id="transactions-basics-uow" revision="1">
- <title>Unidade de trabalho</title>
-
- <para>
- Primeiro, não use o antipattern
<emphasis>sessão-por-operação</emphasis>,
- isto é, não abra e não feche uma <literal>Session</literal>
para cada simples chamada
- ao banco de de dados em uma única thread! Naturalmente, o mesmo é
verdadeiro para
- transações. As chamadas a banco de dados em uma aplicação são feitas
usando uma
- seqüência planejada, elas são agrupadas em unidades de trabalho atômicas.
- (Veja que isso também significa que um auto-commit depois de cada
sentença SQL é
- inútil em uma aplicação, esta modalidade é ideal para o trabalho ad hoc
do console
- do SQL. O Hibernate impede, ou espera que o servidor de aplicação impessa
isso,
- o uso da modalidade de auto-commit.) As transações nunca são opcionais,
toda a
- comunicação com um banco de dados tem que ocorrer dentro de uma
transação, não
- importa se você vai ler ou escrever dados. Como explicado, o
comportamento auto-commit
- para leitura de dados deve ser evitado, como muitas transações pequenas
são
- improváveis de executar melhor do que uma unidade claramente definida do
trabalho. A
- última opção também muito mais manutenível e extensível.
- </para>
-
- <para>
- O pattern mais comum em uma aplicação multi-usuário cliente/servidor é
- <emphasis>sessão-por-requisição</emphasis>. Neste modelo, uma
requisição do cliente é
- enviada ao servidor (onde a camada de persistência do Hibernate roda),
uma
- <literal>Session</literal> nova do Hibernate é aberta, e
todas as operações da base de
- dados são executadas nesta unidade do trabalho. Logo que o trabalho for
completado
- (e a resposta para o cliente for preparada), a sessão é descarregad e
fechada.
- Você usaria também uma única transação de base de dados para servir às
requisições
- dos clientes, começando e commitando-o quando você abre e fecha a
<literal>Session</literal>.
- O relacionamento entre os dois é um-para-um e este modelo é um ajuste
perfeito para muitas
- aplicações.
- </para>
-
- <para>
- O desafio encontra-se na implementação. O Hibernate fornece gerência
integrada da "sessão atual"
- para simplificar este pattern. Tudo que você tem que fazer é iniciar uma
transação quando uma
- requisição tem que ser processada e termina a transação antes que a
resposta seja enviada ao
- cliente. Você pode fazer onde quiser, soluções comuns são
<literal>ServletFilter</literal>,
- interceptador AOP com um pointcut (ponto de corte) nos métodos de serviço
ou em um
- container de proxy/interceptação. Um container de EJB é uma maneira
padronizada para
- implementar aspectos cross-cutting tais como a demarcação da transação em
EJB session beans,
- declarativamente com CMT. Se você se decidir usar demarcação programática
de transação,
- de preferencia a API <literal>Transaction</literal> do
Hibernate mostrada mais adiante neste
- capítulo, para fácilidade no uso e portabilidade de código.
- </para>
-
- <para>
- Seu código de aplicação pode acessar a "sessão atual" para
processar a requisição
- fazendo uma chamada simples a
<literal>sessionFactory.getCurrentSession()</literal> em
- qualquer lugar e com a frequencia necessária. Você sempre conseguirá uma
- <literal>Session</literal> limitada a transação atual. Isto
tem que ser configurado
- para recurso local ou os ambientes JTA. Veja <xref
linkend="architecture-current-session"/>.
- </para>
-
- <para>
- Às vezes é conveniente estender o escopo de uma
<literal>Session</literal> e de
- uma transação do banco de dados até que a "visão esteja
renderizada". É especialmente
- útil em aplicações servlet que utilizam uma fase de rendenderização
separada depois
- que a requisição ter sido processada. Estendendo a transação até que
renderização da
- visão esteja completa é fácil de fazer se você implementar seu próprio
interceptador.
- Entretanto, não se pode fazer facilmente se você confiar em EJBs com
transações
- gerenciadas por contêiner, porque uma transação será terminada quando um
método de
- EJB retornar, antes da renderização de toda visão puder começar.
- Veja o website e o fórum do Hibernate para dicas e exemplos em torno
deste
- pattern <emphasis>Open Session in View</emphasis>.
-
- </para>
-
- </sect2>
-
- <sect2 id="transactions-basics-apptx" revision="1">
- <title>Longas conversações</title>
-
- <para>
- O pattern sessão-por-requisição não é o único conceito útil que você pode
usar ao projetar
- unidades de trabalho. Muitos processos de negócio requerem uma totalidade
de séries de
- interações com o usuário intercaladas com acessos a uma base de dados. Em
aplicações web
- e corporativas não é aceitável para uma transação atrapalhe uma interação
do usuário.
- Considere o seguinte exemplo:
- </para>
-
- <itemizedlist>
- <listitem>
- <para>
- A primeira tela de um diálogo abre os dados carregado pelo
usuário em através de
- <literal>Session</literal> e transação particulares.
O usuário está livre
- modificar os objetos.
- </para>
- </listitem>
- <listitem>
- <para>
- O usuário clica em "Salvar" após 5 minutos e espera
suas modificações serem persistidas;
- espera também que ele era a única pessoa que edita esta
informação e que nenhuma
- modificação conflitante possa ocorrer.
- </para>
- </listitem>
- </itemizedlist>
-
- <para>
- Nós chamamos esta unidade de trabalho, do ponto da visão do usuário,
executando uma
- longa <emphasis>conversação</emphasis> (ou
<emphasis>transação da aplicação</emphasis>).
- Há muitas maneiras de você pode implementar em sua aplicação.
-
- </para>
-
- <para>
- Uma primeira implementação simples pode manter
a<literal>Session</literal> e a transação
- aberta durante o tempo de interação do usuário, com bloqueios na base de
dados para impedir
- a modificação concorrente e para garantir o isolamento e a atomicidade.
Esse é naturalmente
- um anti-pattern, desde que a disputa do bloqueio não permitiria o
escalonameneto da
- aplicação com o número de usuários concorrentes.
- </para>
-
- <para>
- Claramente, nós temos que usar diversas transações para implementar a
conversação.
- Neste caso, Manter o isolamento dos processos de negócio torna-se
responsabilidade
- parcial da camada da aplicação. Uma única conversação geralmente usa
diversas transações.
- Ela será atômica se somente uma destas transações (a última) armazenar
os
- dados atualizados, todas as outras simplesmente leram os dados (por
exemplo em um
- diálogo do estilo wizard que mede diversos ciclos de
requisição/resposta). Isto é mais
- fácil de implementar do que pode parecer, especialmente se você usar as
- características do Hibernate:
- </para>
-
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>Versionamento automático</emphasis> - O
Hibernate pode fazer o
- controle automático de concorrência otimista para você, ele pode
- automaticamente detectar se uma modificação concorrente
- ocorreu durante o tempo de interação do usuário. Geralmente nós
verificamos
- somente no fim da conversação.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>Detached Objects</emphasis>- se você se
decidir usar o já discutido
- pattern <emphasis>session-per-request</emphasis>,
todas as instâncias carregadas
- estarão no estado destacado durante o tempo em que o usuário
estiver pensando.
- O Hibernate permite que você reatache os objetos e persita as
modificações,
- esse pattern é chamado
-
<emphasis>session-per-request-with-detached-objects</emphasis>.
- É usado versionamento automatico para isolar as modificações
concorrentes.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>Extended (or Long) Session</emphasis> A
<literal>Session</literal>
- do Hibernate pode ser desligada da conexão básica do JDBC depois
que a
- transação foi commitada e ser reconectado quando uma nova
requisição do
- cliente ocorrer. Este pattern é conhecido como
- <emphasis>session-per-conversation</emphasis> e faz o
reatamento uniforme
- desnecessário. Versionamento automático é usado para isolar
modificações
- concorrentes e a
<emphasis>session-per-conversation</emphasis> usualmente
- não é permitido para ser nivelado automaticamente, e sim
explicitamente.
- </para>
- </listitem>
- </itemizedlist>
-
- <para>
- Ambos
<emphasis>session-per-request-with-detached-objects</emphasis> e
- <emphasis>session-per-conversation</emphasis> possuem
vantagens e desvantagens,
- nos discutiremos mais tarde neste capítulo no contexto do controle de
- concorrência otimista.
- </para>
-
- </sect2>
-
- <sect2 id="transactions-basics-identity">
- <title>Considerando a identidade do objeto</title>
-
- <para>
- Uma aplicação pode acessar concorrentemente o mesmo estado persistente em
duas
- <literal>Session</literal>s diferentes. Entretanto, uma
instância de uma classe
- persistente nunca é compartilhada entre duas instâncias
<literal>Session</literal>.
- Por tanto, há duas noções diferentes da identidade:
- </para>
-
- <variablelist spacing="compact">
- <varlistentry>
- <term>Identidade da base de dados</term>
- <listitem>
- <para>
- <literal>foo.getId().equals( bar.getId()
)</literal>
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Identidade da JVM</term>
- <listitem>
- <para>
- <literal>foo==bar</literal>
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
-
- <para>
- Então para os objetos acoplados a um
<literal>Session</literal> em <literal>particular </literal>
- (isto é no escopo de um <literal>Session</literal>), as duas
noções são equivalentes e a
- identidade da JVM para a identidade da base de dados é garantida pelo
Hibernate. Entretanto,
- quando a aplicação pode acessar concorrentemente o "mesmo"
objeto do negócio (identidade
- persistente) em duas sessões diferentes, as duas instâncias serão
realmente "diferentes"
- (identidade de JVM). Os conflitos são resolvidos usando (versionamento
automático) no
- flush/commit, usando abordagem otimista.
-
- </para>
-
- <para>
- Este caminho deixa o Hibernate e o banco dedados se preocuparem com a
concorrência; também
- fornece uma escalabilidade melhor, garantindo que a identidade em
unidades de trabalho
- único-encadeadas não necessite de bloqueio dispendioso ou de outros meios
de sincronização.
- A aplicação nunca necessita sincronizar qualquer objeto de negócio tão
longo que transpasse
- uma única thread por <literal>Session</literal>. Dentro de
uma <literal>Session</literal> a
- aplicação pode usar com segurança o <literal>==</literal>
para comparar objetos.
- </para>
-
- <para>
- Com tudo, uma aplicação que usa <literal>==</literal> fora de
uma <literal>Session</literal>,
- pode ver resultados inesperados. Isto pode ocorrer mesmo em alguns
lugares inesperados, por
- exemplo, se você colocar duas instâncias desacopladas em um mesmo
<literal>Set</literal>.
- Ambos podem ter a mesma identidade na base de dados (isto é eles
representam a mesma linha
- em uma tabela), mas a identidade da JVM pela definição não garantida para
instâncias em estado
- desacoplado. O desenvolvedor tem que sobrescrever os métodos
<literal>equals()</literal> e
- <literal>hashCode()</literal> em classes persistentes e
implementar sua própria noção da
- igualdade do objeto. Advertência: nunca use o identificador da base de
dados para implementar
- a igualdade, use atributos de negócio, uma combinação única, geralmente
imutável. O
- identificador da base de dados mudará se um objeto transiente passar para
o estado persistente.
- Se a instância transiente (geralmente junto com instâncias desacopladas)
for inserida em um
- <literal>Set</literal>, mudar o hashcode quebra o contrato do
<literal>Set</literal>.
- Atributos para chaves de negócio não têm que ser tão estável quanto às
chaves primárias
- 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
discussão mais
- completa sobre o assunto. Note também que esta não é uma caracteristica
do Hibernate,
- mas simplesmente como a identidade e a igualdade do objeto de Java têm
que ser implementadas.
- </para>
-
- </sect2>
-
- <sect2 id="transactions-basics-issues">
- <title>Edições comuns</title>
-
- <para>
- Nunca use o anti-patterns
<emphasis>session-per-user-session</emphasis> ou
- <emphasis>session-per-application</emphasis> (naturalmente,
há umas exceções raras a
- essa regra). Note que algumas das seguintes edições podem também
aparecer com patterns
- recomendados, certifique-se que tenha compreendido as implicações antes
de fazer
- uma decisão de projeto:
- </para>
-
- <itemizedlist>
- <listitem>
- <para>
- Uma <literal>Session</literal> não é threadsafe. As
coisas que são supostas para trabalhar
- concorrentemente, como requisições HTTP, session beans, ou Swing,
causarão condições de
- disputa se uma instância <literal>Session</literal>
for compartilhada. Se você mantiver
- sua <literal>Session</literal> do Hibernate em seu
<literal>HttpSession</literal>
- (discutido mais tarde), você deve considerar sincronizar o acesso
a sua sessão do HTTP.
- Caso contrário, um usuário que clica em reload várias muito
rapidamente pode usar o
- mesmo <literal>Session</literal> em duas threads
executando concorrentemente.
- </para>
- </listitem>
- <listitem>
- <para>
- Uma exceção lançada pelo Hibernate significa que você tem que dar
rollback na sua
- transação no banco de dados e fechar a
<literal>Session</literal> imediatamente
- (discutido mais tarde em maiores detalhes). Se sua
<literal>Session</literal> é
- limitado pela aplicação, você tem que parar a aplicação. Dando
rollback na
- transação no banco de dados não põe seus objetos do negócio em um
estado anterior
- que estavam no início da transação. Isto significa que o estado
da base de dados
- e os objetos de negócio perdem a sincronização. Geralmente não é
um problema
- porque as exceções não são recuperáveis e você tem que iniciar
após o
- rollback de qualquer maneira.
- </para>
- </listitem>
- <listitem>
- <para>
- O <literal>Session</literal> guarda em cache cada
objeto que está no estado persistente
- (guardado e checado para estado "sujo" pelo Hibernate).
Isto significa que ele cresce
- infinitamente até que você obtenha uma OutOfMemoryException, se
você o mantiver aberto
- por muito tempo ou simplesmente carregar dados demais. Uma
solução é chamar
- <literal>clear()</literal> e
<literal>evict()</literal> para controlar o cache
- da <literal>Session</literal>, mas você deve
considerar uma Store Procedure
- se precisar de operações que envolvam grande volume de dados.
Algumas soluções são
- mostradas no <xref linkend="batch"/>. Manter uma
<literal>Session</literal> aberta
- durante uma sessão do usuário significa também uma probabilidade
elevada de se acabar
- com dados velhos.
- </para>
- </listitem>
- </itemizedlist>
-
- </sect2>
-
- </sect1>
-
- <sect1 id="transactions-demarcation">
- <title>Demarcação de transações de bancos de dados</title>
-
- <para>
- Os limites de uma transação de banco de dados (ou sistema) são sempre
necessários. Nenhuma
- comunicação com o banco de dados pode ocorrer fora de uma transação de banco
de dados (isto
- parece confundir muitos desenvolvedores que estão usados modo auto-commit).
Sempre use os
- limites desobstruídos da transação, até mesmo para operações somente leitura.
Dependendo
- de seu nível de isolamento e capacidade da base de dados isto pode não ser
requerido,
- mas não há nenhum aspecto negativo se você demarca sempre transações
explicitamente.
- Certamente, uma única transação será melhor executada do que muitas
transações pequenas,
- até mesmo para dados de leitura.
- </para>
-
- <para>
- Uma aplicação do Hibernate pode funcionar em ambientes não gerenciados (isto
é aplicações standalone, Web
- simples ou Swing) e ambientes gerenciados J2EE. Em um ambiente não
gerenciado, o Hibernate é geralmente
- responsável pelo seu próprio pool de conexões. O desenvolvedor tem que
manualmente ajustar limites das
- transaçãos, ou seja, começar, commitar, ou dar rollback nas transações ele
mesmo. Um ambiente gerenciado
- fornece transações gerenciadas por contêiner (CMT - container-managed
transactions), com um conjunto
- da transações definido declarativamente em descritores de deployment de EJB
session beans, por exemplo.
- A demarcação programática é então já não é necessário.
- </para>
-
- <para>
- Entretanto, é freqüentemente desejável manter sua camada de persistência
portável entre ambientes
- de recurso locais não gerenciados e sistemas que podem confiar em JTA, mas
usar BMT em vez de CMT.
- Em ambos os casos você usaria demarcação de transação programática. O
Hibernate oferece uma API
- chamada Transaction que traduz dentro do sistema de transação nativa de seu
ambiente de deployment.
- Esta API é realmente opcional, mas nós encorajamos fortemente seu uso a menos
que você estiver
- em um CMT session bean.
- </para>
-
- <para>
- Geralmente, finalizar um <literal>Session</literal>envolve quatro
fases distintas:
- </para>
-
- <itemizedlist spacing="compact">
- <listitem>
- <para>
- flush da sessão
- </para>
- </listitem>
- <listitem>
- <para>
- commitar a transação
- </para>
- </listitem>
- <listitem>
- <para>
- fechar a sessão
- </para>
- </listitem>
- <listitem>
- <para>
- tratar as exceções
- </para>
- </listitem>
- </itemizedlist>
-
- <para>
- A limpeza da sessão já foi bem discutida, agora nós daremos uma olhada na
demarcação da
- transação e na manipulação de exceção em ambientes controlados e não
controlados.
- </para>
-
-
- <sect2 id="transactions-demarcation-nonmanaged"
revision="2">
- <title>Ambiente não gerenciado</title>
-
- <para>
- Se uma camada de persistência do Hibernate roda em um ambiente não
gerenciado, as conexões
- do banco de dados são geralmente tratadas pelos pools de conexões simples
- (isto é, não baseados em DataSource) dos quais o Hibernate obtém as
conexões assim
- que necessita. A maneira de se manipular uma sessão/transação é mais ou
menos assim:
- </para>
-
- <programlisting><![CDATA[// Non-managed environment 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();
-}]]></programlisting>
-
- <para>
- Você não pode chamar <literal>flush()</literal> do
<literal>Session()</literal>
- explicitamente - a chamada ao <literal>commit()</literal>
dispara automaticamente
- a sincronização para a sessão (dependendo do <xref
linkend="objectstate-flushing">
- FlushMode</xref>). Uma chamada ao
<literal>close()</literal> marca o fim de uma sessão.
- A principal implicação do <literal>close()</literal> é que a
conexão JDBC será abandonada
- pela sessão. Este código Java é portável e funciona em ambientes não
gerenciado e de JTA.
- </para>
-
- <para>
- Uma solução muito mais flexível é gerência integrada de contexto da
"sessão atual"
- do Hibernate, como descrito anteriormente:
- </para>
-
- <programlisting><![CDATA[// Non-managed environment idiom with
getCurrentSession()
-try {
- factory.getCurrentSession().beginTransaction();
-
- // do some work
- ...
-
- factory.getCurrentSession().getTransaction().commit();
-}
-catch (RuntimeException e) {
- factory.getCurrentSession().getTransaction().rollback();
- throw e; // or display error message
-}]]></programlisting>
-
- <para>
- Você muito provavelmente nunca verá estes fragmentos de código em uma
aplicação
- regular; as exceções fatais (do sistema) devem sempre ser pegas no
"alto".
- Ou seja, o código que executa chamadas do Hibernate (na camada de
persistência)
- e o código que trata <literal>RuntimeException</literal> (e
geralmente pode
- somente limpar acima e na saída) estão 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
<literal>SessionFactory</literal>.
- A manipulação de exceção é discutida mais tarde neste capítulo.
- </para>
-
- <para>
- Note que você deve selecionar
<literal>org.hibernate.transaction.JDBCTransactionFactory</literal>
- (que é o padrão) e para o segundo exemplo
<literal>"thread"</literal> como seu
- <literal>hibernate.current_session_context_class</literal>.
- </para>
-
- </sect2>
-
- <sect2 id="transactions-demarcation-jta" revision="3">
- <title>Usando JTA</title>
-
- <para>
- Se sua camada de persistência funcionar em um servidor de aplicação (por
exemplo,
- dentro dos EJB session beans), cada conexão do datasource obtida pelo
Hibernate
- automaticamente fará parte da transação global de JTA. Você pode também
instalar uma
- implementação standalone de JTA e usá-la sem EJB. O Hibernate oferece
duas estratégias
- para a integração de JTA.
- </para>
-
- <para>
- Se você usar bean-managed transactions (BMT - transações gerenciadas por
bean) o Hibernate dirá
- ao servidor de aplicação para começar e para terminar uma transação de
BMT se você usar a API
- Transaction. Assim, o código de gerência de transação é idêntico ao
ambiente não gerenciado.
- </para>
-
- <programlisting><![CDATA[// 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();
-}]]></programlisting>
-
- <para>
- Se você quiser usar um <literal>Session</literal> limitada
por transação, isto é,
- a funcionalidade do <literal>getCurrentSession()</literal>
para a propagação fácil
- do contexto, você terá que usar diretamente a API JTA
<literal>UserTransaction</literal>:
- </para>
-
- <programlisting><![CDATA[// BMT idiom with getCurrentSession()
-try {
- UserTransaction tx = (UserTransaction)new InitialContext()
- .lookup("java:comp/UserTransaction");
-
- tx.begin();
-
- // Do some work on Session bound to transaction
- factory.getCurrentSession().load(...);
- factory.getCurrentSession().persist(...);
-
- tx.commit();
-}
-catch (RuntimeException e) {
- tx.rollback();
- throw e; // or display error message
-}]]></programlisting>
-
- <para>
- Com CMT, a demarcação da transação é feita em descritores de deployment
do session beans,
- não programaticamente, conseqüentemente, o código é reduzido a:
- </para>
-
- <programlisting><![CDATA[// CMT idiom
- Session sess = factory.getCurrentSession();
-
- // do some work
- ...