diff --git a/documentation/manual/pt-BR/src/main/docbook/content/association_mapping.xml b/documentation/manual/pt-BR/src/main/docbook/content/association_mapping.xml index de6907df92..457d72a4fa 100755 --- a/documentation/manual/pt-BR/src/main/docbook/content/association_mapping.xml +++ b/documentation/manual/pt-BR/src/main/docbook/content/association_mapping.xml @@ -1,7 +1,7 @@ - + Mapeamento de Associações diff --git a/documentation/manual/pt-BR/src/main/docbook/content/basic_mapping.xml b/documentation/manual/pt-BR/src/main/docbook/content/basic_mapping.xml index 72d74f8a7e..0effe9ae3f 100755 --- a/documentation/manual/pt-BR/src/main/docbook/content/basic_mapping.xml +++ b/documentation/manual/pt-BR/src/main/docbook/content/basic_mapping.xml @@ -1,3494 +1,3660 @@ - - Mapeamento O/R Bassico - - - Declaração de mapeamento - - - 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. - - - - 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. - - - - Lets kick off with an example mapping: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -]]> - - - 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 - not-null). - - - - - - Doctype - - - Todos os mapeamentos de XML devem declarar o doctype exibido. O DTD atual pode - ser encontrado na URL abaixo, no diretório hibernate-x.x.x/src/org/ - hibernate ou no hibernate3.jar. O Hibernate sempre - irá procurar pelo DTD inicialmente no seu classpath. Se você tentar localizar - o DTD usando uma conexão de internet, compare a declaração do seu DTD com o - conteúdo do seu classpath - - - - EntityResolver - - 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 org.xml.sax.EntityResolver - implementation with the SAXReader it uses to read in the xml files. This custom - EntityResolver recognizes two different systemId namespaces. - - - - - a hibernate namespace is recognized whenever the - resolver encounteres a systemId starting with - http://hibernate.sourceforge.net/; the resolver - attempts to resolve these entities via the classlaoder which loaded - the Hibernate classes. - - - - - a user namespace is recognized whenever the - resolver encounteres a systemId using a classpath:// - 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. - - - - - An example of utilizing user namespacing: - - - -]> - - - - - ... - - - &types; -]]> - - Where types.xml is a resource in the your.domain - package and contains a custom typedef. - - - - - - hibernate-mapping - - - Este elemento tem diversos atributos opcionais. Os atributos - schema e catalog 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 default-cascade - especifica qual estilo de cascata será assumido pelas propriedades e - coleções que não especificarm um atributo cascade. O atributo - auto-import nos deixa utilizar nomes de classes não qualificados - na linguagem de consulta, por default. - - - - - - - - - - - - - ]]> - - - - schema (opcional): O nome do esquema do banco de dados. - - - - - catalog (opcional): O nome do catálogo do banco de dados. - - - - - default-cascade (opcional – default é nenhum - ): Um estilo cascata default. - - - - - default-access (opcional – default é property): - A estratégia que o Hibernate deve utilizar para acessar todas as propridades. Pode - ser uma implementação própria de PropertyAccessor. - - - - - default-lazy (opcional - default é true): - O valor default para atributos lazy da classe e dos - mapeamentos de coleções. - - - - - auto-import ((opcional - default é true): - Especifica se nós podemos usar nomes de classess não qualificados - (das classes deste mapeamento) na linguagem de consulta. - - - - - package (opcional): Especifica um prefixo da package para - assumir para nomes de classes não qualificadas no documento de mapeamento. - - - - - - - Se voce tem duas classes persistentes com o mesmo nome (não qualificadas), você deve - setar auto-import="false". O Hibernate irá gerar uma exceção se - você tentar setar duas classes para o mesmo nome "importado". - - - - Observe que o elemento hibernate-mapping permite a você - aninhar diversos mapeamentos de <class> 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: Cat.hbm.xml, - Dog.hbm.xml, ou se estiver usando herança, - Animal.hbm.xml. - - - - - - class - - - Você pode declarar uma classe persistente utilizando o elemento - class: - - - - - - - - - - - - - - - - - - - - - - - - - - - ]]> - - - - name (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. - - - - - table (opcional – default para nomes de classes não - qualificadas) O nome da sua tabela do banco de dados. - - - - - discriminator-value (opcional – default para o nome da classe): - Um valor que distingue subclasses individuais, usadas para o comportamento polimorfico. - Valores aceitos incluem null e not null - - - - - mutable (opcional - valor default true): - Especifica que instancias da classe são (ou não) mutáveis - - - - - schema (opcional): Sobrepõe o nome do esquema especificado - pelo elemento root <hibernate-mapping>. - - - - - catalog (opcional): Sobrepõe o nome do catálogo especificado - pelo elemento root <hibernate-mapping>. - - - - - proxy (opcional): Especifica um interface para ser - utilizada pelos proxies de inicialização tardia. Você pode especificar o - nome da própria classe. - - - - - dynamic-update (opcional, valor default false): - Especifica que o SQL de UPDATE deve ser gerado em tempo de - execução e conter apenas aquelas colunas cujos valores foram alterados. - - - - - dynamic-insert (opcional, valor default false): - Especifica que o SQL de INSERT deve ser gerado em tempo de - execução e conter apenas aquelas colunas cujos valores não estão nulos. - - - - - select-before-update (opcional, valor default false): - Especifica que o Hibernate never deve executar um SQL de - UPDATE 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 update()), isto significa que o Hibernate ira executar - uma instrução SQL de SELECT adicional para determinar se um - UPDATE é necessário nesse momento. - - - - - polymorphism (opcional, default para implicit): - Determina se deve ser utilizado a query polimorfica implicita ou explicitamente. - - - - - where (opicional) especifica um comando SQL WHERE - arbitrário para ser usado quando da recuperação de objetos desta classe. - - - - - persister (opcional): Espeicifca uma ClassPersister - customizada. - - - - - batch-size (opcional, valor default 1) especifica um - "tamanho de lote" para a recuperação de instancias desta classe pelo identificador. - - - - - optimistic-lock (octional, valor default version): - Determina a estratégia de bloqueio. - - - - - lazy (opcional): A recuperação tardia pode ser completamente - desabilitada, setando lazy="false". - - - - - entity-name (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 - e para maiores informações. - - - - - check (opcional): Uma expressão SQL utilizada para gerar uma - constraint de verificação de múltiplas linhas para a geração - automática do esquema. - - - - - rowid (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 rowid. Um ROWID é uma implementação - que representa de maneira detalhada a localização física de uma determinada - tupla armazenado. - - - - - subselect (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. - subselect (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. - - - - - abstract (opcional): Utilizada para marcar superclasses - abstratas em hierarquias <union-subclass>. - - - - - - - É perfeitamente aceitável para uma classe persitente nomeada ser uma interface. Você deverá - então declarar as classes implementadas desta interface utilizando o elemento - <subclass>. Você pode persistir qualquer classe de aninhada - estatica. Você deverá especificar o nome da classe usando a forma - padrão, por exemplo: eg.Foo$Bar. - - - - Classes imutáveis, mutable="false", não podem ser modificadas ou excluídas - pela aplicação. Isso permite ao Hibernate fazer alguns aperfeiçoamentos de performance. - - - - O atributo opcional proxy 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. - - - Polimorfismo implícito 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 explícito 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 <class> como uma - <subclass> ou <joined-subclass>. - Para a maioria dos casos, o valor default polymorphism="implicit", - é 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). - - - - O atributo persister deixa você customizar a estratégia de persistência - utilizada para a classe. Você pode, por exemplo, especificar sua prórpia subclasse do - org.hibernate.persister.EntityPersister ou você pode criar - uma implementação completamente nova da interface - org.hibernate.persister.ClassPersister que implementa a persistência - através de, por exemplo, chamadas a stored procedeures, serialização de arquivos flat ou - LDAP. Veja org.hibernate.test.CustomPersister para um exemplo - simples (de "persistencia" para uma Hashtable). - - - - Observe que as configurações dynamic-update e - dynamic-insert não sao herdadas pelas subclasses e assim podem tambem - ser especificadas em elementos <subclass> or - <joined-subclass>. Estas configurações podem incrementar a - performance em alguns casos, mas pode realmente diminuir a performance em outras. - Use-as de forma bastante criteriosa. - - - - O uso de select-before-update 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 - Session. - - - - Se você ativar dynamic-update, você terá de escolher - a estratégia de bloqueio otimista: - - - - - version verifica a versão e a hora das colunas - - - - - all cverifica todas as colunas - - - - - dirty verifica as colunas modificadas, permitindo - alguns updates concorrentes - - - - - none não utiliza o bloqueio otimista - - - - - Nós recomendamos 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 Session.merge() é utilizado). - - - - - 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: - - - - - select item.name, max(bid.amount), count(*) - from item - join bid on bid.item_id = item.id - group by item.name - - - - - ... -]]> - - - 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 <subselect> está disponível tanto como um - atributo como um elemento mapeado nested. - - - - - - id - - - Classes mapeadas precisam 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 - <id> define o mapeamento desta propriedade para a chave primária. - - - - - - - - - - - - node="element-name|@attribute-name|element/@attribute|." - - -]]> - - - - name (opcional): O nome do identificador. - - - - - type (opcional): Um nome que indica o tipo no Hibernate. - - - - - column (opcional – default para o a propridade name): O - nome coluna chave primaria. - - - - - unsaved-value (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. - - - - - access (opcional - valor default property): A - estratégia que o Hiberante deve utilizar para acessar o valor da propriedade - - - - - - - Se o atributo name não for declarado, assume-se que a classe não tem - a propriedade de identificação. - - - - O atributo unsaved-value não é mais necessário no Hibernate 3. - - - - Há declaração alternativa <composite-id> permite o acesso a - dados legados com chaves compostas. Nós desencorajamos fortemente o seu uso por - qualquer pessoa. - - - - Generator - - - O elemento filho opcional <generator> 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 <param>. - - - - - uid_table - next_hi_value_column - -]]> - - - Todos os generators implementam a interface org.hibernate.id.IdentifierGenerator. - 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: - - - increment - - - gera identificadores dos tipos long, short ou - int que são unicos apenas quando nenhum outro processo está - inserindo dados na mesma tabela. Não utilize em ambientes - de cluster. - - - - - identity - - - suporta colunas de identidade em DB2, MySQL, MS SQL Server, Sybase e - HypersonicSQL. O identificador retornado é do tipo long, - short ou int. - - - - - sequence - - - utiliza uma sequence em DB2, PostgreSQL, Oracle, SAP DB, McKoi ou um - generator no Interbase. O identificador de retorno é do tipo - long, short ou int. - - - - - hilo - - - utiliza um algoritmo hi/lo para gerar de forma eficiente identificadores do tipo - long, short ou int, - a partir de uma tabela e coluna fornecida (por default - hibernate_unique_key e next_hi) - como fonte para os valores hi. O algoritmo hi/lo gera identificadores que são - únicos apenas para um banco de dados particular. - - - - - seqhilo - - - utiliza um algoritmo hi/lo para gerar de forma eficinete identificadores do tipo - long, short ou int, - a partir de uma sequence de banco de dados fornecida. - - - - - uuid - - - 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. - - - - - guid - - - utiliza um string GUID gerado pelo banco de dados no MS SQL Server - e MySQL. - - - - - native - - - seleciona entre identity, sequence - ou hilo dependendo das capacidades do banco de dados - utilizado. - - - - - assigned - - - deixa a aplicação definir um identificador para o objeto antes que o - save() seja chamado. Esta é a estratégia default - se nenhum elemento <generator> é especificado. - - - - - select - - - 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. - - - - - foreign - - - utiliza o identificador de um outro objeto associado. Normalmente utilizado - em conjunto com uma associaçõa de chave primária do tipo - <one-to-one>. - - - - - sequence-identity - - - 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. - - - - - - - - - - Algoritmo Hi/lo - - Os geradores hilo e seqhilo 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). - - - - - hi_value - next_value - 100 - -]]> - - - - hi_value - 100 - -]]> - - - Infelizemente, voce não pode utilizar hilo quando estiver - fornecendo sia propria Connection 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 - hibernate.transaction.manager_lookup_class. - - - - - UUID algorithm - - 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. - - - - - Colunas de identidade e sequencias - - Para bancos de dados que suportam colunas de identidade (DB2, MySQL, Sybase, - MS SQL), você pode utilizar uma geração de chave identity. - Para bancos de dados que suportam sequencias (DB2, Oracle, PostgreSQL, Interbase, - McKoi, SAP DB) voce pode utilizar a geração de chaves no estilo - sequence. As duas estratégias requerem duas consultas SQL - para inserir um novo objeto. - - - - - person_id_sequence - -]]> - - - -]]> - - - Para desenvolvimento multi-plataforma, a estratégia native - irá escolher entre as estratégias i identity, - sequence e hilo, dependendo das - capacidades do banco de dados utilizado. - - - - - Identificadores especificados - - Se você quer que a aplicação especifique os identificadores - (em vez do Hibernate gerá-los) você deve utilizar o gerador - assigned. 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 <generator>. - - - - Escolher o gerador assigned faz com que o Hibernate - utilize unsaved-value="undefined", 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 Interceptor.isUnsaved(). - - - - - Chaves primárias geradas por triggers - - Apenas para sistemas legados (o Hibernate nao gera DDL com triggers). - - - - - socialSecurityNumber - -]]> - - - No exemplo acima, há uma única propriedade com valor nomeada - socialSecurityNumber definida pela classe, - uma chave natural, e uma surrogate key nomeada - person_id cujo valor é gerado pro uma trigger. - - - - - - - - composite-id - - - node="element-name|." - - - - ...... -]]> - - - Para tabelas com uma chave composta, você pode mapear múltiplas propriedades - da classe como propriedades de identificação. O elemento - <composite-id> aceita o mapeamento da propriedade - <key-property> e mapeamentos - <key-many-to-one>como elements filhos. - - - - - -]]> - - - Sua classe persistente precisa sobre escrever - equals() e hashCode() para implementar - identificadores compostos igualmente. E precisa também implementar - Serializable. - - - - 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 load() - para o estado persistente associado com uma chave composta. Nos chamamos esta - solução de identificador composto embedded e não aconselhamos - para aplicações sérias. - - - - Uma segunda solução é o que podemos chamar de identificador composto - mapped quando a propriedades de identificação nomeadas dentro do - elemento <composite-id> estão duplicadas tando na classe - persistente como em uma classe de identificação separada. - - - - - -]]> - - - No exemplo, ambas as classes de identificação compostas, MedicareId, - e a própria classe entidade tem propriedades nomeadas medicareNumber - e dependent. A classe identificadora precisa sobrepor - equals() e hashCode() e implementar - Serializable. A desvantagem desta solução é obvia – - duplicação de código. - - - - Os seguintes atributos ão utilizados para especificar o mapeamento de - um identificador composto: - - - - - - mapped mapped (opcional, valor default false - ): 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. - - - - - class (opcional, mas requerida para um identificar composto - mapeado): A classe usada como um identificador composto. - - - - - - Nós iremos descrever uma terceira e as vezes mais conveniente solução, onde o - identificador composto é implementado como uma classe componente na - . Os atributos descritos abaixo aplicam-se - apenas para esta solução: - - - - - - name (opcional, requerida para esta solução): Uma - propriedade do tipo componente que armazena o identificador composto - (veja capítulo 9) - - - - - access (opcional - valor default property): - A estartégia Hibernate que deve ser utilizada para acessar o valor da propriedade. - - - - - class (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). - - - - - - Esta terceira solução, um componente de identificação, é o que nós - recomendamos para a maioria das aplicações. - - - - - - discriminator - - - O elemento <discriminator> é 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: string, - character, integer, byte, - short, boolean, - yes_no, true_false. - - - - - - - - - - - ]]> - - - - column (opcional - valor default class) - o nome da coluna discriminadora - - - - - type (opcional - valor default string) - o nome que indica o tipo Hibernate - - - - - force (opcional - valor default false) - "força" o Hibernate a especificar valores discriminadores permitidos mesmo - quando recuperando todas as instancias da classe root. - - - - - insert (opcional - valor default para true) - sete isto para false se sua coluna discriminadora é também - parte do identificador composto mapeado. (Diz ao Hibernate para não incluir a - coluna em comandos SQL INSERTs). - - - - - formula (opcional) uma expressão SQL arbitraria que é e - xecutada quando um tipo tem que ser avaliado. Permite discriminação baseada - em conteúdo. - - - - - - - Valores atuais de uma coluna discriminada são especificados pelo atributo - discriminator-value da <class> - e elementos da <subclass>. - - - - O atributo force é 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. - - - - Usando o atributo formula voce pode declarar uma expressão SQL - arbitrária que sera utilizada para avaliar o tipo de uma linha : - - - ]]> - - - - - version (optional) - - - O elemento <version> é opcional e indica que a tabela - possui dados versionados. Isto é particularmente útil se você planeja utilizar - transações longas (veja abaixo): - - - - - - - - - - - - - ]]> - - - - column (opcional - default a a propriedade name): O nome da - coluna mantendo o numero da versão - - - - - name: O nome da propriedade da classe persistente. - - - - - type (opcional - valor default para integer): - O tipo do numero da versão - - - - - access (opcional - valor default property): - A estratégia Hibernate que deve ser usada para acessar o valor da propriedade. - - - - - unsaved-value (opcional – valor default para undefined - ): 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. ((undefined especifica - que o valor da propriedade de identificação deve ser utilizado). - - - - - generated (optional - defaults to never): - Specifies that this version property value is actually generated by the database. - See the discussion of generated properties. - generated (opcional - valor default never): - Especifica que valor para a propriedade versão é na verdade gerado pelo banco de - dados. Veja a discussão da Seção - generated properties. - - - - - insert (opcional - valor default para true): - Especifica se a coluna de versão deve ser incluída no comando SQL de insert. - Pode ser configurado como false se a coluna do banco de dados - está definida com um valor default de 0. - - - - - - - Números de versão podem ser dos tipos Hibernate long, - integer, short, timestamp ou - calendar. - - - - 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 unsaved-value. 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! - - - - - timestamp (optional) - - - O elemento opcional <timestamp> 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. - - - - - - - - - - - - ]]> - - - - column (opcional - valor default para a propriedade name): - O nome da coluna que mantem o timestamp. - - - - - name: O nome da propriedade no estilo JavaBeans do - tipo Date ou Timestamp da classe - persistente Java. - - - - - access (opcional - valor default para property): - A estretagia Hibernate que deve ser utilizada para acessar o valor da propriedade. - - - - - unsaved-value (opcional - valor default null): - 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. (undefined especifica que um valor de - propriedade de identificação deve ser utilizado) - - - - - source (opcional - valor default para vm): - 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 - Dialects 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) - - - - - generated (opcional - valor default never): - Especifica que o valor da propriedade timestamp é gerado pelo banco de dados. - Veja a discussão generated properties. - - - - - - - Observe que <timestamp> é equivalente a - <version type="timestamp">. E - <timestamp source="db"> é equivalente a - <version type="dbtimestamp">. - - - - - - property - - - O elemento <property> declara uma propriedade - persistente de uma classe, no estilo JavaBean. - - - - - - - - - - - - - - - - - - - - ]]> - - - - name: o nome da propriedade, iniciando com letra minúscula. - - - - - column (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) <column> aninhados. - - - - - - type (opcional): um nome que indica o tipo Hibernate. - - - - - update, insert (opcional - valor default true): - especifica que as colunas mapeadas devem ser incluidas nas instruções SQL de - UPDATE e/ou INSERT . Setar ambas para to - false 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. - - - - - formula (opcional): uma expressão SQL que definie o valor para - uma propriedade calculada. Propriedades calculadas nao tem - uma coluna de mapeamento para elas. - - - - - access (opcional – valor default property): - A estratégia que o Hibernate deve utilizar para acessar o valor da propriedade - - - - - lazy (opcional - valor default para false): - 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). - - - - - unique (opcional): Habilita a geração de DDL de uma - unica constraint para as colunas. Assim, permite que isto seja o - alvo de uma property-ref. - - - - - not-null (opcional): Habilita a geração de DDL de uma - constraint de nulidade para as colunas. - - - - - optimistic-lock (opcional - valor default true): - 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. - - - - - generated (opcional - valor default never): - Especifica que o valor da propriedade é na verdade gerado pelo banco de dados. - Veja a discussão da seção - generated properties. - - - - - - - typename pode ser: - - - - - - The name of a Hibernate basic type (eg. integer, string, character, - date, timestamp, float, binary, serializable, object, blob). - O nome do tipo basico do Hibernate (ex., integer, string, character, - date, timestamp, float, binary, serializable, object, blob). - - - - - O nome da classe Java com um tipo básico default (ex. int, float, - char, java.lang.String, java.util.Date, java.lang.Integer, java.sql.Clob). - - - - - O nome da classe Java serializable - - - - - O nome da classe de um tipo customizado (ex. com.illflow.type.MyCustomType). - - - - - - 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 type. (Por exemplo, para distinguir entre - Hibernate.DATE ou Hibernate.TIMESTAMP, - ou para espcificar uma tipo ciustomizado.) - - - - O atributo access 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 access="field", - 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 - org.hibernate.property.PropertyAccessor. - - - - 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 - SELECT de uma subquery daquery SQL que carrega a instancia: - - - ]]> - - - 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 ( - customerId no exemplo dado). Observe tambem que voce pode usar o - mapeamento de elemento aninhado <formula>, se você não - gostar de usar o atributo. - - - - - - many-to-one - - - Uma associação ordinária para outra classe persistente é declarada usando o - elemento many-to-one. O modelo relacional é uma - associação many-to-one: a uma chave estrangeira de uma tabela referenciando - a chave primaria da tabela destino. - - - - - - - - - - - - - - - - - - - - - - - - ]]> - - - - name: O nome da propriedade. - - - - - column (opcional): O nome da coluna foreign key. Isto - pode também ser especificado através de elementos aninhados - <column>. - - - - - class (opcional – default para o tipo de propriedade - determinado pela reflexão). O nome da classe associada. - - - - - cascade (opcional): Especifica quais operações dever - ser em cascata do objeto pai para o objeto associado. - - - - - fetch (opcional - default para select): - Escolhe entre recuperação outer-join ou recuperação seqüencial. - - - - - update, insert (opcional - valor default true): - especifica que as colunas mapeadas dever ser incluidas em instruções SQL de - UPDATE e/ou INSERT. Setando ambas para - false 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. - - - - - property-ref: (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. - - - - - access (opcional - valor default property): A - estrategia que o Hibernate deve utilizar para acessar o valor da propriedade. - - - - - unique (opcional): Habilita a geração DDL de uma constraint - unique para a coluna foreign-key. Alem disso, permite ser o alvo de uma - property-ref. Isso torna a associação multipla - efetivamente um para um. - - - - - not-null (opcional): Habilita a geração DDL de uma constraint de - nulidade para as foreign keys. - - - - - optimistic-lock (opcional - valor default true): - 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. - - - - - lazy(opcional – valor default proxy): - Por default, associações de ponto unico são envoltas em um proxie. - lazy="no-proxy" 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) - lazy="false" especifica que a associação será - sempre recuperada fortemente. - - - - - not-found (opcional - valor default exception): - Especifica como as foreign keys que referenciam linhas ausentes serão tratadas: - ignore irá tratar a linha ausente como ama associaççao de null - - - - - entity-name (opcional): O nome da entidade da classe associada. - - - - - - formula (optional): Uma expressão SQL que define um valor - para um foreign key computed. - - - - - - Setar o valor do atributo cascade para qualquer valor - significativo diferente de none irá propagar certas operações - ao objeto associado. Os valores significativos são os nomes das operações básicas - do Hibernate, persist, merge, delete, save-update, evict, replicate, lock, - refresh, assim como os valores especiais delete-orphan - e all e combinações de nomes de operações separadas por vírgula, - como por exemplo, cascade="persist,merge,evict" ou - cascade="all,delete-orphan". Veja a seção - 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. - - - - Uma típica declaração muitos-pra-um se parece com esta: - - - ]]> - - - O atributo property-ref 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 Product tenha um número - seqüencial exclusivo, que não é a chave primária. (O atributo unique - controla a geração de DDL do Hibernate com a ferramenta SchemaExport.) - - - ]]> - - - Então o mapeamento para OrderItem poderia usar: - - - ]]> - - - Porém, isto obviamente não é indicado, nunca. - - - - Se a chave exclusiva referenciada engloba múltiplas propriedades da entidade associada, - você deve mapear as propriedades referenciadas dentro de um elemento chamado - <properties> - - - - - Se a chave exclusiva referenciada é a propriedade de um componente, você pode especificar - um caminho para a propriedade. - - - ]]> - - - - - one-to-one (um-pra-um) - - - Uma associação um-pra-um para outra classe persistente é declarada usando - um elemento one-to-one . - - - - - - - - - - - - - - - - ]]> - - - - name: O nome da propriedade. - - - - - class (opcional – default para o tipo da propriedade - definido via reflection): O nome da classe associada. - - - - - cascade (opcional): Especifica qual operação deve - ser cascateada do objeto pai para o objeto associado. - - - - - constrained (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 save() e - delete() são cascateadas, e determina se a associação - pode ser substituída (isto também é usado pela ferramenta schema export). - - - - - fetch ((opcional – valor default select): - Escolhe entre outer-join fetching ou sequential select fetching. - - - - - property-ref(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. - - - - - access (opcional - valor default padrão property): - A estratégia que o Hibernate pode usar para acessar o valor da propriedade. - - - - - formula (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 org.hibernate.test.onetooneformula - para exemplo). - - - - - lazy (opcional – valor default proxy): - Por default, associações single point são proxied. lazy="no-proxy" - especifica que a propriedade deve ser fetched lazily quando o atributo é acessado - pela primeira vez (requer build-time bytecode instrumentation). - lazy="false" especifica que a associação vai sempre ser - avidamente fetched. Note que se constrained="false", - proxing é impossível e o Hibernate vai ávido fetch a associação! - - - - - entity-name (opcional): O nome da entidade da classe associada. - - - - - - - Existem duas variedades de associações um-pra-um: - - - - associações de chave primária - - - associações de chave estrangeira exclusiva - - - - - 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 uma associação de chave primária, adicione os seguintes mapeamentos em - Employee e Person, respectivamente. - - - ]]> - ]]> - - - 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 foreign: - - - - - - employee - - - ... - -]]> - - - Uma nova instância de Person salva recentemente é então assinada - com o mesmo valor da chave primária da instância de employee referenciada - com a propriedade employee daquela Person. - - - - Alternativamente, uma chave estrangeira com uma unique constraint, de - Employee para Person, pode ser expressa como: - - - ]]> - - - E esta associação pode ser feita de forma bi-direcional adicionando o seguinte - no mapeamento de Person: - - - ]]> - - - - - natural-id - - - - - ...... -]]> - - - 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 <natural-id>. O Hibernate irá gerar a chave - exclusiva necessária e as constraints de nullability , e seu mapeamento será - apropriadamente auto documentado. - - - - Nós recomendamos com enfase que você implemente equals() e - hashCode() para comparar as propriedades da chave natural da - entidade. - - - - Este mapeamento não tem o objetivo de uso com entidades com natural chaves primárias. - - - - - - mutable mutable (opcional, valor defaultfalse): - Por default, propriedades naturais identificadoras são consideradas imutáveis (constante). - - - - - - - - componente, componente dinâmico - - - O elemento<component> 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. - - - - - - - - - - - - - - - - - - ........ -]]> - - - - name: O nome da propriedade. - - - - - class (opcional – valor default para o tipo de - propriedade determinada por reflection): O nome da classe (filha) do - componente. - - - - - insert: As colunas mapeadas aparecem nos - SQL de INSERTs? - - - - - update: As colunas mapeadas aparecem nos - SQL de UPDATEs? - - - - - access (opcional – valor default property): - A estratégia que o Hibernate pode usar para acessar o valor da propriedade. - - - - - lazy (opcional - valor default false): - Especifica que este componente deve ser fetched lazily quando o atributo for - acessado pela primeira vez (requer build-time bytecode instrumentation). - - - - - optimistic-lock (opcional – valor default true): - 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. - - - - - unique (opcional – valor default false): - Especifica que existe uma unique constraint em todas as colunas mapeadas do - componente. - - - - - - - A tag filha <property> acrescenta a propriedade - de mapeamento da classe filha para colunas de uma tabela. - - - - O elemento <component> permite um sub-elemento - <parent> mapeie uma propriedade da classe do componente - como uma referencia de volta para a entidade que o contém. - - - - O elemento <dynamic-component> permite que um - Map possa ser mapeado como um componente onde os nomes das - propriedades referem-se para as chaves no mapa, veja - . - - - - - - propriedades - - - O elemento <properties> 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 - property-ref. É também um modo conveninente para definir uma - unique constraint de múltiplas colunas. - - - - - - - - - - - - - - - ........ -]]> - - - - name:: O nome lógico do agrupamento – - não é o nome atual de propriedade. - - - - - insert: As colunas mapeadas aparecem nos - SQL de INSERTs? - - - - - update: As colunas mapeadas aparecem nos - SQL de UPDATEs? - - - - - optimistic-lock (opcional – valor default true): - 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. - - - - - unique (opcional – valor defautl false): - Especifica que uma unique constraint existe em todas as colunas mapeadas do componente. - - - - - - - Por exemplo, se nós temos o seguinte mapeamento de <properties>: - - - - - ... - - - - - -]]> - - - Então nós podemos ter uma associação de dados herdados que referem a esta chave - exclusiva da tabela Person, ao invés de se referirem a chave - primária: - - - - - - -]]> - - - Nós não recomendamos o uso deste tipo de coisa fora do contexto de mapeamento de - dados herdados. - - - - - - subclass (subclasse) - - - 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 <subclass> - deve ser usada. - - - - - - - - - - - - - ..... -]]> - - - - name: O nome de classe completamente qualificada da subclasse. - - - - - discriminator-value (opcional – valor default o nome da classe): - Um valor que distingue subclasses individuais. - - - - - proxy (opcional): Especifica a classe ou interface que - usará os proxies de inicialização atrasada. - - - - - lazy (opcional, valor default true): - Configurar lazy="false" desabilitará o uso de - inicialização atrasada. - - - - - - Cada subclasse deve declarar suas próprias propriedades persistentes e subclasses. - As propriedades <version> e <id> - são configuradas para serem herdades da classe raiz. Cada subclasse numa hierarquia - deve definir um único discriminator-value. Se nenhum for - especificado, o nome da classe Java completamente qualificada será usada. - - - - Para informações sobre mapeamento de heranças, veja o . - - - - - - joined-subclass - - - 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 - <joined-subclass>. - - - - - - - - - - - - - - - ..... -]]> - - - - name: O nome da classe completamente qualificada da - subclasse. - - - - - table: O nome da tabela da subclasse. - - - - - proxy (opcional): Especifica a classe ou interface - para usar os proxies de recuperação atrasada. - - - - - lazy (opcional, valor default true): - Fixanr lazy="false" desabilita o uso recuperação - atrasada. - - - - - - - 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 <key>. O mapeamento no início do - capítulo poderia ser re-escrito assim: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -]]> - - - Para informações de mapeamentos de herança, veja . - - - - - - union-subclass - - - 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 - <class> 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 <union-subclass>. - - - - - - - - - - - - - - ..... -]]> - - - - name: O nome da subclasse completamente qualificada. - - - - - table: O nome da tabela da subclasse. - - - - - proxy (optional): Specifies a class or interface to use - for lazy initializing proxies. - - proxy (opcional): Especifica a classe ou interface para usar - os proxies de recuperação atrasada. - - - - - lazy (optional, defaults to true): Setting - lazy="false" disables the use of lazy fetching. - lazy (opcional, valor default ptrue): - Fixando lazy="false" desabilita o uso da recuperação atrasada. - - - - - - - A coluna discriminatõria não é requerida para esta estratégia de mapeamento. - - - - - Para informações sobre mapeamentos de herança, veja . - - - - - - join - - - Usando o elemento <join>>, é possível mapear - propriedades de uma classe para várias tabelas. - - - - - - - - - - - - - - - - - ... -]]> - - - - - table: O nome da tabela associada. - - - - - schema (opcional): Sobrepõe o nome do esquema - especificado pelo elemento raiz <hibernate-mapping>. - - - - - catalog (opcional): Sobrepõe o nome do catálogo - especificado pelo elemento raiz<hibernate-mapping>. - - - - - fetch(opcional – valor default join): Se setado - para join, o padrão, o Hibernate irá usar um inner join para - restaurar um join definido por uma classe ou suas subclasses e - uma outer join para um join definido por uma subclasse. - Se setado para select, então o Hibernate irá usar uma seleção - seqüencial para um <join> 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 - <join> definido pela classe e suas superclasses. - - - - - inverse (opcional – valor default false): - Se habilitado, o Hibernate não irá tentar inserir ou atualizar as propriedades - definidas por este join. - - - - - optional (opcional – valor default false): - 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. - - - - - - - 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): - - - - - ... - - - - - - - - ...]]> - - - 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. - - - - - - key - - - Nós vimos que o elemento <key> 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. - - - - - - - - - - - - ]]> - - - - . - column (opcional): O nome da coluna da chave estrangeira. - Isto também pode ser especificado por aninhamento de elemento(s) - <column>. - - - - - on-delete (opcional, valor default noaction): - Especifica se a constraint da chave estrangeira no banco de dados esta - habilitada para cascade delete . - - - - - property-ref (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.) - - - - - not-null (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). - - - - - update (optional): Specifies that the foreign key should never - be updated (this is implied whenever the foreign key is also part of the primary - key). - update (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). - - - - - unique (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). - - - - - - - Nós recomendamos que para sistemas que a performance de delete seja importante, todas as - chaves deve ser definida on-delete="cascade", e o Hibernate irá usar - uma constraint a nível de banco de dados ON CASCADE DELETE, ao invés - de muitas instruções DELETE. Esteja ciente que esta característica é - um atalho da estratégia usual de optimistic locking do Hibernate para dados versionados. - - - - Os atributos not-null e update 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ê - deve declarar a coluna chave usando - <key not-null="true">. - - - - - - elementos column e formula - - Qualquer elemento de mapeamente que aceita um atributo column irá - aceitar alternativamente um subelemento <column>. Da mesma forma, - formula é uma alternativa para o atributo formula. - - - ]]> - - SQL expression]]> - - - O atributo column e formula podem até ser combinados - dentro da mesma propriedade ou associação mapeando para expressar, - por exemplo, associações exóticas. - - - - - 'MAILING' -]]> - - - - - import - - - 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 auto-import="true". - Você pode até importar classes e interfaces que não estão explicitamente mapeadas. - - - ]]> - - - - - - - ]]> - - - - class: O nome qualificado (do pacote) de qualquer classe Java. - - - - - rename (opcional – valor default, o nome da classe não - qualificada): Um nome que pode ser usado numa linguagem de consulta. - - - - - - - - - any - - - Existe mais um tipo de propriedade de mapeamento. O elemento de mapeamento - <any> 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). - - - - - O atributo meta-type 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 id-type. Você deve especificar - o mapeamento de valores do meta-type para nome de classes. - - - - - - - - -]]> - - - - - - - - - - - - - - ..... - - - ..... -]]> - - - - name: o nome da propriedade. - - - - - id-type: o tipo identificador. - - - - - meta-type (opcional – valor default string): - Qualquer tipo que é permitido para um mapeamento discriminador. - - - - - cascade (opcional – valor default none): - o estilo do cascade. - - - - - access (opcional – valor default property): - A estratégia que o hibernate deve usar para acessar o valor da propriedade. - - - - - optimistic-lock (opcional - valor defaulttrue): - 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. - - - - - - - - - - - Tipos do Hibernate - - - Entidades e valores - - - 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. - - - - Uma entidade 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 cascata 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. - - - - Uma entidade em estado persistente consiste de referências para outras entidades - e instâncias de tipos de valor. 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) - são 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. - - - - - 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 - componente é uma classe de usuário definida com valores - semânticos. Uma propriedade de Java de tipo java.lang.String - 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. - - - - Nós iremos rever ambos os conceitos durante toda a documentação. - - - - - 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 - <class>, <subclass> e assim por diante. - Para tipos de valores nós usamos <property>, - <component>, etc, geralmente com um atributo - type. O valor deste atributo é o nome de um tipo de - mapeamento 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. - - - - Todos os tipos internos do hibernate exceto coleções suportam semânticas nulas. - - - - - - - Valores de tipos básicos - - - O tipos internos de mapeamentos básicos podem ser a grosso modo categorizado como: - - - integer, long, short, float, double, character, byte, - boolean, yes_no, true_false - - - Tipos de mapeamentos de classes primitivas ou wrapper Java especificos - (vendor-specific) para tipos de coluna SQL. Boolean, - boolean, yes_no são todas codificações alternativas - para um boolean ou java.lang.Boolean - do Java. - - - - - string - - - Um tipo de mapeamento de java.lang.String para - VARCHAR (ou VARCHAR2 no Oracle). - - - - - date, time, timestamp - - - Tipos de mapeamento de java.util.Date e suas - subclasses para os tipos SQL DATE, - TIME e TIMESTAMP - (ou equivalente). - - - - - calendar, calendar_date - - - Tipo de mapeamento de java.util.Calendar para - os tipos SQL TIMESTAMP e - DATE (ou equivalente). - - - - - big_decimal, big_integer - - - Tipo de mapeamento de java.math.BigDecimal and - java.math.BigInteger para NUMERIC - (ou NUMBER no Oracle). - - - - - locale, timezone, currency - - - Tipos de mapeamentos de java.util.Locale, - java.util.TimeZone e java.util.Currency - para VARCHAR (ou VARCHAR2 no Oracle). - Instâncias de f Locale e Currency - são mapeados para seus códigos ISO. Instâncias de TimeZone - são mapeados para seu ID. - - - - - class - - - um tipo de mapeamento de java.lang.Class para - VARCHAR (ou VARCHAR2 no - Oracle). Uma Class é mapeada pelo - seu nome qualificado (completo). - - - - - binary - - - Mapeia arrays de bytes para um tipo binário de SQL apropriado. - - - - - text - - - Maps long Java strings to a SQL CLOB or - TEXT type. - Mapeia strings longas de Java para um tipo SQL - CLOB ou TEXT. - - - - - serializable - - - Mapeia tipos Java serializáveis para um tipo binário SQL apropriado. - Você pode também indicar o tipo serializable do - Hibernate com o nome da classe ou interface Java serializável que - não é padrão para um tipo básico. - - - - - clob, blob - - - Tipos de mapeamentos para as classes JDBC java.sql.Clob and - java.sql.Blob. 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.) - - - - - - imm_date, imm_time, imm_timestamp, imm_calendar, imm_calendar_date, - imm_serializable, imm_binary - - - - 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 Date.setTime() para - uma instância mapeada como imm_timestamp. Para mudar - o valor da propriedade, e ter a mudança feita persistente, a aplicação - deve atribuir um novo objeto (nonidentical) à propriedade. - - - - - - - - - Identificadores únicos das entidades e coleções podem ser de qualquer tipo - básico exceto binary, blob ou - clob. (Identificadores compostos também são permitidos, - veja abaixo.) - - - - Os tipos de valores básicos têm suas constantes Type - correspondentes definidas em org.hibernate.Hibernate. Por exemplo, - Hibernate.STRING representa o tipo string. - - - - - - Tipos de valores personalizados - - - É relativamente fácil para desenvolvedores criar seus próprios tipos de valor. - Por exemplo, você pode querer persistir propriedades do tipo - java.lang.BigInteger para colunas VARCHAR. 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 - getName()/setName() do tipo - java.lang.String que é persistido para colunas - FIRST_NAME, INITIAL, SURNAME. - - - - - Para implementar um tipo personalizado, implemente org.hibernate.UserType - or org.hibernate.CompositeUserType e declare propriedades usando o nome - qualificado da classe do tipo. Veja org.hibernate.test.DoubleStringType - para ver o tipo das coisas que são possíveis. - - - - - -]]> - - - Observe o uso da tag <column> para mapear uma propriedade - para colunas múltiplas. - - - - As interfaces CompositeUserType, EnhancedUserType, - UserCollectionType, e UserVersionType - fornecem suporte para usos mais especializados. - - - - Você pode mesmo fornecer parâmetros a um UserType no arquivo de mapeamento. - Para isto, seu UserType deve implementar a interface - org.hibernate.usertype.ParameterizedType. Para fornecer parâmetros a seu - tipo personalizado, você pode usar o elemento <type> em seus - arquivos de mapeamento. - - - - - 0 - -]]> - - - O UserType pode agora recuperar o valor para o parâmetro chamado - default da Propriedade do passado a ele. - - - - Se você usar freqüentemente um determinado UserType, pode ser útil definir - um nome mais curto para ele. Você pode fazer isto usando o elemento - <typedef>. Typedefs atribui um nome a um tipo personalizado, e pode também - conter uma lista de valores default de parâmetro se o tipo for parametrizado. - - - - 0 -]]> - - ]]> - - - 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. - - - - Even though Hibernate's rich range of built-in types and support for components means you - will very rarely need 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 MonetaryAmount class is a good - candidate for a CompositeUserType, 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. - - - - - - - - Mapping a class more than once - - It is possible to provide more than one mapping for a particular persistent class. In this - case you must specify an entity name 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. - - - - ... - - - - - - - - ... - -]]> - - - Notice how associations are now specified using entity-name instead of - class. - - - - - - SQL quoted identifiers - - 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 Dialect (usually double quotes, but brackets for SQL - Server and backticks for MySQL). - - - - - - ... -]]> - - - - - - Metadata alternatives - - - XML isn't for everyone, and so there are some alternative ways to define O/R mapping metadata in Hibernate. - - - - Using XDoclet markup - - - Many Hibernate users prefer to embed mapping information directly in sourcecode using - XDoclet @hibernate.tags. 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 Cat class with XDoclet mappings. - - - - - - See the Hibernate web site for more examples of XDoclet and Hibernate. - - - - - - Using JDK 5.0 Annotations - - - 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 EntityManager of JSR-220 (the persistence API), - support for mapping metadata is available via the Hibernate Annotations - package, as a separate download. Both EJB3 (JSR-220) and Hibernate3 metadata is supported. - - - - This is an example of a POJO class annotated as an EJB entity bean: - - - orders; - - // Getter/setter and business methods -}]]> - - - 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. - - - - - - - Generated Properties - - Generated properties are properties which have their values generated by the - database. Typically, Hibernate applications needed to refresh - 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. - - - Properties marked as generated must additionally be non-insertable and non-updateable. - Only versions, - timestamps, and - simple properties can be marked as - generated. - - - never (the default) - means that the given property value - is not generated within the database. - - - insert - 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 - version and - timestamp properties can - be marked as generated, this option is not available there... - - - always - states that the property value is generated both - on insert and on update. - - - - - Auxiliary Database Objects - - 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 java.sql.Statement.execute() - method is valid here (ALTERs, INSERTS, etc). There are essentially two modes for - defining auxiliary database objects... - - - The first mode is to explicitly list the CREATE and DROP commands out in the mapping - file: - - - ... - - CREATE TRIGGER my_trigger ... - DROP TRIGGER my_trigger - -]]> - - 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 - org.hibernate.mapping.AuxiliaryDatabaseObject interface. - - - ... - - - -]]> - - Additionally, these database objects can be optionally scoped such that they only - apply when certain dialects are used. - - - ... - - - - - -]]> - - - + + Mapeamento O/R Bassico + + + Declaração de mapeamento + + + 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. + + + + 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. + + + + Lets kick off with an example mapping: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +]]> + + + 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 + not-null). + + + + + + Doctype + + + Todos os mapeamentos de XML devem declarar o doctype exibido. O DTD atual pode + ser encontrado na URL abaixo, no diretório hibernate-x.x.x/src/org/ + hibernate ou no hibernate3.jar. O Hibernate sempre + irá procurar pelo DTD inicialmente no seu classpath. Se você tentar localizar + o DTD usando uma conexão de internet, compare a declaração do seu DTD com o + conteúdo do seu classpath + + + + EntityResolver + + 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 org.xml.sax.EntityResolver + implementation with the SAXReader it uses to read in the xml files. This custom + EntityResolver recognizes two different systemId namespaces. + + + + + a hibernate namespace is recognized whenever the + resolver encounteres a systemId starting with + http://hibernate.sourceforge.net/; the resolver + attempts to resolve these entities via the classlaoder which loaded + the Hibernate classes. + + + + + a user namespace is recognized whenever the + resolver encounteres a systemId using a classpath:// + 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. + + + + + An example of utilizing user namespacing: + + + +]> + + + + + ... + + + &types; +]]> + + Where types.xml is a resource in the your.domain + package and contains a custom typedef. + + + + + + hibernate-mapping + + + Este elemento tem diversos atributos opcionais. Os atributos + schema e catalog 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 default-cascade + especifica qual estilo de cascata será assumido pelas propriedades e + coleções que não especificarm um atributo cascade. O atributo + auto-import nos deixa utilizar nomes de classes não qualificados + na linguagem de consulta, por default. + + + + + + + + + + + + + ]]> + + + + schema (opcional): O nome do esquema do banco de dados. + + + + + catalog (opcional): O nome do catálogo do banco de dados. + + + + + default-cascade (opcional – default é nenhum + ): Um estilo cascata default. + + + + + default-access (opcional – default é property): + A estratégia que o Hibernate deve utilizar para acessar todas as propridades. Pode + ser uma implementação própria de PropertyAccessor. + + + + + default-lazy (opcional - default é true): + O valor default para atributos lazy da classe e dos + mapeamentos de coleções. + + + + + auto-import ((opcional - default é true): + Especifica se nós podemos usar nomes de classess não qualificados + (das classes deste mapeamento) na linguagem de consulta. + + + + + package (opcional): Especifica um prefixo da package para + assumir para nomes de classes não qualificadas no documento de mapeamento. + + + + + + + Se voce tem duas classes persistentes com o mesmo nome (não qualificadas), você deve + setar auto-import="false". O Hibernate irá gerar uma exceção se + você tentar setar duas classes para o mesmo nome "importado". + + + + Observe que o elemento hibernate-mapping permite a você + aninhar diversos mapeamentos de <class> 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: Cat.hbm.xml, + Dog.hbm.xml, ou se estiver usando herança, + Animal.hbm.xml. + + + + + + class + + + Você pode declarar uma classe persistente utilizando o elemento + class: + + + + + + + + + + + + + + + + + + + + + + + + + + + ]]> + + + + name (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. + + + + + table (opcional – default para nomes de classes não + qualificadas) O nome da sua tabela do banco de dados. + + + + + discriminator-value (opcional – default para o nome da classe): + Um valor que distingue subclasses individuais, usadas para o comportamento polimorfico. + Valores aceitos incluem null e not null + + + + + mutable (opcional - valor default true): + Especifica que instancias da classe são (ou não) mutáveis + + + + + schema (opcional): Sobrepõe o nome do esquema especificado + pelo elemento root <hibernate-mapping>. + + + + + catalog (opcional): Sobrepõe o nome do catálogo especificado + pelo elemento root <hibernate-mapping>. + + + + + proxy (opcional): Especifica um interface para ser + utilizada pelos proxies de inicialização tardia. Você pode especificar o + nome da própria classe. + + + + + dynamic-update (opcional, valor default false): + Especifica que o SQL de UPDATE deve ser gerado em tempo de + execução e conter apenas aquelas colunas cujos valores foram alterados. + + + + + dynamic-insert (opcional, valor default false): + Especifica que o SQL de INSERT deve ser gerado em tempo de + execução e conter apenas aquelas colunas cujos valores não estão nulos. + + + + + select-before-update (opcional, valor default false): + Especifica que o Hibernate never deve executar um SQL de + UPDATE 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 update()), isto significa que o Hibernate ira executar + uma instrução SQL de SELECT adicional para determinar se um + UPDATE é necessário nesse momento. + + + + + polymorphism (opcional, default para implicit): + Determina se deve ser utilizado a query polimorfica implicita ou explicitamente. + + + + + where (opicional) especifica um comando SQL WHERE + arbitrário para ser usado quando da recuperação de objetos desta classe. + + + + + persister (opcional): Espeicifca uma ClassPersister + customizada. + + + + + batch-size (opcional, valor default 1) especifica um + "tamanho de lote" para a recuperação de instancias desta classe pelo identificador. + + + + + optimistic-lock (octional, valor default version): + Determina a estratégia de bloqueio. + + + + + lazy (opcional): A recuperação tardia pode ser completamente + desabilitada, setando lazy="false". + + + + + entity-name (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 + e para maiores informações. + + + + + check (opcional): Uma expressão SQL utilizada para gerar uma + constraint de verificação de múltiplas linhas para a geração + automática do esquema. + + + + + rowid (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 rowid. Um ROWID é uma implementação + que representa de maneira detalhada a localização física de uma determinada + tupla armazenado. + + + + + subselect (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. + subselect (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. + + + + + abstract (opcional): Utilizada para marcar superclasses + abstratas em hierarquias <union-subclass>. + + + + + + + É perfeitamente aceitável para uma classe persitente nomeada ser uma interface. Você deverá + então declarar as classes implementadas desta interface utilizando o elemento + <subclass>. Você pode persistir qualquer classe de aninhada + estatica. Você deverá especificar o nome da classe usando a forma + padrão, por exemplo: eg.Foo$Bar. + + + + Classes imutáveis, mutable="false", não podem ser modificadas ou excluídas + pela aplicação. Isso permite ao Hibernate fazer alguns aperfeiçoamentos de performance. + + + + O atributo opcional proxy 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. + + + Polimorfismo implícito 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 explícito 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 <class> como uma + <subclass> ou <joined-subclass>. + Para a maioria dos casos, o valor default polymorphism="implicit", + é 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). + + + + O atributo persister deixa você customizar a estratégia de persistência + utilizada para a classe. Você pode, por exemplo, especificar sua prórpia subclasse do + org.hibernate.persister.EntityPersister ou você pode criar + uma implementação completamente nova da interface + org.hibernate.persister.ClassPersister que implementa a persistência + através de, por exemplo, chamadas a stored procedeures, serialização de arquivos flat ou + LDAP. Veja org.hibernate.test.CustomPersister para um exemplo + simples (de "persistencia" para uma Hashtable). + + + + Observe que as configurações dynamic-update e + dynamic-insert não sao herdadas pelas subclasses e assim podem tambem + ser especificadas em elementos <subclass> or + <joined-subclass>. Estas configurações podem incrementar a + performance em alguns casos, mas pode realmente diminuir a performance em outras. + Use-as de forma bastante criteriosa. + + + + O uso de select-before-update 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 + Session. + + + + Se você ativar dynamic-update, você terá de escolher + a estratégia de bloqueio otimista: + + + + + version verifica a versão e a hora das colunas + + + + + all cverifica todas as colunas + + + + + dirty verifica as colunas modificadas, permitindo + alguns updates concorrentes + + + + + none não utiliza o bloqueio otimista + + + + + Nós recomendamos 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 Session.merge() é utilizado). + + + + + 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: + + + + + select item.name, max(bid.amount), count(*) + from item + join bid on bid.item_id = item.id + group by item.name + + + + + ... +]]> + + + 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 <subselect> está disponível tanto como um + atributo como um elemento mapeado nested. + + + + + + id + + + Classes mapeadas precisam 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 + <id> define o mapeamento desta propriedade para a chave primária. + + + + + + + + + + + + node="element-name|@attribute-name|element/@attribute|." + + +]]> + + + + name (opcional): O nome do identificador. + + + + + type (opcional): Um nome que indica o tipo no Hibernate. + + + + + column (opcional – default para o a propridade name): O + nome coluna chave primaria. + + + + + unsaved-value (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. + + + + + access (opcional - valor default property): A + estratégia que o Hiberante deve utilizar para acessar o valor da propriedade + + + + + + + Se o atributo name não for declarado, assume-se que a classe não tem + a propriedade de identificação. + + + + O atributo unsaved-value não é mais necessário no Hibernate 3. + + + + Há declaração alternativa <composite-id> permite o acesso a + dados legados com chaves compostas. Nós desencorajamos fortemente o seu uso por + qualquer pessoa. + + + + Generator + + + O elemento filho opcional <generator> 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 <param>. + + + + + uid_table + next_hi_value_column + +]]> + + + Todos os generators implementam a interface org.hibernate.id.IdentifierGenerator. + 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: + + + increment + + + gera identificadores dos tipos long, short ou + int que são unicos apenas quando nenhum outro processo está + inserindo dados na mesma tabela. Não utilize em ambientes + de cluster. + + + + + identity + + + suporta colunas de identidade em DB2, MySQL, MS SQL Server, Sybase e + HypersonicSQL. O identificador retornado é do tipo long, + short ou int. + + + + + sequence + + + utiliza uma sequence em DB2, PostgreSQL, Oracle, SAP DB, McKoi ou um + generator no Interbase. O identificador de retorno é do tipo + long, short ou int. + + + + + hilo + + + utiliza um algoritmo hi/lo para gerar de forma eficiente identificadores do tipo + long, short ou int, + a partir de uma tabela e coluna fornecida (por default + hibernate_unique_key e next_hi) + como fonte para os valores hi. O algoritmo hi/lo gera identificadores que são + únicos apenas para um banco de dados particular. + + + + + seqhilo + + + utiliza um algoritmo hi/lo para gerar de forma eficinete identificadores do tipo + long, short ou int, + a partir de uma sequence de banco de dados fornecida. + + + + + uuid + + + 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. + + + + + guid + + + utiliza um string GUID gerado pelo banco de dados no MS SQL Server + e MySQL. + + + + + native + + + seleciona entre identity, sequence + ou hilo dependendo das capacidades do banco de dados + utilizado. + + + + + assigned + + + deixa a aplicação definir um identificador para o objeto antes que o + save() seja chamado. Esta é a estratégia default + se nenhum elemento <generator> é especificado. + + + + + select + + + 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. + + + + + foreign + + + utiliza o identificador de um outro objeto associado. Normalmente utilizado + em conjunto com uma associaçõa de chave primária do tipo + <one-to-one>. + + + + + sequence-identity + + + 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. + + + + + + + + + + Algoritmo Hi/lo + + Os geradores hilo e seqhilo 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). + + + + + hi_value + next_value + 100 + +]]> + + + + hi_value + 100 + +]]> + + + Infelizemente, voce não pode utilizar hilo quando estiver + fornecendo sia propria Connection 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 + hibernate.transaction.manager_lookup_class. + + + + + UUID algorithm + + 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. + + + + + Colunas de identidade e sequencias + + Para bancos de dados que suportam colunas de identidade (DB2, MySQL, Sybase, + MS SQL), você pode utilizar uma geração de chave identity. + Para bancos de dados que suportam sequencias (DB2, Oracle, PostgreSQL, Interbase, + McKoi, SAP DB) voce pode utilizar a geração de chaves no estilo + sequence. As duas estratégias requerem duas consultas SQL + para inserir um novo objeto. + + + + + person_id_sequence + +]]> + + + +]]> + + + Para desenvolvimento multi-plataforma, a estratégia native + irá escolher entre as estratégias i identity, + sequence e hilo, dependendo das + capacidades do banco de dados utilizado. + + + + + Identificadores especificados + + Se você quer que a aplicação especifique os identificadores + (em vez do Hibernate gerá-los) você deve utilizar o gerador + assigned. 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 <generator>. + + + + Escolher o gerador assigned faz com que o Hibernate + utilize unsaved-value="undefined", 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 Interceptor.isUnsaved(). + + + + + Chaves primárias geradas por triggers + + Apenas para sistemas legados (o Hibernate nao gera DDL com triggers). + + + + + socialSecurityNumber + +]]> + + + No exemplo acima, há uma única propriedade com valor nomeada + socialSecurityNumber definida pela classe, + uma chave natural, e uma surrogate key nomeada + person_id cujo valor é gerado pro uma trigger. + + + + + + + Enhanced identifier generators + + + 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. + + + + The first of these new generators is org.hibernate.id.enhanced.SequenceStyleGenerator + which is intended firstly as a replacement for the sequence generator and secondly as + a better portability generator than native (because native + (generally) chooses between identity and sequence which have + largely different semantics which can cause subtle isssues in applications eyeing portability). + org.hibernate.id.enhanced.SequenceStyleGenerator 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 native 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: + + + + sequence_name (optional, defaults to hibernate_sequence): + The name of the sequence (or table) to be used. + + + + + initial_value (optional, defaults to 1): The initial + value to be retrieved from the sequence/table. In sequence creation terms, this is analogous + to the clause typical named "STARTS WITH". + + + + + increment_size (optional, defaults to 1): 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". + + + + + force_table_use (optional, defaults to false): Should + we force the use of a table as the backing structure even though the dialect might support + sequence? + + + + + value_column (optional, defaults to next_val): Only + relevant for table structures! The name of the column on the table which is used to + hold the value. + + + + + optimizer (optional, defaults to none): + See + + + + + + The second of these new generators is org.hibernate.id.enhanced.TableGenerator which + is intended firstly as a replacement for the table generator (although it actually + functions much more like org.hibernate.id.MultipleHiLoPerTableGenerator) and secondly + as a re-implementation of org.hibernate.id.MultipleHiLoPerTableGenerator 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: + + + + table_name (optional, defaults to hibernate_sequences): + The name of the table to be used. + + + + + value_column_name (optional, defaults to next_val): + The name of the column on the table which is used to hold the value. + + + + + segment_column_name (optional, defaults to sequence_name): + 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. + + + + + segment_value (optional, defaults to default): + The "segment key" value for the segment from which we want to pull increment values for + this generator. + + + + + segment_value_length (optional, defaults to 255): + Used for schema generation; the column size to create this segment key column. + + + + + initial_value (optional, defaults to 1): + The initial value to be retrieved from the table. + + + + + increment_size (optional, defaults to 1): + The value by which subsequent calls to the table should differ. + + + + + optimizer (optional, defaults to ): + See + + + + + + + + Identifier generator optimization + + 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 + ( support this notion. + + + + none (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. + + + + + hilo: 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 + increment_size is multiplied by that value in memory to define a group + "hi value". + + + + + pooled: like was discussed for hilo, 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. increment_size + here refers to the values coming from the database. + + + + + + + + + composite-id + + + node="element-name|." + + + + ...... +]]> + + + Para tabelas com uma chave composta, você pode mapear múltiplas propriedades + da classe como propriedades de identificação. O elemento + <composite-id> aceita o mapeamento da propriedade + <key-property> e mapeamentos + <key-many-to-one>como elements filhos. + + + + + +]]> + + + Sua classe persistente precisa sobre escrever + equals() e hashCode() para implementar + identificadores compostos igualmente. E precisa também implementar + Serializable. + + + + 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 load() + para o estado persistente associado com uma chave composta. Nos chamamos esta + solução de identificador composto embedded e não aconselhamos + para aplicações sérias. + + + + Uma segunda solução é o que podemos chamar de identificador composto + mapped quando a propriedades de identificação nomeadas dentro do + elemento <composite-id> estão duplicadas tando na classe + persistente como em uma classe de identificação separada. + + + + + +]]> + + + No exemplo, ambas as classes de identificação compostas, MedicareId, + e a própria classe entidade tem propriedades nomeadas medicareNumber + e dependent. A classe identificadora precisa sobrepor + equals() e hashCode() e implementar + Serializable. A desvantagem desta solução é obvia – + duplicação de código. + + + + Os seguintes atributos ão utilizados para especificar o mapeamento de + um identificador composto: + + + + + + mapped mapped (opcional, valor default false + ): 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. + + + + + class (opcional, mas requerida para um identificar composto + mapeado): A classe usada como um identificador composto. + + + + + + Nós iremos descrever uma terceira e as vezes mais conveniente solução, onde o + identificador composto é implementado como uma classe componente na + . Os atributos descritos abaixo aplicam-se + apenas para esta solução: + + + + + + name (opcional, requerida para esta solução): Uma + propriedade do tipo componente que armazena o identificador composto + (veja capítulo 9) + + + + + access (opcional - valor default property): + A estartégia Hibernate que deve ser utilizada para acessar o valor da propriedade. + + + + + class (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). + + + + + + Esta terceira solução, um componente de identificação, é o que nós + recomendamos para a maioria das aplicações. + + + + + + discriminator + + + O elemento <discriminator> é 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: string, + character, integer, byte, + short, boolean, + yes_no, true_false. + + + + + + + + + + + ]]> + + + + column (opcional - valor default class) + o nome da coluna discriminadora + + + + + type (opcional - valor default string) + o nome que indica o tipo Hibernate + + + + + force (opcional - valor default false) + "força" o Hibernate a especificar valores discriminadores permitidos mesmo + quando recuperando todas as instancias da classe root. + + + + + insert (opcional - valor default para true) + sete isto para false se sua coluna discriminadora é também + parte do identificador composto mapeado. (Diz ao Hibernate para não incluir a + coluna em comandos SQL INSERTs). + + + + + formula (opcional) uma expressão SQL arbitraria que é e + xecutada quando um tipo tem que ser avaliado. Permite discriminação baseada + em conteúdo. + + + + + + + Valores atuais de uma coluna discriminada são especificados pelo atributo + discriminator-value da <class> + e elementos da <subclass>. + + + + O atributo force é 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. + + + + Usando o atributo formula voce pode declarar uma expressão SQL + arbitrária que sera utilizada para avaliar o tipo de uma linha : + + + ]]> + + + + + version (optional) + + + O elemento <version> é opcional e indica que a tabela + possui dados versionados. Isto é particularmente útil se você planeja utilizar + transações longas (veja abaixo): + + + + + + + + + + + + + ]]> + + + + column (opcional - default a a propriedade name): O nome da + coluna mantendo o numero da versão + + + + + name: O nome da propriedade da classe persistente. + + + + + type (opcional - valor default para integer): + O tipo do numero da versão + + + + + access (opcional - valor default property): + A estratégia Hibernate que deve ser usada para acessar o valor da propriedade. + + + + + unsaved-value (opcional – valor default para undefined + ): 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. ((undefined especifica + que o valor da propriedade de identificação deve ser utilizado). + + + + + generated (optional - defaults to never): + Specifies that this version property value is actually generated by the database. + See the discussion of generated properties. + generated (opcional - valor default never): + Especifica que valor para a propriedade versão é na verdade gerado pelo banco de + dados. Veja a discussão da Seção + generated properties. + + + + + insert (opcional - valor default para true): + Especifica se a coluna de versão deve ser incluída no comando SQL de insert. + Pode ser configurado como false se a coluna do banco de dados + está definida com um valor default de 0. + + + + + + + Números de versão podem ser dos tipos Hibernate long, + integer, short, timestamp ou + calendar. + + + + 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 unsaved-value. 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! + + + + + timestamp (optional) + + + O elemento opcional <timestamp> 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. + + + + + + + + + + + + ]]> + + + + column (opcional - valor default para a propriedade name): + O nome da coluna que mantem o timestamp. + + + + + name: O nome da propriedade no estilo JavaBeans do + tipo Date ou Timestamp da classe + persistente Java. + + + + + access (opcional - valor default para property): + A estretagia Hibernate que deve ser utilizada para acessar o valor da propriedade. + + + + + unsaved-value (opcional - valor default null): + 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. (undefined especifica que um valor de + propriedade de identificação deve ser utilizado) + + + + + source (opcional - valor default para vm): + 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 + Dialects 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) + + + + + generated (opcional - valor default never): + Especifica que o valor da propriedade timestamp é gerado pelo banco de dados. + Veja a discussão generated properties. + + + + + + + Observe que <timestamp> é equivalente a + <version type="timestamp">. E + <timestamp source="db"> é equivalente a + <version type="dbtimestamp">. + + + + + + property + + + O elemento <property> declara uma propriedade + persistente de uma classe, no estilo JavaBean. + + + + + + + + + + + + + + + + + + + + ]]> + + + + name: o nome da propriedade, iniciando com letra minúscula. + + + + + column (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) <column> aninhados. + + + + + + type (opcional): um nome que indica o tipo Hibernate. + + + + + update, insert (opcional - valor default true): + especifica que as colunas mapeadas devem ser incluidas nas instruções SQL de + UPDATE e/ou INSERT . Setar ambas para to + false 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. + + + + + formula (opcional): uma expressão SQL que definie o valor para + uma propriedade calculada. Propriedades calculadas nao tem + uma coluna de mapeamento para elas. + + + + + access (opcional – valor default property): + A estratégia que o Hibernate deve utilizar para acessar o valor da propriedade + + + + + lazy (opcional - valor default para false): + 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). + + + + + unique (opcional): Habilita a geração de DDL de uma + unica constraint para as colunas. Assim, permite que isto seja o + alvo de uma property-ref. + + + + + not-null (opcional): Habilita a geração de DDL de uma + constraint de nulidade para as colunas. + + + + + optimistic-lock (opcional - valor default true): + 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. + + + + + generated (opcional - valor default never): + Especifica que o valor da propriedade é na verdade gerado pelo banco de dados. + Veja a discussão da seção + generated properties. + + + + + + + typename pode ser: + + + + + + The name of a Hibernate basic type (eg. integer, string, character, + date, timestamp, float, binary, serializable, object, blob). + O nome do tipo basico do Hibernate (ex., integer, string, character, + date, timestamp, float, binary, serializable, object, blob). + + + + + O nome da classe Java com um tipo básico default (ex. int, float, + char, java.lang.String, java.util.Date, java.lang.Integer, java.sql.Clob). + + + + + O nome da classe Java serializable + + + + + O nome da classe de um tipo customizado (ex. com.illflow.type.MyCustomType). + + + + + + 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 type. (Por exemplo, para distinguir entre + Hibernate.DATE ou Hibernate.TIMESTAMP, + ou para espcificar uma tipo ciustomizado.) + + + + O atributo access 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 access="field", + 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 + org.hibernate.property.PropertyAccessor. + + + + 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 + SELECT de uma subquery daquery SQL que carrega a instancia: + + + ]]> + + + 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 ( + customerId no exemplo dado). Observe tambem que voce pode usar o + mapeamento de elemento aninhado <formula>, se você não + gostar de usar o atributo. + + + + + + many-to-one + + + Uma associação ordinária para outra classe persistente é declarada usando o + elemento many-to-one. O modelo relacional é uma + associação many-to-one: a uma chave estrangeira de uma tabela referenciando + a chave primaria da tabela destino. + + + + + + + + + + + + + + + + + + + + + + + + ]]> + + + + name: O nome da propriedade. + + + + + column (opcional): O nome da coluna foreign key. Isto + pode também ser especificado através de elementos aninhados + <column>. + + + + + class (opcional – default para o tipo de propriedade + determinado pela reflexão). O nome da classe associada. + + + + + cascade (opcional): Especifica quais operações dever + ser em cascata do objeto pai para o objeto associado. + + + + + fetch (opcional - default para select): + Escolhe entre recuperação outer-join ou recuperação seqüencial. + + + + + update, insert (opcional - valor default true): + especifica que as colunas mapeadas dever ser incluidas em instruções SQL de + UPDATE e/ou INSERT. Setando ambas para + false 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. + + + + + property-ref: (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. + + + + + access (opcional - valor default property): A + estrategia que o Hibernate deve utilizar para acessar o valor da propriedade. + + + + + unique (opcional): Habilita a geração DDL de uma constraint + unique para a coluna foreign-key. Alem disso, permite ser o alvo de uma + property-ref. Isso torna a associação multipla + efetivamente um para um. + + + + + not-null (opcional): Habilita a geração DDL de uma constraint de + nulidade para as foreign keys. + + + + + optimistic-lock (opcional - valor default true): + 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. + + + + + lazy(opcional – valor default proxy): + Por default, associações de ponto unico são envoltas em um proxie. + lazy="no-proxy" 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) + lazy="false" especifica que a associação será + sempre recuperada fortemente. + + + + + not-found (opcional - valor default exception): + Especifica como as foreign keys que referenciam linhas ausentes serão tratadas: + ignore irá tratar a linha ausente como ama associaççao de null + + + + + entity-name (opcional): O nome da entidade da classe associada. + + + + + + formula (optional): Uma expressão SQL que define um valor + para um foreign key computed. + + + + + + Setar o valor do atributo cascade para qualquer valor + significativo diferente de none irá propagar certas operações + ao objeto associado. Os valores significativos são os nomes das operações básicas + do Hibernate, persist, merge, delete, save-update, evict, replicate, lock, + refresh, assim como os valores especiais delete-orphan + e all e combinações de nomes de operações separadas por vírgula, + como por exemplo, cascade="persist,merge,evict" ou + cascade="all,delete-orphan". Veja a seção + 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. + + + + Uma típica declaração muitos-pra-um se parece com esta: + + + ]]> + + + O atributo property-ref 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 Product tenha um número + seqüencial exclusivo, que não é a chave primária. (O atributo unique + controla a geração de DDL do Hibernate com a ferramenta SchemaExport.) + + + ]]> + + + Então o mapeamento para OrderItem poderia usar: + + + ]]> + + + Porém, isto obviamente não é indicado, nunca. + + + + Se a chave exclusiva referenciada engloba múltiplas propriedades da entidade associada, + você deve mapear as propriedades referenciadas dentro de um elemento chamado + <properties> + + + + + Se a chave exclusiva referenciada é a propriedade de um componente, você pode especificar + um caminho para a propriedade. + + + ]]> + + + + + one-to-one (um-pra-um) + + + Uma associação um-pra-um para outra classe persistente é declarada usando + um elemento one-to-one . + + + + + + + + + + + + + + + + ]]> + + + + name: O nome da propriedade. + + + + + class (opcional – default para o tipo da propriedade + definido via reflection): O nome da classe associada. + + + + + cascade (opcional): Especifica qual operação deve + ser cascateada do objeto pai para o objeto associado. + + + + + constrained (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 save() e + delete() são cascateadas, e determina se a associação + pode ser substituída (isto também é usado pela ferramenta schema export). + + + + + fetch ((opcional – valor default select): + Escolhe entre outer-join fetching ou sequential select fetching. + + + + + property-ref(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. + + + + + access (opcional - valor default padrão property): + A estratégia que o Hibernate pode usar para acessar o valor da propriedade. + + + + + formula (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 org.hibernate.test.onetooneformula + para exemplo). + + + + + lazy (opcional – valor default proxy): + Por default, associações single point são proxied. lazy="no-proxy" + especifica que a propriedade deve ser fetched lazily quando o atributo é acessado + pela primeira vez (requer build-time bytecode instrumentation). + lazy="false" especifica que a associação vai sempre ser + avidamente fetched. Note que se constrained="false", + proxing é impossível e o Hibernate vai ávido fetch a associação! + + + + + entity-name (opcional): O nome da entidade da classe associada. + + + + + + + Existem duas variedades de associações um-pra-um: + + + + associações de chave primária + + + associações de chave estrangeira exclusiva + + + + + 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 uma associação de chave primária, adicione os seguintes mapeamentos em + Employee e Person, respectivamente. + + + ]]> + ]]> + + + 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 foreign: + + + + + + employee + + + ... + +]]> + + + Uma nova instância de Person salva recentemente é então assinada + com o mesmo valor da chave primária da instância de employee referenciada + com a propriedade employee daquela Person. + + + + Alternativamente, uma chave estrangeira com uma unique constraint, de + Employee para Person, pode ser expressa como: + + + ]]> + + + E esta associação pode ser feita de forma bi-direcional adicionando o seguinte + no mapeamento de Person: + + + ]]> + + + + + natural-id + + + + + ...... +]]> + + + 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 <natural-id>. O Hibernate irá gerar a chave + exclusiva necessária e as constraints de nullability , e seu mapeamento será + apropriadamente auto documentado. + + + + Nós recomendamos com enfase que você implemente equals() e + hashCode() para comparar as propriedades da chave natural da + entidade. + + + + Este mapeamento não tem o objetivo de uso com entidades com natural chaves primárias. + + + + + + mutable mutable (opcional, valor defaultfalse): + Por default, propriedades naturais identificadoras são consideradas imutáveis (constante). + + + + + + + + componente, componente dinâmico + + + O elemento<component> 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. + + + + + + + + + + + + + + + + + + ........ +]]> + + + + name: O nome da propriedade. + + + + + class (opcional – valor default para o tipo de + propriedade determinada por reflection): O nome da classe (filha) do + componente. + + + + + insert: As colunas mapeadas aparecem nos + SQL de INSERTs? + + + + + update: As colunas mapeadas aparecem nos + SQL de UPDATEs? + + + + + access (opcional – valor default property): + A estratégia que o Hibernate pode usar para acessar o valor da propriedade. + + + + + lazy (opcional - valor default false): + Especifica que este componente deve ser fetched lazily quando o atributo for + acessado pela primeira vez (requer build-time bytecode instrumentation). + + + + + optimistic-lock (opcional – valor default true): + 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. + + + + + unique (opcional – valor default false): + Especifica que existe uma unique constraint em todas as colunas mapeadas do + componente. + + + + + + + A tag filha <property> acrescenta a propriedade + de mapeamento da classe filha para colunas de uma tabela. + + + + O elemento <component> permite um sub-elemento + <parent> mapeie uma propriedade da classe do componente + como uma referencia de volta para a entidade que o contém. + + + + O elemento <dynamic-component> permite que um + Map possa ser mapeado como um componente onde os nomes das + propriedades referem-se para as chaves no mapa, veja + . + + + + + + propriedades + + + O elemento <properties> 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 + property-ref. É também um modo conveninente para definir uma + unique constraint de múltiplas colunas. + + + + + + + + + + + + + + + ........ +]]> + + + + name:: O nome lógico do agrupamento – + não é o nome atual de propriedade. + + + + + insert: As colunas mapeadas aparecem nos + SQL de INSERTs? + + + + + update: As colunas mapeadas aparecem nos + SQL de UPDATEs? + + + + + optimistic-lock (opcional – valor default true): + 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. + + + + + unique (opcional – valor defautl false): + Especifica que uma unique constraint existe em todas as colunas mapeadas do componente. + + + + + + + Por exemplo, se nós temos o seguinte mapeamento de <properties>: + + + + + ... + + + + + +]]> + + + Então nós podemos ter uma associação de dados herdados que referem a esta chave + exclusiva da tabela Person, ao invés de se referirem a chave + primária: + + + + + + +]]> + + + Nós não recomendamos o uso deste tipo de coisa fora do contexto de mapeamento de + dados herdados. + + + + + + subclass (subclasse) + + + 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 <subclass> + deve ser usada. + + + + + + + + + + + + + ..... +]]> + + + + name: O nome de classe completamente qualificada da subclasse. + + + + + discriminator-value (opcional – valor default o nome da classe): + Um valor que distingue subclasses individuais. + + + + + proxy (opcional): Especifica a classe ou interface que + usará os proxies de inicialização atrasada. + + + + + lazy (opcional, valor default true): + Configurar lazy="false" desabilitará o uso de + inicialização atrasada. + + + + + + Cada subclasse deve declarar suas próprias propriedades persistentes e subclasses. + As propriedades <version> e <id> + são configuradas para serem herdades da classe raiz. Cada subclasse numa hierarquia + deve definir um único discriminator-value. Se nenhum for + especificado, o nome da classe Java completamente qualificada será usada. + + + + Para informações sobre mapeamento de heranças, veja o . + + + + + + joined-subclass + + + 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 + <joined-subclass>. + + + + + + + + + + + + + + + ..... +]]> + + + + name: O nome da classe completamente qualificada da + subclasse. + + + + + table: O nome da tabela da subclasse. + + + + + proxy (opcional): Especifica a classe ou interface + para usar os proxies de recuperação atrasada. + + + + + lazy (opcional, valor default true): + Fixanr lazy="false" desabilita o uso recuperação + atrasada. + + + + + + + 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 <key>. O mapeamento no início do + capítulo poderia ser re-escrito assim: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +]]> + + + Para informações de mapeamentos de herança, veja . + + + + + + union-subclass + + + 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 + <class> 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 <union-subclass>. + + + + + + + + + + + + + + ..... +]]> + + + + name: O nome da subclasse completamente qualificada. + + + + + table: O nome da tabela da subclasse. + + + + + proxy (optional): Specifies a class or interface to use + for lazy initializing proxies. + + proxy (opcional): Especifica a classe ou interface para usar + os proxies de recuperação atrasada. + + + + + lazy (optional, defaults to true): Setting + lazy="false" disables the use of lazy fetching. + lazy (opcional, valor default ptrue): + Fixando lazy="false" desabilita o uso da recuperação atrasada. + + + + + + + A coluna discriminatõria não é requerida para esta estratégia de mapeamento. + + + + + Para informações sobre mapeamentos de herança, veja . + + + + + + join + + + Usando o elemento <join>>, é possível mapear + propriedades de uma classe para várias tabelas. + + + + + + + + + + + + + + + + + ... +]]> + + + + + table: O nome da tabela associada. + + + + + schema (opcional): Sobrepõe o nome do esquema + especificado pelo elemento raiz <hibernate-mapping>. + + + + + catalog (opcional): Sobrepõe o nome do catálogo + especificado pelo elemento raiz<hibernate-mapping>. + + + + + fetch(opcional – valor default join): Se setado + para join, o padrão, o Hibernate irá usar um inner join para + restaurar um join definido por uma classe ou suas subclasses e + uma outer join para um join definido por uma subclasse. + Se setado para select, então o Hibernate irá usar uma seleção + seqüencial para um <join> 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 + <join> definido pela classe e suas superclasses. + + + + + inverse (opcional – valor default false): + Se habilitado, o Hibernate não irá tentar inserir ou atualizar as propriedades + definidas por este join. + + + + + optional (opcional – valor default false): + 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. + + + + + + + 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): + + + + + ... + + + + + + + + ...]]> + + + 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. + + + + + + key + + + Nós vimos que o elemento <key> 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. + + + + + + + + + + + + ]]> + + + + . + column (opcional): O nome da coluna da chave estrangeira. + Isto também pode ser especificado por aninhamento de elemento(s) + <column>. + + + + + on-delete (opcional, valor default noaction): + Especifica se a constraint da chave estrangeira no banco de dados esta + habilitada para cascade delete . + + + + + property-ref (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.) + + + + + not-null (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). + + + + + update (optional): Specifies that the foreign key should never + be updated (this is implied whenever the foreign key is also part of the primary + key). + update (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). + + + + + unique (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). + + + + + + + Nós recomendamos que para sistemas que a performance de delete seja importante, todas as + chaves deve ser definida on-delete="cascade", e o Hibernate irá usar + uma constraint a nível de banco de dados ON CASCADE DELETE, ao invés + de muitas instruções DELETE. Esteja ciente que esta característica é + um atalho da estratégia usual de optimistic locking do Hibernate para dados versionados. + + + + Os atributos not-null e update 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ê + deve declarar a coluna chave usando + <key not-null="true">. + + + + + + elementos column e formula + + Qualquer elemento de mapeamente que aceita um atributo column irá + aceitar alternativamente um subelemento <column>. Da mesma forma, + formula é uma alternativa para o atributo formula. + + + ]]> + + SQL expression]]> + + + O atributo column e formula podem até ser combinados + dentro da mesma propriedade ou associação mapeando para expressar, + por exemplo, associações exóticas. + + + + + 'MAILING' +]]> + + + + + import + + + 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 auto-import="true". + Você pode até importar classes e interfaces que não estão explicitamente mapeadas. + + + ]]> + + + + + + + ]]> + + + + class: O nome qualificado (do pacote) de qualquer classe Java. + + + + + rename (opcional – valor default, o nome da classe não + qualificada): Um nome que pode ser usado numa linguagem de consulta. + + + + + + + + + any + + + Existe mais um tipo de propriedade de mapeamento. O elemento de mapeamento + <any> 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). + + + + + O atributo meta-type 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 id-type. Você deve especificar + o mapeamento de valores do meta-type para nome de classes. + + + + + + + + +]]> + + + + + + + + + + + + + + ..... + + + ..... +]]> + + + + name: o nome da propriedade. + + + + + id-type: o tipo identificador. + + + + + meta-type (opcional – valor default string): + Qualquer tipo que é permitido para um mapeamento discriminador. + + + + + cascade (opcional – valor default none): + o estilo do cascade. + + + + + access (opcional – valor default property): + A estratégia que o hibernate deve usar para acessar o valor da propriedade. + + + + + optimistic-lock (opcional - valor defaulttrue): + 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. + + + + + + + + + + + Tipos do Hibernate + + + Entidades e valores + + + 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. + + + + Uma entidade 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 cascata 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. + + + + Uma entidade em estado persistente consiste de referências para outras entidades + e instâncias de tipos de valor. 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) + são 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. + + + + + 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 + componente é uma classe de usuário definida com valores + semânticos. Uma propriedade de Java de tipo java.lang.String + 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. + + + + Nós iremos rever ambos os conceitos durante toda a documentação. + + + + + 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 + <class>, <subclass> e assim por diante. + Para tipos de valores nós usamos <property>, + <component>, etc, geralmente com um atributo + type. O valor deste atributo é o nome de um tipo de + mapeamento 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. + + + + Todos os tipos internos do hibernate exceto coleções suportam semânticas nulas. + + + + + + + Valores de tipos básicos + + + O tipos internos de mapeamentos básicos podem ser a grosso modo categorizado como: + + + integer, long, short, float, double, character, byte, + boolean, yes_no, true_false + + + Tipos de mapeamentos de classes primitivas ou wrapper Java especificos + (vendor-specific) para tipos de coluna SQL. Boolean, + boolean, yes_no são todas codificações alternativas + para um boolean ou java.lang.Boolean + do Java. + + + + + string + + + Um tipo de mapeamento de java.lang.String para + VARCHAR (ou VARCHAR2 no Oracle). + + + + + date, time, timestamp + + + Tipos de mapeamento de java.util.Date e suas + subclasses para os tipos SQL DATE, + TIME e TIMESTAMP + (ou equivalente). + + + + + calendar, calendar_date + + + Tipo de mapeamento de java.util.Calendar para + os tipos SQL TIMESTAMP e + DATE (ou equivalente). + + + + + big_decimal, big_integer + + + Tipo de mapeamento de java.math.BigDecimal and + java.math.BigInteger para NUMERIC + (ou NUMBER no Oracle). + + + + + locale, timezone, currency + + + Tipos de mapeamentos de java.util.Locale, + java.util.TimeZone e java.util.Currency + para VARCHAR (ou VARCHAR2 no Oracle). + Instâncias de f Locale e Currency + são mapeados para seus códigos ISO. Instâncias de TimeZone + são mapeados para seu ID. + + + + + class + + + um tipo de mapeamento de java.lang.Class para + VARCHAR (ou VARCHAR2 no + Oracle). Uma Class é mapeada pelo + seu nome qualificado (completo). + + + + + binary + + + Mapeia arrays de bytes para um tipo binário de SQL apropriado. + + + + + text + + + Maps long Java strings to a SQL CLOB or + TEXT type. + Mapeia strings longas de Java para um tipo SQL + CLOB ou TEXT. + + + + + serializable + + + Mapeia tipos Java serializáveis para um tipo binário SQL apropriado. + Você pode também indicar o tipo serializable do + Hibernate com o nome da classe ou interface Java serializável que + não é padrão para um tipo básico. + + + + + clob, blob + + + Tipos de mapeamentos para as classes JDBC java.sql.Clob and + java.sql.Blob. 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.) + + + + + + imm_date, imm_time, imm_timestamp, imm_calendar, imm_calendar_date, + imm_serializable, imm_binary + + + + 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 Date.setTime() para + uma instância mapeada como imm_timestamp. Para mudar + o valor da propriedade, e ter a mudança feita persistente, a aplicação + deve atribuir um novo objeto (nonidentical) à propriedade. + + + + + + + + + Identificadores únicos das entidades e coleções podem ser de qualquer tipo + básico exceto binary, blob ou + clob. (Identificadores compostos também são permitidos, + veja abaixo.) + + + + Os tipos de valores básicos têm suas constantes Type + correspondentes definidas em org.hibernate.Hibernate. Por exemplo, + Hibernate.STRING representa o tipo string. + + + + + + Tipos de valores personalizados + + + É relativamente fácil para desenvolvedores criar seus próprios tipos de valor. + Por exemplo, você pode querer persistir propriedades do tipo + java.lang.BigInteger para colunas VARCHAR. 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 + getName()/setName() do tipo + java.lang.String que é persistido para colunas + FIRST_NAME, INITIAL, SURNAME. + + + + + Para implementar um tipo personalizado, implemente org.hibernate.UserType + or org.hibernate.CompositeUserType e declare propriedades usando o nome + qualificado da classe do tipo. Veja org.hibernate.test.DoubleStringType + para ver o tipo das coisas que são possíveis. + + + + + +]]> + + + Observe o uso da tag <column> para mapear uma propriedade + para colunas múltiplas. + + + + As interfaces CompositeUserType, EnhancedUserType, + UserCollectionType, e UserVersionType + fornecem suporte para usos mais especializados. + + + + Você pode mesmo fornecer parâmetros a um UserType no arquivo de mapeamento. + Para isto, seu UserType deve implementar a interface + org.hibernate.usertype.ParameterizedType. Para fornecer parâmetros a seu + tipo personalizado, você pode usar o elemento <type> em seus + arquivos de mapeamento. + + + + + 0 + +]]> + + + O UserType pode agora recuperar o valor para o parâmetro chamado + default da Propriedade do passado a ele. + + + + Se você usar freqüentemente um determinado UserType, pode ser útil definir + um nome mais curto para ele. Você pode fazer isto usando o elemento + <typedef>. Typedefs atribui um nome a um tipo personalizado, e pode também + conter uma lista de valores default de parâmetro se o tipo for parametrizado. + + + + 0 +]]> + + ]]> + + + 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. + + + + Even though Hibernate's rich range of built-in types and support for components means you + will very rarely need 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 MonetaryAmount class is a good + candidate for a CompositeUserType, 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. + + + + + + + + Mapping a class more than once + + It is possible to provide more than one mapping for a particular persistent class. In this + case you must specify an entity name 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. + + + + ... + + + + + + + + ... + +]]> + + + Notice how associations are now specified using entity-name instead of + class. + + + + + + SQL quoted identifiers + + 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 Dialect (usually double quotes, but brackets for SQL + Server and backticks for MySQL). + + + + + + ... +]]> + + + + + + Metadata alternatives + + + XML isn't for everyone, and so there are some alternative ways to define O/R mapping metadata in Hibernate. + + + + Using XDoclet markup + + + Many Hibernate users prefer to embed mapping information directly in sourcecode using + XDoclet @hibernate.tags. 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 Cat class with XDoclet mappings. + + + + + + See the Hibernate web site for more examples of XDoclet and Hibernate. + + + + + + Using JDK 5.0 Annotations + + + 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 EntityManager of JSR-220 (the persistence API), + support for mapping metadata is available via the Hibernate Annotations + package, as a separate download. Both EJB3 (JSR-220) and Hibernate3 metadata is supported. + + + + This is an example of a POJO class annotated as an EJB entity bean: + + + orders; + + // Getter/setter and business methods +}]]> + + + 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. + + + + + + + Generated Properties + + Generated properties are properties which have their values generated by the + database. Typically, Hibernate applications needed to refresh + 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. + + + Properties marked as generated must additionally be non-insertable and non-updateable. + Only versions, + timestamps, and + simple properties can be marked as + generated. + + + never (the default) - means that the given property value + is not generated within the database. + + + insert - 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 + version and + timestamp properties can + be marked as generated, this option is not available there... + + + always - states that the property value is generated both + on insert and on update. + + + + + Auxiliary Database Objects + + 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 java.sql.Statement.execute() + method is valid here (ALTERs, INSERTS, etc). There are essentially two modes for + defining auxiliary database objects... + + + The first mode is to explicitly list the CREATE and DROP commands out in the mapping + file: + + + ... + + CREATE TRIGGER my_trigger ... + DROP TRIGGER my_trigger + +]]> + + 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 + org.hibernate.mapping.AuxiliaryDatabaseObject interface. + + + ... + + + +]]> + + Additionally, these database objects can be optionally scoped such that they only + apply when certain dialects are used. + + + ... + + + + + +]]> + + + diff --git a/documentation/manual/pt-BR/src/main/docbook/content/batch.xml b/documentation/manual/pt-BR/src/main/docbook/content/batch.xml index 6bf66d2210..e1e73b25c9 100755 --- a/documentation/manual/pt-BR/src/main/docbook/content/batch.xml +++ b/documentation/manual/pt-BR/src/main/docbook/content/batch.xml @@ -1,360 +1,364 @@ - - Processamento de lotes - - - Uma alternativa para inserir 100.000 linhas no banco de dados usando o Hibernate - pode ser a seguinte: - - - - - - Isto irá falhar em algum lugar próximo a linha 50.000, lançando uma - OutOfMemoryException. Isso ocorre devido ao fato do Hibernate - fazer cache de todas as instâncias de Customer inseridas num - cachê em nível de sessão. - - - - 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): - - - - - - Você também pode querer rodar esse tipo de processamento de lotes com o cache - secundário completamente desabilitado: - - - - - - Mas isto não é absolutamente necessário, desde que nós possamos ajustar o - CacheMode para desabilitar a interação com o cache secundário. - - - - Inserção de lotes - - - Quando você estiver inserindo novos objetos persistentes, vocês deve executar - os métodos flush() e clear() regularmente - na sessão, para controlar o tamanho do cache primário. - - - - - - - - Batch updates - - - Para recuperar e atualizar informações a mesma idéia é válida. Adicionalmente, - pode precisar usar o scroll() para usar recursos no lado - do servidor em queries que retornam muita informação. - - - - - - - - A interface StatelessSession - - 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 StatelessSession 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. - - - - - - Veja neste exempo, as instancias de Customer retornadas pela query - são imediatamente desvinculadas. Elas nunca serão assossiadas à um contexto persistente. - - - - As operações insert(), update() e delete() - definidos pela interface StatelessSession são considerados - operações diretas no banco de dados (row-level operations), isso resulta em uma - execução imediata de comandos SQL INSERT, UPDATE ou - DELETE respectivamente. Devido a isso, eles possuem uma - semântica bem diferente das operações save(), saveOrUpdate() - ou delete() definidas na interface Session. - - - - - - Operações no estilo DML - - - 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 Data Manipulation Language - (SQL-style DML): INSERT, UPDATE, DELETE) - 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) - (HQL). - - - - A pseudo-sintaxe para expressões UPDATE e DELETE é: - ( UPDATE | DELETE ) FROM? NomeEntidade (WHERE condições_where)?. - Algumas observações: - - - - - - Na clausula from, a palavra chave FROM é opcional; - - - - - 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. - - - - - Na joins (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. - - - - - A clausula where também é opcional. - - - - - - Como exemplo para executar um HQL UPDATE, use o - método Query.executeUpdate()(o método ganhou o nome - devido a sua familiaridade com o do JDBC - PreparedStatement.executeUpdate()): - - - - - - HQL UPDATE statements, by default do not effect the - version - or the timestamp property values - for the affected entities; this is in keeping with the EJB3 specification. However, - you can force Hibernate to properly reset the version or - timestamp property values through the use of a versioned update. - This is achieved by adding the VERSIONED keyword after the UPDATE - keyword. - - - - - - Note that custom version types (org.hibernate.usertype.UserVersionType) - are not allowed in conjunction with a update versioned statement. - - - - - Para executar um HQL DELETE, use o mesmo método - Query.executeUpdate(): - - - - - - O valor int retornado pelo método Query.executeUpdate() - 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. - - - - - A pseudo-sintaxe para o comando INSERT é: - INSERT INTO EntityName properties_list select_statement. Alguns - pontos a observar: - - - - - - Apenas a forma INSERT INTO ... SELECT ... é suportada; INSERT INTO ... VALUES ... - não é suportada. - - - A lista de propriedade é análoga à especificação da coluna - do comando SQL INSERT. 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 - INSERT não são polimorficos. - - - - - 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 Tipo do Hibernate - que são equivalentes em oposição a equal. - Isso pode causar problemas nas combinações entre a propriedade definida como - org.hibernate.type.DateTypee um propriedade definida como - org.hibernate.type.TimestampType, embora o banco de dados não possa - fazer uma distinção ou possa ser capaz de manusear a conversão. - - - - - 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 - org.hibernate.id.SequenceGenerator (e suas subclasses) - e qualquer implementação de org.hibernate.id.PostInsertIdentifierGenerator. - Aqui, a exceção mais notável é o org.hibernate.id.TableHiLoGenerator, que - não pode ser usado porque ele não dispõe de mecanismos para recuperar o seu valor. - - - - - For properties mapped as either version or timestamp, - 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 seed value defined - by the org.hibernate.type.VersionType is used). - - Para propriedades mapeadas como version ou timestamp, - 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 valor semente - definido pela classe org.hibernate.type.VersionType). - - - - - - Exemplo da execução de um HQL INSERT: - - - - - - - + + Processamento de lotes + + + Uma alternativa para inserir 100.000 linhas no banco de dados usando o Hibernate + pode ser a seguinte: + + + + + + Isto irá falhar em algum lugar próximo a linha 50.000, lançando uma + OutOfMemoryException. Isso ocorre devido ao fato do Hibernate + fazer cache de todas as instâncias de Customer inseridas num + cachê em nível de sessão. + + + + 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): + + + + + + Você também pode querer rodar esse tipo de processamento de lotes com o cache + secundário completamente desabilitado: + + + + + Note that Hibernate disables insert batching at the JDBC level transparently if you + use an identiy identifier generator. + + + + Mas isto não é absolutamente necessário, desde que nós possamos ajustar o + CacheMode para desabilitar a interação com o cache secundário. + + + + Inserção de lotes + + + Quando você estiver inserindo novos objetos persistentes, vocês deve executar + os métodos flush() e clear() regularmente + na sessão, para controlar o tamanho do cache primário. + + + + + + + + Batch updates + + + Para recuperar e atualizar informações a mesma idéia é válida. Adicionalmente, + pode precisar usar o scroll() para usar recursos no lado + do servidor em queries que retornam muita informação. + + + + + + + + A interface StatelessSession + + 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 StatelessSession 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. + + + + + + Veja neste exempo, as instancias de Customer retornadas pela query + são imediatamente desvinculadas. Elas nunca serão assossiadas à um contexto persistente. + + + + As operações insert(), update() e delete() + definidos pela interface StatelessSession são considerados + operações diretas no banco de dados (row-level operations), isso resulta em uma + execução imediata de comandos SQL INSERT, UPDATE ou + DELETE respectivamente. Devido a isso, eles possuem uma + semântica bem diferente das operações save(), saveOrUpdate() + ou delete() definidas na interface Session. + + + + + + Operações no estilo DML + + + 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 Data Manipulation Language + (SQL-style DML): INSERT, UPDATE, DELETE) + 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) + (HQL). + + + + A pseudo-sintaxe para expressões UPDATE e DELETE é: + ( UPDATE | DELETE ) FROM? NomeEntidade (WHERE condições_where)?. + Algumas observações: + + + + + + Na clausula from, a palavra chave FROM é opcional; + + + + + 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. + + + + + Na joins (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. + + + + + A clausula where também é opcional. + + + + + + Como exemplo para executar um HQL UPDATE, use o + método Query.executeUpdate()(o método ganhou o nome + devido a sua familiaridade com o do JDBC + PreparedStatement.executeUpdate()): + + + + + + HQL UPDATE statements, by default do not effect the + version + or the timestamp property values + for the affected entities; this is in keeping with the EJB3 specification. However, + you can force Hibernate to properly reset the version or + timestamp property values through the use of a versioned update. + This is achieved by adding the VERSIONED keyword after the UPDATE + keyword. + + + + + + Note that custom version types (org.hibernate.usertype.UserVersionType) + are not allowed in conjunction with a update versioned statement. + + + + + Para executar um HQL DELETE, use o mesmo método + Query.executeUpdate(): + + + + + + O valor int retornado pelo método Query.executeUpdate() + 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. + + + + + A pseudo-sintaxe para o comando INSERT é: + INSERT INTO EntityName properties_list select_statement. Alguns + pontos a observar: + + + + + + Apenas a forma INSERT INTO ... SELECT ... é suportada; INSERT INTO ... VALUES ... + não é suportada. + + + A lista de propriedade é análoga à especificação da coluna + do comando SQL INSERT. 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 + INSERT não são polimorficos. + + + + + 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 Tipo do Hibernate + que são equivalentes em oposição a equal. + Isso pode causar problemas nas combinações entre a propriedade definida como + org.hibernate.type.DateTypee um propriedade definida como + org.hibernate.type.TimestampType, embora o banco de dados não possa + fazer uma distinção ou possa ser capaz de manusear a conversão. + + + + + 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 + org.hibernate.id.SequenceGenerator (e suas subclasses) + e qualquer implementação de org.hibernate.id.PostInsertIdentifierGenerator. + Aqui, a exceção mais notável é o org.hibernate.id.TableHiLoGenerator, que + não pode ser usado porque ele não dispõe de mecanismos para recuperar o seu valor. + + + + + For properties mapped as either version or timestamp, + 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 seed value defined + by the org.hibernate.type.VersionType is used). + + Para propriedades mapeadas como version ou timestamp, + 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 valor semente + definido pela classe org.hibernate.type.VersionType). + + + + + + Exemplo da execução de um HQL INSERT: + + + + + + + diff --git a/documentation/manual/pt-BR/src/main/docbook/content/best_practices.xml b/documentation/manual/pt-BR/src/main/docbook/content/best_practices.xml index f23de050c8..f3ec3eec59 100755 --- a/documentation/manual/pt-BR/src/main/docbook/content/best_practices.xml +++ b/documentation/manual/pt-BR/src/main/docbook/content/best_practices.xml @@ -1,7 +1,7 @@ - + Boas práticas diff --git a/documentation/manual/pt-BR/src/main/docbook/content/collection_mapping.xml b/documentation/manual/pt-BR/src/main/docbook/content/collection_mapping.xml index 7ffb4ab4d7..9eb4b77f33 100755 --- a/documentation/manual/pt-BR/src/main/docbook/content/collection_mapping.xml +++ b/documentation/manual/pt-BR/src/main/docbook/content/collection_mapping.xml @@ -1,7 +1,7 @@ - + Mapeamento de Coleções diff --git a/documentation/manual/pt-BR/src/main/docbook/content/component_mapping.xml b/documentation/manual/pt-BR/src/main/docbook/content/component_mapping.xml index a55677a2a2..3006500a93 100755 --- a/documentation/manual/pt-BR/src/main/docbook/content/component_mapping.xml +++ b/documentation/manual/pt-BR/src/main/docbook/content/component_mapping.xml @@ -1,7 +1,7 @@ - + Mapeamento de Componentes diff --git a/documentation/manual/pt-BR/src/main/docbook/content/configuration.xml b/documentation/manual/pt-BR/src/main/docbook/content/configuration.xml index 3ed3672849..504f11a9b2 100755 --- a/documentation/manual/pt-BR/src/main/docbook/content/configuration.xml +++ b/documentation/manual/pt-BR/src/main/docbook/content/configuration.xml @@ -1,1792 +1,1789 @@ - - - Configuração - - - 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 hibernate.properties - de exemplo no etc/ que mostra várias opções. Apenas coloque o arquivo - de exemplo no seu classpath e personalize-o. - - - - 1.11 Configuração programática - - - Uma instância de org.hibernate.cfg.Configuration - representa um conjunto inteiro de mapeamentos de tipos Java da aplicação para - um banco de dados SQL. O Configuration é usado para construir - uma SessionFactory (imutável). Os mapeamentos são compilados - a partir de arquivos de mapeamento XML. - - - - - Você pode obter uma instância Configuration intanciando- - o diretamente e especificando documentos de mapeamento XML. Se o arquivo - de mapeamento estão no classpath, use use addResource(): - - - - - - Uma alternativa (às vezes melhor) é especificar a classe mapeada, - e permitir que o Hibernate encontre o documento de mapeamento para você: - - - - - - Então o Hibernate procurará pelos arquivos de mapeamento chamados - /org/hibernate/auction/Item.hbm.xml e - /org/hibernate/auction/Bid.hbm.xml no classpath. - Esta abordagem elimina qualquer nome de arquivo de difícil compreensão. - - - - Uma Configuration também permite você especificar - propriedades de configuração: - - - - - - Este não é o único caminho para passar as propriedades de configuração - para o Hibernate. As várias opções incluem: - - - - - - Passar uma instância de java.util.Properties - para Configuration.setProperties(). - - - - - Colocar hibernate.properties no diretório - raiz do classpath. - - - - - Determinar as propriedades do System - usando java -Dproperty=value. - - - - - Include <property> elements in - hibernate.cfg.xml (discussed later). - Incluir elementos <property> no - hibernate.cfg.xml (discutido mais tarde). - - - - - - hibernate.properties é o caminho mais facil - se você quer começar mais rápido. - - - - O Configuration é entendido como um objeto startup-time, - é descartado uma vez que a SessionFactory é criada. - - - - - - Obtendo uma SessionFactory - - - Quando todos os mapeamentos têm sido analisados pelo Configuration, - a aplicação deve obter uma factory para as instâncias da Session. - O objetivo desta factory é ser compartilhado por todas as threads da aplicação: - - - - - - Hibernate permite sua aplicação instanciar mais do que uma - SessionFactory. Isto é útil se você está usando mais - do que um banco de dados. - - - - - - Conexões JDBC - - - Normalmente, você quer mandar criar a SessionFactory criar um - pool de conexões JDBC para você. Se você seguir essa abordagem, a abertura de uma - Session é tão simples quanto: - - - - - - - Assim que você fizer algo que requer o acesso ao banco de dados, uma - conexão JDBC será obtida do pool. - - - - 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 - org.hibernate.cfg.Environment. Nós iremos descrever agora - o mais importantes configurações de conexão JDBC. - - - - O Hibernate obterá conexões( e pool) usando java.sql.DriverManager - se você determinar as seguintes propriedades: - - - - Propriedades JDBC Hibernate - - - - - - Nome da Propriedade - Propósito - - - - - - hibernate.connection.driver_class - - - Classe driver jdbc - - - - - hibernate.connection.url - - - URL jdbc - - - - - hibernate.connection.username - - - Usuário do banco de dados - - - - - hibernate.connection.password - - - Senha do usuário do banco de dados - - - - - hibernate.connection.pool_size - - - Número máximo de connecxões no pool - - - - -
- - - O algoritmo de pool de conexões do próprio Hibernate entretanto é completamente - rudimentar. A intenção dele e ajudar a iniciar e não para usar em um - sistema de produção ou até para testar desempenho. Você deveria usar - uma ferramente de pool de terceiros para conseguir melhor desempenho e estabilidade. - Apenas especifique a propriedade hibernate.connection.pool_size - 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. - - - - O C3P0 é um pool conexão JDBC de código aberto distribuído junto com - Hibernate no diretório lib. O Hibernate usará o - C3P0ConnectionProvider para o pool de conexão se - você configurar a propriedade hibernate.c3p0.*. Se você - gostar de usar Proxool consulte ao pacote hibernate.properties - e o web site do Hibernate para mais informações. - - - - Aqui é um exemplo de arquivo hibernate.properties para C3P0: - - - - - - Para usar dentro de um servidor de aplicação, você deve configurar - o Hibernate para obter conexões de um application server - Datasource registrado no JNDI. Você necessitará - determinar pelo menos uma das seguintes propriedades: - - - - Propriedades do Datasource do Hibernate - - - - - - Nome da Propriedade - Propósito - - - - - - hibernate.connection.datasource - - - Nome datasource JNDI - - - - - hibernate.jndi.url - - - URL do fornecedor JNDI (opcional) - - - - - hibernate.jndi.class - - - Classe do JNDI InitialContextFactory (opcional) - - - - - hibernate.connection.username - - - Usuário do banco de dados (opcional) - - - - - hibernate.connection.password - - - Senha do usuário do banco de dados (opcional) - - - - -
- - - Eis um exemplo de arquivo hibernate.properties para - um servidor de aplicação fornecedor de datasources JNDI: - - - - - - 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. - - - - Arbitrariamente as propriedades de conexão podem ser acrescentandas ao - "hibernate.connnection" ao nome da propriedade. Por exemplo, - você deve especificar o charSet usando hibernate.connection.charSet.t. - - - - Você pode definir sua própria estratégia de plugin para obter conexões JDBC implementando - a interface org.hibernate.connection.ConnectionProvider. Você pode - escolher uma implementação customizada setando hibernate.connection.provider_class. - - -
- - - Propriedades opcionais de configuração - - - 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. - - - - Aviso: algumas destas propriedades são somente a "nível de sistema". - Propriedades nível de sistema podem ser determinados somente via java -Dproperty=value - ou hibernate.properties. Elas nãopodem ser - configuradas por outras técnicas descritas abaixo. - - - - Hibernate Configuration Properties - - - - - - Nome da Propriedade - Propósito - - - - - - hibernate.dialect - - - O nome da classe de um Dialeto - que permite o Hibernate gerar SQL otimizado para um banco de - dados relacional em particular. - - Ex. - full.classname.of.Dialect - - - - - - hibernate.show_sql - - - Escreve todas as instruções SQL no console. Esta é uma alternativa - a configurar a categoria de log org.hibernate.SQL - para debug. - - Ex. - true | false - - - - - - hibernate.format_sql - - - Imprime o SQL formatado no log e console. - - Ex. - true | false - - - - - - hibernate.default_schema - - - Qualifica no sql gerado, os nome das tabelas sem qualificar - com schena/tablespace dado - - Ex. - SCHEMA_NAME - - - - - - hibernate.default_catalog - - - Qualifica no sql gerado, os nome das tabelas sem qualificar - com catálogo dado - - Ex. - CATALOG_NAME - - - - - - hibernate.session_factory_name - - - O SessionFactory irá automaticamente - se ligar a este nome no JNDI depois de ter sido criado. - - Ex. - jndi/composite/name - - - - - - hibernate.max_fetch_depth - - - Estabelece a "profundidade" máxima para árvore outer join fetch - para associações finais únicas(one-to-one,many-to-one). - Um 0 desativa por default a busca outer join. - - eg. - Valores recomendados entre0 e 3 - - - - - - hibernate.default_batch_fetch_size - - - Determina um tamanho default para busca de associações em lotes do Hibernate - - eg. - Valores recomendados 4, 8, - 16 - - - - - - hibernate.default_entity_mode - - - Determina um modo default para representação de entidades - para todas as sessões abertas desta SessionFactory - - dynamic-map, dom4j, - pojo - - - - - - hibernate.order_updates - - - 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. - - Ex. - true | false - - - - - - hibernate.generate_statistics - - - If enabled, Hibernate will collect statistics useful for - performance tuning. - Se habilitado, o Hibernate coletará estatísticas úties - para performance tuning dos bancos. - - Ex. - true | false - - - - - - hibernate.use_identifer_rollback - - - Se habilitado, propriedades identificadoras geradas - serão zeradas para os valores default quando os - objetos forem apagados. - - Ex. - true | false - - - - - - hibernate.use_sql_comments - - - Se ligado, o Hibernate irá gerar comentários dentro do SQL, - para facilitar o debugging, o valor default é false. - - eg. - true | false - - - - - -
- - - JDBC Hibernate e Propriedades de Conexão - - - - - - Nome da Propriedade - Propósito - - - - - - hibernate.jdbc.fetch_size - - - Um valor maior que zero determina o tamanho do fetch - do JDBC( chamadas Statement.setFetchSize()). - - - - - hibernate.jdbc.batch_size - - - Um valor maior que zero habilita uso de batch updates JDBC2 pelo Hibernate. - - Ex. - valores recomentados entre 5 e 30 - - - - - - hibernate.jdbc.batch_versioned_data - - - Sete esta propriedade como true se seu driver JDBC retorna - o número correto de linhas no executeBatch() ( É usualmente - seguro tornar esta opção ligada). O Hibernate então irá usar betched DML - para automaticamente versionar dados. false por default. - - Ex. - true | false - - - - - - hibernate.jdbc.factory_class - - - Escolher um Batcher customizado. Muitas - aplicações não irão necessitar desta propriedade de configuração - - Ex. - classname.of.BatcherFactory - - - - - - hibernate.jdbc.use_scrollable_resultset - - - 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. - - Ex. - true | false - - - - - - hibernate.jdbc.use_streams_for_binary - - - Use streams para escrever/ler tipos binary - ou serializable para/a o JDBC( propriedade a nível de sistema). - - Ex. - true | false - - - - - - hibernate.jdbc.use_get_generated_keys - - - Possibilita o uso PreparedStatement.getGeneratedKeys() - 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. - - Ex. - true|false - - - - - - hibernate.connection.provider_class - - - O nome da classe de um ConnectionProvider personalizado - o qual proverá conexões JDBC para o Hibernate. - - Ex. - classname.of.ConnectionProvider - - - - - - hibernate.connection.isolation - - - Determina o nível de isolamento de uma transação JDBC. - Verifique java.sql.Connection para valores - siginificativos mas note que a maior parte dos bancos de dados - não suportam todos os níveis de isolamento. - - Ex. - 1, 2, 4, 8 - - - - - - hibernate.connection.autocommit - - - Habilita autocommit para conexões no pool JDBC( não recomendado). - - Ex. - true | false - - - - - - hibernate.connection.release_mode - - - 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 after_statement 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 - after_transaction. auto escolheremos - after_statement para as estratégias de transaçãoes JTA e CMT - e after_transaction para as estratégias de transação JDBC - - Ex. - auto (default) | on_close | - after_transaction | after_statement - - - Note that this setting only affects Sessions returned from - SessionFactory.openSession. For Sessions - obtained through SessionFactory.getCurrentSession, the - CurrentSessionContext implementation configured for use - controls the connection release mode for those Sessions. - See - - - - - - hibernate.connection.<propertyName> - - - Passa a propriedade JDBC propertyName - para DriverManager.getConnection(). - - - - - hibernate.jndi.<propertyName> - - - Passar a propriedade propertyName para - o InitialContextFactory JNDI. - - - - -
- - - Propriedades de Cachê do Hibernate - - - - - - Nome da Propriedade - Propósito - - - - - - hibernate.cache.provider_class - - - O nome da classe de um CacheProvider customizado. - - Ex. - classname.of.CacheProvider - - - - - - hibernate.cache.use_minimal_puts - - - 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. - - Ex. - true|false - - - - - - hibernate.cache.use_query_cache - - - Habilita a cache de consultas, Mesmo assim, consultas individuais ainda tem que ser - habilitadas para o cache. - - Ex. - true|false - - - - - - hibernate.cache.use_second_level_cache - - - May be used to completely disable the second level cache, which is enabled - by default for classes which specify a <cache> - mapping. - Pode ser usada para desabilitar completamente ocache de segundo nível, - o qual está habilitado por default para classes que especificam - um mapeamento <cache>. - - - Ex. - true|false - - - - - - hibernate.cache.query_cache_factory - - - O nome de uma classe que implementa a interface - QueryCache personalizada, por - default, um StandardQueryCache - criado automaticamente. - - Ex. - classname.of.QueryCache - - - - - - hibernate.cache.region_prefix - - - Um prefixo para usar nos nomes da área especial - do cachê de segundo nível. - - Ex. - prefix - - - - - - hibernate.cache.use_structured_entries - - - 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. - - Ex. - true|false - - - - - -
- - - Propriedades de Transação do Hibernate - - - - - - Nome da Propriedade - Propósito - - - - - - hibernate.transaction.factory_class - - - O nome da clase de um a TransactionFactory - para usar com API Transaction - ( por default JDBCTransactionFactory). - - Ex. - classname.of.TransactionFactory - - - - - - jta.UserTransaction - - - Um nome JNDI usado pelo JTATransactionFactory - para obter uma UserTransaction JTA a partir - do servidor de aplicação. - - Ex. - jndi/composite/name - - - - - - hibernate.transaction.manager_lookup_class - - - O nome da classe de um TransactionManagerLookup - – requerido quando caching a nível JVM esta habilitado ou quando - estivermos usando um generator hilo em um ambiente JTA. - - Ex. - classname.of.TransactionManagerLookup - - - - - - hibernate.transaction.flush_before_completion - - - 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 - - - Ex. - true | false - - - - - - hibernate.transaction.auto_close_session - - - 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 - - - Ex. - true | false - - - - - -
- - - Propriedades Variadas - - - - - - Nome da Propriedade - Propósito - - - - - - hibernate.current_session_context_class - - - Forneçe uma estratégia (personalizada) para extensão - da Session "corrente". Veja - para - mais informação sobre estratégias internas. - - Ex. - jta | thread | - managed | custom.Class - - - - - - hibernate.query.factory_class - - - Escolha a implementação de análise HQL. - - eg. - org.hibernate.hql.ast.ASTQueryTranslatorFactory or - org.hibernate.hql.classic.ClassicQueryTranslatorFactory - - - - - - hibernate.query.substitutions - - - Mapeamento a partir de símbolos em consultas HQL para - símbolos SQL( símbolos devem ser funções ou nome literais - , por exemplo). - - eg. - hqlLiteral=SQL_LITERAL, hqlFunction=SQLFUNC - - - - - - hibernate.hbm2ddl.auto - - - Automaticamente valida ou exporta schema DDL para o banco de - dados quando o SessionFactory é criads. - Com create-drop, o schema do banco de dados - será excluido quando a create-drop for - fechada esplicitamente. - - Ex. - validate | update | - create | create-drop - - - - - - hibernate.cglib.use_reflection_optimizer - - - 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. - - Ex. - true | false - - - - - -
- - - Dialetos SQL - - - Você deve sempre determinar a propriedade hibernate.dialect - para a subclasse de org.hibernate.dialect.Dialect 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. - - - - Hibernate SQL Dialects (<literal>hibernate.dialect</literal>) - - - - - - RDBMS - Dialect - - - - - DB2 org.hibernate.dialect.DB2Dialect - - - DB2 AS/400 org.hibernate.dialect.DB2400Dialect - - - DB2 OS390 org.hibernate.dialect.DB2390Dialect - - - PostgreSQL org.hibernate.dialect.PostgreSQLDialect - - - MySQL org.hibernate.dialect.MySQLDialect - - - MySQL with InnoDB org.hibernate.dialect.MySQLInnoDBDialect - - - MySQL with MyISAM org.hibernate.dialect.MySQLMyISAMDialect - - - Oracle (any version) org.hibernate.dialect.OracleDialect - - - Oracle 9i/10g org.hibernate.dialect.Oracle9Dialect - - - Sybase org.hibernate.dialect.SybaseDialect - - - Sybase Anywhere org.hibernate.dialect.SybaseAnywhereDialect - - - Microsoft SQL Server org.hibernate.dialect.SQLServerDialect - - - SAP DB org.hibernate.dialect.SAPDBDialect - - - Informix org.hibernate.dialect.InformixDialect - - - HypersonicSQL org.hibernate.dialect.HSQLDialect - - - Ingres org.hibernate.dialect.IngresDialect - - - Progress org.hibernate.dialect.ProgressDialect - - - Mckoi SQL org.hibernate.dialect.MckoiDialect - - - Interbase org.hibernate.dialect.InterbaseDialect - - - Pointbase org.hibernate.dialect.PointbaseDialect - - - FrontBase org.hibernate.dialect.FrontbaseDialect - - - Firebird org.hibernate.dialect.FirebirdDialect - - - -
- -
- - - Recuperação por união externa (Outer Join Fetching) - - - 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 . - - - - - A recuperação por união externa (Outer Join Fetching) pode ser desabilitado - globalmente setando a propriedade - hibernate.max_fetch_depth para 0. - 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 fetch="join". - - - - Veja para mais informações. - - - - - - Fluxos Binários (Binary Streams) - - - O Oracle limita o tamanho de arrays de byte que pode ser - passado para/de o driver JDBC. Se você desejar usar grandes instâncias de - tipos binary ou serializable, você - deve habilitar hibernate.jdbc.use_streams_for_binary. - Essa é uma configuração que só pode ser feita a nível de sistema. - - - - - - Cachê de segundo nível e query - - - As propriedades prefixadas pelo hibernate.cache - permite você usar um sistema de cachê de segundo nível - em um processo executado em clustercom Hibernate. - Veja para mais detalhes. - - - - - - Substituições na Linguagem de Consulta - - - Você pode definir novos símbolos de consulta Hibernate usando - hibernate.query.substitutions. - Por exemplo: - - - hibernate.query.substitutions true=1, false=0 - - - Faria com que os símbolos true e false - passasem a ser traduzidos para literais inteiro no SQL gerado. - - - hibernate.query.substitutions toLowercase=LOWER - - - permitirá você renomear a função LOWER no SQL. - - - - - - Estatísticas do Hibernate - - - If you enable hibernate.generate_statistics, Hibernate will - expose a number of metrics that are useful when tuning a running system via - SessionFactory.getStatistics(). Hibernate can even be configured - to expose these statistics via JMX. Read the Javadoc of the interfaces in - org.hibernate.stats for more information. - - Se você habilitar hibernate.generate_statistics, o Hibernate - exibirá um número de métricas bastante útil ao ajustar um sistema via - SessionFactory.getStatistics(). O Hibernate pode até ser - configurado para exibir essas estatísticas via JMX. Leia o Javadoc da interface - org.hibernate.stats para mais informações. - - - -
- - - Logging - - - Hibernate registra vários eventos usando Apache commons-logging. - - - - O serviço commons-logging direcionará a saída para o Apache Log4j - ( se você incluir log4j.jarr 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 http://jakarta.apache.org. - Para usar Log4j você necessitará colocar um arquivo - log4j.properties no seu classpath, um exemplo de arquivo - de propriedades é distribuído com o Hibernate no diretório - src/. - - - - - 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: - - - - Categorias de Log do Hibernate - - - - - - Categoria - Função - - - - - org.hibernate.SQL - Registra todas as instruções SQL DML a medida que elas são executadas - - - org.hibernate.type - Registra todos os parâmetros JDBC - - - org.hibernate.tool.hbm2ddl - Registra todas as instruções SQL DDL a medida que elas são executadas - - - org.hibernate.pretty - - 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). - - - - org.hibernate.cache - Registra todas as atividades de cachê de segundo nível - - - org.hibernate.transaction - Registra atividades relacionada a transação - - - org.hibernate.jdbc - Registra todas as requisições de recursos JDBC - - - org.hibernate.hql.ast.AST - - Registra instruções SQL e HQL durante a análise da consultas - - - - org.hibernate.secure - Registra todas as requisições de autorização JAAS - - - org.hibernate - - Registra tudo ( uma parte das informações, mas muito - útil para controle de erros ) - - - - -
- - - Quando desenvolver aplicações com Hibernate, você deve quase sempre trabalhar com - debug debug para a categoria org.hibernate.SQL, - ou, alternativamente, a com a propriedade hibernate.show_sql habilitada. - - - -
- - - Implementado uma <literal>NamingStrategy</literal> - - - A interface org.hibernate.cfg.NamingStrategy permite você - especificar um "padrão de nomeação" para objetos do banco de dados e elementos schema. - - - - 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( TBL_prefixos, por exemplo). A estratégia - default usada pelo Hibernate é completamente mínima. - - - - Você pode especificar uma estratégia diferente ao chamar - Configuration.setNamingStrategy() antes de adicionar - os mapeamentos: - - - - - - org.hibernate.cfg.ImprovedNamingStrategy é uma estratégia - interna que pode ser um ponto de começo útil para algumas aplicações. - - - - - - Arquivo de configuração XML - - - Uma maneira alternativa de configuração é especificar uma configuração completa - em um arquivo chamado hibernate.cfg.xml. Este arquivo pode - ser usado como um substituto para o arquivo hibernate.properties - ou, se ambos estão presentes, sobrescrever propriedades. - - - - The XML configuration file is by default expected to be in the root o - your CLASSPATH. Here is an example: - O arquivo XML de configuração é por default esperado para estar na - raiz do seu CLASSPATH. Veja um exemplo: - - - - - - - - - - - - java:/comp/env/jdbc/MyDB - org.hibernate.dialect.MySQLDialect - false - - org.hibernate.transaction.JTATransactionFactory - - java:comp/UserTransaction - - - - - - - - - - - - -]]> - - - Como você pode ver, a vantagem deste enfoque é a externalização dos nomes dos - arquivos de mapeamento para configuração. O hibernate.cfg.xml - também é mais conveniente caso você tenha que ajustar o cache do Hibernate. - Note que a escolha é sua em usar hibernate.properties ou - hibernate.cfg.xml, ambos são equivalente, à exceção dos benefícios - acima mencionados de usar a sintaxe de XML. - - - - Com a configuração do XML, iniciar o Hibernate é então tão simples como - - - - - - You can pick a different XML configuration file using - - - - - - - - Integração com servidores de aplicação J2EE - - - O Hibernate tem os seguintes pontos da integração para o infraestrutura de J2EE: - - - - - - DataSources gerenciados pelo container: O Hibernate pode - usar conexões JDBC gerenciadas pelo Container e fornecidas pela JNDI. Geralmente, - um TransactionManager compatível com JTA e um - ResourceManager 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 Transaction - para esta manter seu código portável. - - - - - - - - Ligação (binding) automática a JNDI: O Hibernate pode - associar sua SessionFactory a JNDI depois de iniciado. - - - - - - - - Ligação (binding) Session na JTA: - A Session do Hibernate pode automaticamente ser ligada - ao escopo da transações JTA. Simplesmente localizando a SessionFactory - da JNDI e obtendo aSession corrente. Deixe o Hibernate cuidar - da limpeza e encerramento da Session 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). - - - - - - - - JMX deployment: 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 SessionFactory de uma - Configuration. O container iniciará seu - HibernateService, e idealmente também cuidará - das dependências de serviços (DataSources, têm que estar disponíveis - antes do Hibernate iniciar, etc.). - - - - - - Dependendo em seu ambiente, você poderia ter que ajustar a opção de configuração - hibernate.connection.aggressive_release para verdadeiro ( true ), - se seu servidor de aplicações lançar exeções "retenção de conecção". - - - - Configuração de estratégia de transação - - - A API Hibernate Session é 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 UserTransaction quando necessário. - - - - - Para manter seu código portável entre estes dois ( e outros ) ambientes, recomendamos - a API Hibernate Transaction, que envolve e esconde o sistema subjacente. - Você tem que especificar um classe construtora para Transaction instanciar - ajustando a propriedade de configuração do hibernate.transaction.factory_class. - - - - - Existem três escolhas (internas) padrões: - - - - - org.hibernate.transaction.JDBCTransactionFactory - - delegada as transações (JDBC)a bases de dados (Padrão) - - - - - org.hibernate.transaction.JTATransactionFactory - - - 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. - - - - - org.hibernate.transaction.CMTTransactionFactory - - delega para um container gerenciador de transações JTA - - - - - - Você também pode definir suas próprias estratégias de transação ( para um serviço de - transação CORBA por exemplo). - - - - Algumas características no Hibernate (ex., o cache de segundo nível, sessões contextuais - com JTA, etc.) requerem acesso a JTA TransactionManager em um ambiente - controlado. Em um servidor de aplicação você tem que especificar como o Hibernate pode - obter uma referência para a TransactionManager, pois o J2EE não - padronize um mecanismo simples : - - - - Gerenciadores de transações JTA - - - - - - Transaction Factory - Application Server - - - - - org.hibernate.transaction.JBossTransactionManagerLookup - JBoss - - - org.hibernate.transaction.WeblogicTransactionManagerLookup - Weblogic - - - org.hibernate.transaction.WebSphereTransactionManagerLookup - WebSphere - - - org.hibernate.transaction.WebSphereExtendedJTATransactionLookup - WebSphere 6 - - - org.hibernate.transaction.OrionTransactionManagerLookup - Orion - - - org.hibernate.transaction.ResinTransactionManagerLookup - Resin - - - org.hibernate.transaction.JOTMTransactionManagerLookup - JOTM - - - org.hibernate.transaction.JOnASTransactionManagerLookup - JOnAS - - - org.hibernate.transaction.JRun4TransactionManagerLookup - JRun4 - - - org.hibernate.transaction.BESTransactionManagerLookup - Borland ES - - - -
- -
- - - <literal>SessionFactory</literal> ligada a JNDI - - - Uma SessionFactory de Hibernate ligada a JNDI pode simplificar - a localização da fabrica e a criação de novas Sessions. - Observe que isto não relacionado a um Datasource ligado - a JNDI, simplemente ambos usam o mesmo registro! - - - - If you wish to have the SessionFactory bound to a JNDI namespace, specify - a name (eg. java:hibernate/SessionFactory) using the property - hibernate.session_factory_name. If this property is omitted, the - SessionFactory will not be bound to JNDI. (This is especially useful in - environments with a read-only JNDI default implementation, e.g. Tomcat.) - - - - When binding the SessionFactory to JNDI, Hibernate will use the values of - hibernate.jndi.url, hibernate.jndi.class to instantiate - an initial context. If they are not specified, the default InitialContext - will be used. - - - - Hibernate will automatically place the SessionFactory in JNDI after - you call cfg.buildSessionFactory(). 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 HibernateService (discussed later). - - - - If you use a JNDI SessionFactory, an EJB or any other class may - obtain the SessionFactory using a JNDI lookup. - - - - We recommend that you bind the SessionFactory to JNDI in - a managend environment and use a static singleton otherwise. - To shield your application code from these details, we also recommend to hide the - actual lookup code for a SessionFactory in a helper class, - such as HibernateUtil.getSessionFactory(). Note that such a - class is also a convenient way to startup Hibernate—see chapter 1. - - - - - - Current Session context management with JTA - - - The easiest way to handle Sessions and transactions is - Hibernates automatic "current" Session management. - See the discussion of current sessions. - Using the "jta" session context, if there is no Hibernate - Session associated with the current JTA transaction, one will - be started and associated with that JTA transaction the first time you call - sessionFactory.getCurrentSession(). The Sessions - retrieved via getCurrentSession() in "jta" 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 Sessions 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 UserTransaction, or (recommended - for portable code) use the Hibernate Transaction API to set - transaction boundaries. If you run in an EJB container, declarative transaction - demarcation with CMT is preferred. - - - - - - JMX deployment - - - The line cfg.buildSessionFactory() still has to be executed - somewhere to get a SessionFactory into JNDI. You can do this - either in a static initializer block (like the one in - HibernateUtil) or you deploy Hibernate as a managed - service. - - - - Hibernate is distributed with org.hibernate.jmx.HibernateService - 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 - jboss-service.xml for JBoss 4.0.x: - - - - - - - - - jboss.jca:service=RARDeployer - jboss.jca:service=LocalTxCM,name=HsqlDS - - - java:/hibernate/SessionFactory - - - java:HsqlDS - org.hibernate.dialect.HSQLDialect - - - - org.hibernate.transaction.JTATransactionFactory - - org.hibernate.transaction.JBossTransactionManagerLookup - true - true - - - 5 - - - true - org.hibernate.cache.EhCacheProvider - true - - - true - - - auction/Item.hbm.xml,auction/Category.hbm.xml - - - -]]> - - - This file is deployed in a directory called META-INF and packaged - in a JAR file with the extension .sar (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. - - - - -
- -
- + + + Configuração + + + 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 hibernate.properties + de exemplo no etc/ que mostra várias opções. Apenas coloque o arquivo + de exemplo no seu classpath e personalize-o. + + + + 1.11 Configuração programática + + + Uma instância de org.hibernate.cfg.Configuration + representa um conjunto inteiro de mapeamentos de tipos Java da aplicação para + um banco de dados SQL. O Configuration é usado para construir + uma SessionFactory (imutável). Os mapeamentos são compilados + a partir de arquivos de mapeamento XML. + + + + + Você pode obter uma instância Configuration intanciando- + o diretamente e especificando documentos de mapeamento XML. Se o arquivo + de mapeamento estão no classpath, use use addResource(): + + + + + + Uma alternativa (às vezes melhor) é especificar a classe mapeada, + e permitir que o Hibernate encontre o documento de mapeamento para você: + + + + + + Então o Hibernate procurará pelos arquivos de mapeamento chamados + /org/hibernate/auction/Item.hbm.xml e + /org/hibernate/auction/Bid.hbm.xml no classpath. + Esta abordagem elimina qualquer nome de arquivo de difícil compreensão. + + + + Uma Configuration também permite você especificar + propriedades de configuração: + + + + + + Este não é o único caminho para passar as propriedades de configuração + para o Hibernate. As várias opções incluem: + + + + + + Passar uma instância de java.util.Properties + para Configuration.setProperties(). + + + + + Colocar hibernate.properties no diretório + raiz do classpath. + + + + + Determinar as propriedades do System + usando java -Dproperty=value. + + + + + Include <property> elements in + hibernate.cfg.xml (discussed later). + Incluir elementos <property> no + hibernate.cfg.xml (discutido mais tarde). + + + + + + hibernate.properties é o caminho mais facil + se você quer começar mais rápido. + + + + O Configuration é entendido como um objeto startup-time, + é descartado uma vez que a SessionFactory é criada. + + + + + + Obtendo uma SessionFactory + + + Quando todos os mapeamentos têm sido analisados pelo Configuration, + a aplicação deve obter uma factory para as instâncias da Session. + O objetivo desta factory é ser compartilhado por todas as threads da aplicação: + + + + + + Hibernate permite sua aplicação instanciar mais do que uma + SessionFactory. Isto é útil se você está usando mais + do que um banco de dados. + + + + + + Conexões JDBC + + + Normalmente, você quer mandar criar a SessionFactory criar um + pool de conexões JDBC para você. Se você seguir essa abordagem, a abertura de uma + Session é tão simples quanto: + + + + + + + Assim que você fizer algo que requer o acesso ao banco de dados, uma + conexão JDBC será obtida do pool. + + + + 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 + org.hibernate.cfg.Environment. Nós iremos descrever agora + o mais importantes configurações de conexão JDBC. + + + + O Hibernate obterá conexões( e pool) usando java.sql.DriverManager + se você determinar as seguintes propriedades: + + + + Propriedades JDBC Hibernate + + + + + + Nome da Propriedade + Propósito + + + + + + hibernate.connection.driver_class + + + Classe driver jdbc + + + + + hibernate.connection.url + + + URL jdbc + + + + + hibernate.connection.username + + + Usuário do banco de dados + + + + + hibernate.connection.password + + + Senha do usuário do banco de dados + + + + + hibernate.connection.pool_size + + + Número máximo de connecxões no pool + + + + +
+ + + O algoritmo de pool de conexões do próprio Hibernate entretanto é completamente + rudimentar. A intenção dele e ajudar a iniciar e não para usar em um + sistema de produção ou até para testar desempenho. Você deveria usar + uma ferramente de pool de terceiros para conseguir melhor desempenho e estabilidade. + Apenas especifique a propriedade hibernate.connection.pool_size + 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. + + + + O C3P0 é um pool conexão JDBC de código aberto distribuído junto com + Hibernate no diretório lib. O Hibernate usará o + C3P0ConnectionProvider para o pool de conexão se + você configurar a propriedade hibernate.c3p0.*. Se você + gostar de usar Proxool consulte ao pacote hibernate.properties + e o web site do Hibernate para mais informações. + + + + Aqui é um exemplo de arquivo hibernate.properties para C3P0: + + + + + + Para usar dentro de um servidor de aplicação, você deve configurar + o Hibernate para obter conexões de um application server + Datasource registrado no JNDI. Você necessitará + determinar pelo menos uma das seguintes propriedades: + + + + Propriedades do Datasource do Hibernate + + + + + + Nome da Propriedade + Propósito + + + + + + hibernate.connection.datasource + + + Nome datasource JNDI + + + + + hibernate.jndi.url + + + URL do fornecedor JNDI (opcional) + + + + + hibernate.jndi.class + + + Classe do JNDI InitialContextFactory (opcional) + + + + + hibernate.connection.username + + + Usuário do banco de dados (opcional) + + + + + hibernate.connection.password + + + Senha do usuário do banco de dados (opcional) + + + + +
+ + + Eis um exemplo de arquivo hibernate.properties para + um servidor de aplicação fornecedor de datasources JNDI: + + + + + + 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. + + + + Arbitrariamente as propriedades de conexão podem ser acrescentandas ao + "hibernate.connnection" ao nome da propriedade. Por exemplo, + você deve especificar o charSet usando hibernate.connection.charSet.t. + + + + Você pode definir sua própria estratégia de plugin para obter conexões JDBC implementando + a interface org.hibernate.connection.ConnectionProvider. Você pode + escolher uma implementação customizada setando hibernate.connection.provider_class. + + +
+ + + Propriedades opcionais de configuração + + + 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. + + + + Aviso: algumas destas propriedades são somente a "nível de sistema". + Propriedades nível de sistema podem ser determinados somente via java -Dproperty=value + ou hibernate.properties. Elas nãopodem ser + configuradas por outras técnicas descritas abaixo. + + + + Hibernate Configuration Properties + + + + + + Nome da Propriedade + Propósito + + + + + + hibernate.dialect + + + O nome da classe de um Dialeto + que permite o Hibernate gerar SQL otimizado para um banco de + dados relacional em particular. + + Ex. + full.classname.of.Dialect + + + + + + hibernate.show_sql + + + Escreve todas as instruções SQL no console. Esta é uma alternativa + a configurar a categoria de log org.hibernate.SQL + para debug. + + Ex. + true | false + + + + + + hibernate.format_sql + + + Imprime o SQL formatado no log e console. + + Ex. + true | false + + + + + + hibernate.default_schema + + + Qualifica no sql gerado, os nome das tabelas sem qualificar + com schena/tablespace dado + + Ex. + SCHEMA_NAME + + + + + + hibernate.default_catalog + + + Qualifica no sql gerado, os nome das tabelas sem qualificar + com catálogo dado + + Ex. + CATALOG_NAME + + + + + + hibernate.session_factory_name + + + O SessionFactory irá automaticamente + se ligar a este nome no JNDI depois de ter sido criado. + + Ex. + jndi/composite/name + + + + + + hibernate.max_fetch_depth + + + Estabelece a "profundidade" máxima para árvore outer join fetch + para associações finais únicas(one-to-one,many-to-one). + Um 0 desativa por default a busca outer join. + + eg. + Valores recomendados entre0 e 3 + + + + + + hibernate.default_batch_fetch_size + + + Determina um tamanho default para busca de associações em lotes do Hibernate + + eg. + Valores recomendados 4, 8, + 16 + + + + + + hibernate.default_entity_mode + + + Determina um modo default para representação de entidades + para todas as sessões abertas desta SessionFactory + + dynamic-map, dom4j, + pojo + + + + + + hibernate.order_updates + + + 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. + + Ex. + true | false + + + + + + hibernate.generate_statistics + + + If enabled, Hibernate will collect statistics useful for + performance tuning. + Se habilitado, o Hibernate coletará estatísticas úties + para performance tuning dos bancos. + + Ex. + true | false + + + + + + hibernate.use_identifer_rollback + + + Se habilitado, propriedades identificadoras geradas + serão zeradas para os valores default quando os + objetos forem apagados. + + Ex. + true | false + + + + + + hibernate.use_sql_comments + + + Se ligado, o Hibernate irá gerar comentários dentro do SQL, + para facilitar o debugging, o valor default é false. + + eg. + true | false + + + + + +
+ + + JDBC Hibernate e Propriedades de Conexão + + + + + + Nome da Propriedade + Propósito + + + + + + hibernate.jdbc.fetch_size + + + Um valor maior que zero determina o tamanho do fetch + do JDBC( chamadas Statement.setFetchSize()). + + + + + hibernate.jdbc.batch_size + + + Um valor maior que zero habilita uso de batch updates JDBC2 pelo Hibernate. + + Ex. + valores recomentados entre 5 e 30 + + + + + + hibernate.jdbc.batch_versioned_data + + + Sete esta propriedade como true se seu driver JDBC retorna + o número correto de linhas no executeBatch() ( É usualmente + seguro tornar esta opção ligada). O Hibernate então irá usar betched DML + para automaticamente versionar dados. false por default. + + Ex. + true | false + + + + + + hibernate.jdbc.factory_class + + + Escolher um Batcher customizado. Muitas + aplicações não irão necessitar desta propriedade de configuração + + Ex. + classname.of.BatcherFactory + + + + + + hibernate.jdbc.use_scrollable_resultset + + + 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. + + Ex. + true | false + + + + + + hibernate.jdbc.use_streams_for_binary + + + Use streams para escrever/ler tipos binary + ou serializable para/a o JDBC( propriedade a nível de sistema). + + Ex. + true | false + + + + + + hibernate.jdbc.use_get_generated_keys + + + Possibilita o uso PreparedStatement.getGeneratedKeys() + 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. + + Ex. + true|false + + + + + + hibernate.connection.provider_class + + + O nome da classe de um ConnectionProvider personalizado + o qual proverá conexões JDBC para o Hibernate. + + Ex. + classname.of.ConnectionProvider + + + + + + hibernate.connection.isolation + + + Determina o nível de isolamento de uma transação JDBC. + Verifique java.sql.Connection para valores + siginificativos mas note que a maior parte dos bancos de dados + não suportam todos os níveis de isolamento. + + Ex. + 1, 2, 4, 8 + + + + + + hibernate.connection.autocommit + + + Habilita autocommit para conexões no pool JDBC( não recomendado). + + Ex. + true | false + + + + + + hibernate.connection.release_mode + + + 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 after_statement 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 + after_transaction. auto escolheremos + after_statement para as estratégias de transaçãoes JTA e CMT + e after_transaction para as estratégias de transação JDBC + + Ex. + auto (default) | on_close | + after_transaction | after_statement + + + Note that this setting only affects Sessions returned from + SessionFactory.openSession. For Sessions + obtained through SessionFactory.getCurrentSession, the + CurrentSessionContext implementation configured for use + controls the connection release mode for those Sessions. + See + + + + + + hibernate.connection.<propertyName> + + + Passa a propriedade JDBC propertyName + para DriverManager.getConnection(). + + + + + hibernate.jndi.<propertyName> + + + Passar a propriedade propertyName para + o InitialContextFactory JNDI. + + + + +
+ + + Propriedades de Cachê do Hibernate + + + + + + Nome da Propriedade + Propósito + + + + + + hibernate.cache.provider_class + + + O nome da classe de um CacheProvider customizado. + + Ex. + classname.of.CacheProvider + + + + + + hibernate.cache.use_minimal_puts + + + 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. + + Ex. + true|false + + + + + + hibernate.cache.use_query_cache + + + Habilita a cache de consultas, Mesmo assim, consultas individuais ainda tem que ser + habilitadas para o cache. + + Ex. + true|false + + + + + + hibernate.cache.use_second_level_cache + + + Pode ser usada para desabilitar completamente ocache de segundo nível, + o qual está habilitado por default para classes que especificam + um mapeamento <cache>. + + + Ex. + true|false + + + + + + hibernate.cache.query_cache_factory + + + O nome de uma classe que implementa a interface + QueryCache personalizada, por + default, um StandardQueryCache + criado automaticamente. + + Ex. + classname.of.QueryCache + + + + + + hibernate.cache.region_prefix + + + Um prefixo para usar nos nomes da área especial + do cachê de segundo nível. + + Ex. + prefix + + + + + + hibernate.cache.use_structured_entries + + + 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. + + Ex. + true|false + + + + + +
+ + + Propriedades de Transação do Hibernate + + + + + + Nome da Propriedade + Propósito + + + + + + hibernate.transaction.factory_class + + + O nome da clase de um a TransactionFactory + para usar com API Transaction + ( por default JDBCTransactionFactory). + + Ex. + classname.of.TransactionFactory + + + + + + jta.UserTransaction + + + Um nome JNDI usado pelo JTATransactionFactory + para obter uma UserTransaction JTA a partir + do servidor de aplicação. + + Ex. + jndi/composite/name + + + + + + hibernate.transaction.manager_lookup_class + + + O nome da classe de um TransactionManagerLookup + – requerido quando caching a nível JVM esta habilitado ou quando + estivermos usando um generator hilo em um ambiente JTA. + + Ex. + classname.of.TransactionManagerLookup + + + + + + hibernate.transaction.flush_before_completion + + + 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 + + + Ex. + true | false + + + + + + hibernate.transaction.auto_close_session + + + 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 + + + Ex. + true | false + + + + + +
+ + + Propriedades Variadas + + + + + + Nome da Propriedade + Propósito + + + + + + hibernate.current_session_context_class + + + Forneçe uma estratégia (personalizada) para extensão + da Session "corrente". Veja + para + mais informação sobre estratégias internas. + + Ex. + jta | thread | + managed | custom.Class + + + + + + hibernate.query.factory_class + + + Escolha a implementação de análise HQL. + + eg. + org.hibernate.hql.ast.ASTQueryTranslatorFactory or + org.hibernate.hql.classic.ClassicQueryTranslatorFactory + + + + + + hibernate.query.substitutions + + + Mapeamento a partir de símbolos em consultas HQL para + símbolos SQL( símbolos devem ser funções ou nome literais + , por exemplo). + + eg. + hqlLiteral=SQL_LITERAL, hqlFunction=SQLFUNC + + + + + + hibernate.hbm2ddl.auto + + + Automaticamente valida ou exporta schema DDL para o banco de + dados quando o SessionFactory é criads. + Com create-drop, o schema do banco de dados + será excluido quando a create-drop for + fechada esplicitamente. + + Ex. + validate | update | + create | create-drop + + + + + + hibernate.cglib.use_reflection_optimizer + + + 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. + + Ex. + true | false + + + + + +
+ + + Dialetos SQL + + + Você deve sempre determinar a propriedade hibernate.dialect + para a subclasse de org.hibernate.dialect.Dialect 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. + + + + Hibernate SQL Dialects (<literal>hibernate.dialect</literal>) + + + + + + RDBMS + Dialect + + + + + DB2 org.hibernate.dialect.DB2Dialect + + + DB2 AS/400 org.hibernate.dialect.DB2400Dialect + + + DB2 OS390 org.hibernate.dialect.DB2390Dialect + + + PostgreSQL org.hibernate.dialect.PostgreSQLDialect + + + MySQL org.hibernate.dialect.MySQLDialect + + + MySQL with InnoDB org.hibernate.dialect.MySQLInnoDBDialect + + + MySQL with MyISAM org.hibernate.dialect.MySQLMyISAMDialect + + + Oracle (any version) org.hibernate.dialect.OracleDialect + + + Oracle 9i/10g org.hibernate.dialect.Oracle9Dialect + + + Sybase org.hibernate.dialect.SybaseDialect + + + Sybase Anywhere org.hibernate.dialect.SybaseAnywhereDialect + + + Microsoft SQL Server org.hibernate.dialect.SQLServerDialect + + + SAP DB org.hibernate.dialect.SAPDBDialect + + + Informix org.hibernate.dialect.InformixDialect + + + HypersonicSQL org.hibernate.dialect.HSQLDialect + + + Ingres org.hibernate.dialect.IngresDialect + + + Progress org.hibernate.dialect.ProgressDialect + + + Mckoi SQL org.hibernate.dialect.MckoiDialect + + + Interbase org.hibernate.dialect.InterbaseDialect + + + Pointbase org.hibernate.dialect.PointbaseDialect + + + FrontBase org.hibernate.dialect.FrontbaseDialect + + + Firebird org.hibernate.dialect.FirebirdDialect + + + +
+ +
+ + + Recuperação por união externa (Outer Join Fetching) + + + 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 . + + + + + A recuperação por união externa (Outer Join Fetching) pode ser desabilitado + globalmente setando a propriedade + hibernate.max_fetch_depth para 0. + 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 fetch="join". + + + + Veja para mais informações. + + + + + + Fluxos Binários (Binary Streams) + + + O Oracle limita o tamanho de arrays de byte que pode ser + passado para/de o driver JDBC. Se você desejar usar grandes instâncias de + tipos binary ou serializable, você + deve habilitar hibernate.jdbc.use_streams_for_binary. + Essa é uma configuração que só pode ser feita a nível de sistema. + + + + + + Cachê de segundo nível e query + + + As propriedades prefixadas pelo hibernate.cache + permite você usar um sistema de cachê de segundo nível + em um processo executado em clustercom Hibernate. + Veja para mais detalhes. + + + + + + Substituições na Linguagem de Consulta + + + Você pode definir novos símbolos de consulta Hibernate usando + hibernate.query.substitutions. + Por exemplo: + + + hibernate.query.substitutions true=1, false=0 + + + Faria com que os símbolos true e false + passasem a ser traduzidos para literais inteiro no SQL gerado. + + + hibernate.query.substitutions toLowercase=LOWER + + + permitirá você renomear a função LOWER no SQL. + + + + + + Estatísticas do Hibernate + + + If you enable hibernate.generate_statistics, Hibernate will + expose a number of metrics that are useful when tuning a running system via + SessionFactory.getStatistics(). Hibernate can even be configured + to expose these statistics via JMX. Read the Javadoc of the interfaces in + org.hibernate.stats for more information. + + Se você habilitar hibernate.generate_statistics, o Hibernate + exibirá um número de métricas bastante útil ao ajustar um sistema via + SessionFactory.getStatistics(). O Hibernate pode até ser + configurado para exibir essas estatísticas via JMX. Leia o Javadoc da interface + org.hibernate.stats para mais informações. + + + +
+ + + Logging + + + Hibernate registra vários eventos usando Apache commons-logging. + + + + O serviço commons-logging direcionará a saída para o Apache Log4j + ( se você incluir log4j.jarr 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 http://jakarta.apache.org. + Para usar Log4j você necessitará colocar um arquivo + log4j.properties no seu classpath, um exemplo de arquivo + de propriedades é distribuído com o Hibernate no diretório + src/. + + + + + 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: + + + + Categorias de Log do Hibernate + + + + + + Categoria + Função + + + + + org.hibernate.SQL + Registra todas as instruções SQL DML a medida que elas são executadas + + + org.hibernate.type + Registra todos os parâmetros JDBC + + + org.hibernate.tool.hbm2ddl + Registra todas as instruções SQL DDL a medida que elas são executadas + + + org.hibernate.pretty + + 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). + + + + org.hibernate.cache + Registra todas as atividades de cachê de segundo nível + + + org.hibernate.transaction + Registra atividades relacionada a transação + + + org.hibernate.jdbc + Registra todas as requisições de recursos JDBC + + + org.hibernate.hql.ast.AST + + Registra instruções SQL e HQL durante a análise da consultas + + + + org.hibernate.secure + Registra todas as requisições de autorização JAAS + + + org.hibernate + + Registra tudo ( uma parte das informações, mas muito + útil para controle de erros ) + + + + +
+ + + Quando desenvolver aplicações com Hibernate, você deve quase sempre trabalhar com + debug debug para a categoria org.hibernate.SQL, + ou, alternativamente, a com a propriedade hibernate.show_sql habilitada. + + + +
+ + + Implementado uma <literal>NamingStrategy</literal> + + + A interface org.hibernate.cfg.NamingStrategy permite você + especificar um "padrão de nomeação" para objetos do banco de dados e elementos schema. + + + + 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( TBL_prefixos, por exemplo). A estratégia + default usada pelo Hibernate é completamente mínima. + + + + Você pode especificar uma estratégia diferente ao chamar + Configuration.setNamingStrategy() antes de adicionar + os mapeamentos: + + + + + + org.hibernate.cfg.ImprovedNamingStrategy é uma estratégia + interna que pode ser um ponto de começo útil para algumas aplicações. + + + + + + Arquivo de configuração XML + + + Uma maneira alternativa de configuração é especificar uma configuração completa + em um arquivo chamado hibernate.cfg.xml. Este arquivo pode + ser usado como um substituto para o arquivo hibernate.properties + ou, se ambos estão presentes, sobrescrever propriedades. + + + + The XML configuration file is by default expected to be in the root o + your CLASSPATH. Here is an example: + O arquivo XML de configuração é por default esperado para estar na + raiz do seu CLASSPATH. Veja um exemplo: + + + + + + + + + + + + java:/comp/env/jdbc/MyDB + org.hibernate.dialect.MySQLDialect + false + + org.hibernate.transaction.JTATransactionFactory + + java:comp/UserTransaction + + + + + + + + + + + + +]]> + + + Como você pode ver, a vantagem deste enfoque é a externalização dos nomes dos + arquivos de mapeamento para configuração. O hibernate.cfg.xml + também é mais conveniente caso você tenha que ajustar o cache do Hibernate. + Note que a escolha é sua em usar hibernate.properties ou + hibernate.cfg.xml, ambos são equivalente, à exceção dos benefícios + acima mencionados de usar a sintaxe de XML. + + + + Com a configuração do XML, iniciar o Hibernate é então tão simples como + + + + + + You can pick a different XML configuration file using + + + + + + + + Integração com servidores de aplicação J2EE + + + O Hibernate tem os seguintes pontos da integração para o infraestrutura de J2EE: + + + + + + DataSources gerenciados pelo container: O Hibernate pode + usar conexões JDBC gerenciadas pelo Container e fornecidas pela JNDI. Geralmente, + um TransactionManager compatível com JTA e um + ResourceManager 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 Transaction + para esta manter seu código portável. + + + + + + + + Ligação (binding) automática a JNDI: O Hibernate pode + associar sua SessionFactory a JNDI depois de iniciado. + + + + + + + + Ligação (binding) Session na JTA: + A Session do Hibernate pode automaticamente ser ligada + ao escopo da transações JTA. Simplesmente localizando a SessionFactory + da JNDI e obtendo aSession corrente. Deixe o Hibernate cuidar + da limpeza e encerramento da Session 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). + + + + + + + + JMX deployment: 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 SessionFactory de uma + Configuration. O container iniciará seu + HibernateService, e idealmente também cuidará + das dependências de serviços (DataSources, têm que estar disponíveis + antes do Hibernate iniciar, etc.). + + + + + + Dependendo em seu ambiente, você poderia ter que ajustar a opção de configuração + hibernate.connection.aggressive_release para verdadeiro ( true ), + se seu servidor de aplicações lançar exeções "retenção de conecção". + + + + Configuração de estratégia de transação + + + A API Hibernate Session é 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 UserTransaction quando necessário. + + + + + Para manter seu código portável entre estes dois ( e outros ) ambientes, recomendamos + a API Hibernate Transaction, que envolve e esconde o sistema subjacente. + Você tem que especificar um classe construtora para Transaction instanciar + ajustando a propriedade de configuração do hibernate.transaction.factory_class. + + + + + Existem três escolhas (internas) padrões: + + + + + org.hibernate.transaction.JDBCTransactionFactory + + delegada as transações (JDBC)a bases de dados (Padrão) + + + + + org.hibernate.transaction.JTATransactionFactory + + + 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. + + + + + org.hibernate.transaction.CMTTransactionFactory + + delega para um container gerenciador de transações JTA + + + + + + Você também pode definir suas próprias estratégias de transação ( para um serviço de + transação CORBA por exemplo). + + + + Algumas características no Hibernate (ex., o cache de segundo nível, sessões contextuais + com JTA, etc.) requerem acesso a JTA TransactionManager em um ambiente + controlado. Em um servidor de aplicação você tem que especificar como o Hibernate pode + obter uma referência para a TransactionManager, pois o J2EE não + padronize um mecanismo simples : + + + + Gerenciadores de transações JTA + + + + + + Transaction Factory + Application Server + + + + + org.hibernate.transaction.JBossTransactionManagerLookup + JBoss + + + org.hibernate.transaction.WeblogicTransactionManagerLookup + Weblogic + + + org.hibernate.transaction.WebSphereTransactionManagerLookup + WebSphere + + + org.hibernate.transaction.WebSphereExtendedJTATransactionLookup + WebSphere 6 + + + org.hibernate.transaction.OrionTransactionManagerLookup + Orion + + + org.hibernate.transaction.ResinTransactionManagerLookup + Resin + + + org.hibernate.transaction.JOTMTransactionManagerLookup + JOTM + + + org.hibernate.transaction.JOnASTransactionManagerLookup + JOnAS + + + org.hibernate.transaction.JRun4TransactionManagerLookup + JRun4 + + + org.hibernate.transaction.BESTransactionManagerLookup + Borland ES + + + +
+ +
+ + + <literal>SessionFactory</literal> ligada a JNDI + + + Uma SessionFactory de Hibernate ligada a JNDI pode simplificar + a localização da fabrica e a criação de novas Sessions. + Observe que isto não relacionado a um Datasource ligado + a JNDI, simplemente ambos usam o mesmo registro! + + + + If you wish to have the SessionFactory bound to a JNDI namespace, specify + a name (eg. java:hibernate/SessionFactory) using the property + hibernate.session_factory_name. If this property is omitted, the + SessionFactory will not be bound to JNDI. (This is especially useful in + environments with a read-only JNDI default implementation, e.g. Tomcat.) + + + + When binding the SessionFactory to JNDI, Hibernate will use the values of + hibernate.jndi.url, hibernate.jndi.class to instantiate + an initial context. If they are not specified, the default InitialContext + will be used. + + + + Hibernate will automatically place the SessionFactory in JNDI after + you call cfg.buildSessionFactory(). 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 HibernateService (discussed later). + + + + If you use a JNDI SessionFactory, an EJB or any other class may + obtain the SessionFactory using a JNDI lookup. + + + + We recommend that you bind the SessionFactory to JNDI in + a managend environment and use a static singleton otherwise. + To shield your application code from these details, we also recommend to hide the + actual lookup code for a SessionFactory in a helper class, + such as HibernateUtil.getSessionFactory(). Note that such a + class is also a convenient way to startup Hibernate—see chapter 1. + + + + + + Current Session context management with JTA + + + The easiest way to handle Sessions and transactions is + Hibernates automatic "current" Session management. + See the discussion of current sessions. + Using the "jta" session context, if there is no Hibernate + Session associated with the current JTA transaction, one will + be started and associated with that JTA transaction the first time you call + sessionFactory.getCurrentSession(). The Sessions + retrieved via getCurrentSession() in "jta" 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 Sessions 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 UserTransaction, or (recommended + for portable code) use the Hibernate Transaction API to set + transaction boundaries. If you run in an EJB container, declarative transaction + demarcation with CMT is preferred. + + + + + + JMX deployment + + + The line cfg.buildSessionFactory() still has to be executed + somewhere to get a SessionFactory into JNDI. You can do this + either in a static initializer block (like the one in + HibernateUtil) or you deploy Hibernate as a managed + service. + + + + Hibernate is distributed with org.hibernate.jmx.HibernateService + 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 + jboss-service.xml for JBoss 4.0.x: + + + + + + + + + jboss.jca:service=RARDeployer + jboss.jca:service=LocalTxCM,name=HsqlDS + + + java:/hibernate/SessionFactory + + + java:HsqlDS + org.hibernate.dialect.HSQLDialect + + + + org.hibernate.transaction.JTATransactionFactory + + org.hibernate.transaction.JBossTransactionManagerLookup + true + true + + + 5 + + + true + org.hibernate.cache.EhCacheProvider + true + + + true + + + auction/Item.hbm.xml,auction/Category.hbm.xml + + + +]]> + + + This file is deployed in a directory called META-INF and packaged + in a JAR file with the extension .sar (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. + + + + +
+ +
+ diff --git a/documentation/manual/pt-BR/src/main/docbook/content/events.xml b/documentation/manual/pt-BR/src/main/docbook/content/events.xml index 361db3cb6f..5ca4e22e9a 100755 --- a/documentation/manual/pt-BR/src/main/docbook/content/events.xml +++ b/documentation/manual/pt-BR/src/main/docbook/content/events.xml @@ -1,7 +1,7 @@ - + Interceptadores e Eventos diff --git a/documentation/manual/pt-BR/src/main/docbook/content/example_mappings.xml b/documentation/manual/pt-BR/src/main/docbook/content/example_mappings.xml index 4870703ef6..6cf7fbccd1 100755 --- a/documentation/manual/pt-BR/src/main/docbook/content/example_mappings.xml +++ b/documentation/manual/pt-BR/src/main/docbook/content/example_mappings.xml @@ -1,7 +1,7 @@ - + Exemplo: Vários Mapeamentos diff --git a/documentation/manual/pt-BR/src/main/docbook/content/example_parentchild.xml b/documentation/manual/pt-BR/src/main/docbook/content/example_parentchild.xml index 5196ef2ee3..1e7dd7a18d 100755 --- a/documentation/manual/pt-BR/src/main/docbook/content/example_parentchild.xml +++ b/documentation/manual/pt-BR/src/main/docbook/content/example_parentchild.xml @@ -1,7 +1,7 @@ - + Example: Parent/Child diff --git a/documentation/manual/pt-BR/src/main/docbook/content/example_weblog.xml b/documentation/manual/pt-BR/src/main/docbook/content/example_weblog.xml index ec7e14b98c..da4c4cbe75 100755 --- a/documentation/manual/pt-BR/src/main/docbook/content/example_weblog.xml +++ b/documentation/manual/pt-BR/src/main/docbook/content/example_weblog.xml @@ -1,7 +1,7 @@ - + Example: Weblog Application diff --git a/documentation/manual/pt-BR/src/main/docbook/content/filters.xml b/documentation/manual/pt-BR/src/main/docbook/content/filters.xml index b666744189..044ec7a877 100755 --- a/documentation/manual/pt-BR/src/main/docbook/content/filters.xml +++ b/documentation/manual/pt-BR/src/main/docbook/content/filters.xml @@ -1,7 +1,7 @@ - + Filtrando dados diff --git a/documentation/manual/pt-BR/src/main/docbook/content/inheritance_mapping.xml b/documentation/manual/pt-BR/src/main/docbook/content/inheritance_mapping.xml index 94c5bf622c..0ad76faa69 100755 --- a/documentation/manual/pt-BR/src/main/docbook/content/inheritance_mapping.xml +++ b/documentation/manual/pt-BR/src/main/docbook/content/inheritance_mapping.xml @@ -1,7 +1,7 @@ - + Mapeamento de Herança diff --git a/documentation/manual/pt-BR/src/main/docbook/content/performance.xml b/documentation/manual/pt-BR/src/main/docbook/content/performance.xml index ab9a7b7974..a2d6347f56 100755 --- a/documentation/manual/pt-BR/src/main/docbook/content/performance.xml +++ b/documentation/manual/pt-BR/src/main/docbook/content/performance.xml @@ -1,7 +1,7 @@ - + Aumentando a performance diff --git a/documentation/manual/pt-BR/src/main/docbook/content/persistent_classes.xml b/documentation/manual/pt-BR/src/main/docbook/content/persistent_classes.xml index d4ff8ac25e..d8da59276c 100755 --- a/documentation/manual/pt-BR/src/main/docbook/content/persistent_classes.xml +++ b/documentation/manual/pt-BR/src/main/docbook/content/persistent_classes.xml @@ -1,7 +1,7 @@ - + Persistent Classes diff --git a/documentation/manual/pt-BR/src/main/docbook/content/preface.xml b/documentation/manual/pt-BR/src/main/docbook/content/preface.xml index 8d859ba4e2..08846c81a6 100644 --- a/documentation/manual/pt-BR/src/main/docbook/content/preface.xml +++ b/documentation/manual/pt-BR/src/main/docbook/content/preface.xml @@ -1,7 +1,7 @@ - + Prefácio diff --git a/documentation/manual/pt-BR/src/main/docbook/content/query_criteria.xml b/documentation/manual/pt-BR/src/main/docbook/content/query_criteria.xml index 7fcec6cb56..d3e16effb2 100755 --- a/documentation/manual/pt-BR/src/main/docbook/content/query_criteria.xml +++ b/documentation/manual/pt-BR/src/main/docbook/content/query_criteria.xml @@ -1,7 +1,7 @@ - + Consultas por critérios diff --git a/documentation/manual/pt-BR/src/main/docbook/content/query_hql.xml b/documentation/manual/pt-BR/src/main/docbook/content/query_hql.xml index 0860d84ec6..6886b1017a 100755 --- a/documentation/manual/pt-BR/src/main/docbook/content/query_hql.xml +++ b/documentation/manual/pt-BR/src/main/docbook/content/query_hql.xml @@ -1,1163 +1,1174 @@ - - HQL: A linguagem de Queries do Hibernate - - - 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. - - - - Case Sensitíve - - - As Queries não são case-sensitive, exceto pelo nomes das classes e propriedades Java. - sELEct e o mesmo que - SELECT mas - org.hibernate.eg.FOO não é - org.hibernate.eg.Foo e - foo.barSet não é - foo.BARSET. - - - - - 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. - - - - - - A clausula from - - - A mais simples query possível do Hibernate é a assim: - - - - - - Ela irá retornar todas as instancias da classe eg.Cat. - Necessariamente não precisamos qualificar o nome da classe, pois é realizado - auto-import por padrão. Por isso na maior parte do tempos - nós simplesmente escrevemos: - - - - - - Na maior parte do tempo, você precisará atribuir um alias, - desde que você queira se referia ao Cat em outras partes da - query. - - - - - - Essa query atribui um alias a cat para as instancias de - Cat, então nós podemos usar esse alias depois na query. - A palavra chave as é opcional; poderíamos escrever assim: - - - - - - Múltiplas classes pode ser envolvidas, resultando em um produto cartesiano ou "cross" join. - - - - - - - É 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: domesticCat). - - - - - - Associações e joins - - - Nós também podemos querer atribuir aliases em uma entidade associada, ou mesmo - em elementos de uma coleção de valores, usando um join. - - - - - - - - - - Os tipos de joins suportados foram inspirados no SQL ANSI: - - - - - - inner join - - - - - left outer join - - - - - right outer join - - - - - full join (geralmente não é útil) - - - - - - The inner join, left outer join and - right outer join constructs may be abbreviated. - As construções inner join, left outer join e - right outer join podem ser abreviadas. - - - - - - Você pode fornecer condições extras de join usando a palavra - chave do HQL with. - - - with kitten.bodyWeight > 10.0]]> - - - 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 para mais informações. - - - fetchcat.mate - left join fetchcat.kittens]]> - - - Usualmente, um fetchjoin não precisa atribuir um alias, pois o objeto associado não - deve ser usado na clausula where (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: - - - fetchcat.mate - left join fetchcat.kittens child - left join fetchchild.kittens]]> - - - Observe que a construção fetch não deve ser usada em queries invocadas usando - iterate() (embora possa ser usado com scroll()). O - fetch também não deve ser usado junto com o setMaxResults() ou - setFirstResult() 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 fetch não deve ser usado junto com uma condição with em - uma condição with 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 - full join fetch e right join fetch não são significativos. - - - - - Se está usando o nível de propriedade lazy (com instrumentação de bytecode), é possível - forçar o Hibernate a buscar as propriedades lazy imediatamente (na primeira query), - usando fetch all properties . - - - fetchall properties order by name]]> - fetchall properties where lower(doc.name) like '%cats%']]> - - - - - Formas e sintaxe de joins - - - O HQL suporta duas formas de associação para união: implícita e explicita. - - - - As queries apresentadas na seção anterior usam a forma explicita, onde a - palavra chave "join" é explicitamente usada na clausula "from". Essa é a forma recomendada. - - - - A forma implícita 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 implícita resulta em declarações - SQL que contem inner joins. - - - - - - - Clausula select - - - A clausula select seleciona quais obetos e propriedades retornam - no resultado da query. Considere: - - - - - - A query selecionará mates (companheiros), de outros Cats. - Atualmente, podemos expressar a query de forma mais compacta como: - - - - - - Queries podem retornar propriedades de qualquer tipo de valor, incluindo propriedades de tipo de componente: - - - - - - - - - Queries podem retornar múltiplos objetos e/ou propriedades como um array do - tipo Object[], - - - - - - ou como um List, - - - - - - ou como um objeto Java typesafe, - - - - - - assumindo que a classe Family tenha um construtor apropriado. - - - - Pode-se designar referencias a expressões selecionadas, as: - - - - - - Isto é bem mais útil quando usado junto com select new map: - - - - - - Esta query retorna um Map de referencias para valores selecionados. - - - - - - Funções de agregação - - - As queries HQL podem retornar o resultado de funções agregadas nas propriedades. - - - - - - - - As funções agregadas suportadas são: - - - - - - avg(...), sum(...), min(...), max(...) - - - - - count(*) - - - - - count(...), count(distinct ...), count(all...) - - - - - - Pode-se usar operadores aritiméticos, concatenação e funções SQL - reconhecidas na clausula select: - - - - - - - - As palavras distinct e all podem ser usadas e têm - a mesma semântica como no SQL. - - - - - - - - Queries polimórficas - - - A query: - - - - - - retorna instancias não só de Cat, mas também de subclasses como - DomesticCat. As queries do Hibernate podem nomear qualquer classe Java - ou interface na clausula from. 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: - - - - - - A interface Named pode ser implementada por várias classes persistentes: - - - - - - Note que as duas últimas queries requerem mais de um SQL SELECT . Isto significa que a clausula - order by não ordena corretamente todo o resultado. (Isso também significa que - você não pode chamar essas queries usando Query.scroll().) - - - - - - A clausula where - - - A clausula where permite estreitar a lista de instancias retornada. - Se não houver referencia alguma, pode-se referir a propriedades pelo nome: - - - - - - Se houver uma referência, use o nome da propriedade qualificada: - - - - - - retorna instancias de Cat com nome ‘Fritz’. - - - - - - retornará todas as instancias de Foo, para cada - um que tiver uma instancia de bar com a propriedade - date igual a propriedade - startDate de - Foo. Expressões de filtro compostas fazem da - clausula where, extremamente poderosa. Consideremos: - - - - - - Esta query traduzida para uma query SQL com uma tabela (inner) join. Se fosse - escrever algo como: - - - - - - Poderia-se terminar com uma query que necessitasse de join de quatro tabelas, - no SQL. - - - - O operador = pode ser uasdo para comparar não apenas propriedades, - mas também instancias: - - - - - - - - A propriedade especial (lowercase) id pode ser usada para referenciar - o identificador único de um objeto. (Pode-se usar também o nome de sua propriedade) - - - - - - A Segunda query é eficiente. Nenhuma união de tabelas é necessária! - - - - As propriedades de identificadores compostas também podem ser usadas. Suponha que - Person tenha um identificador composto que consiste de - country e medicareNumber. - - - - - - - - Mais uma vez, a Segunda query não precisa de nenhum join de tabela. - - - - Assim mesmo, a propriedade especial class 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. - - - - - - 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 com um componente address. - - - - - - Um tipo "any" tem as propriedades id e class especiais, - nôs permitindo expressar um join da seguinte forma (onde AuditLog.item é - uma propriedade mapeada com <any>) - - - - - - Veja que log.item.class e payment.class podem - referir-se a valores de colunas de banco de dados completamente diferentes, na query acima. - - - - - - Expressões - - - As expressões permitidas na cláusula where inclui a maioria - das coisas que você poderia escrever no SQL: - - - - - - operadores matemáticos +, -, *, / - - - - - operadores de comparação binários =, >=, <=, <>, !=, like - - - - - operadores lógicos and, or, not - - - - - parenteses ( ), indicating grouping - - - - - in, - not in, - between, - is null, - is not null, - is empty, - is not empty, - member of and - not member of - - - - - case "simples" , case ... when ... then ... else ... end, and - "searched" case, case when ... then ... else ... end - - - - - concatenação de string ...||... ou concat(...,...) - - - - - current_date(), current_time(), - current_timestamp() - - - - - second(...), minute(...), - hour(...), day(...), - month(...), year(...), - - - - - qualquer funcao ou operador definida pela EJB-QL 3.0: substring(), trim(), - lower(), upper(), length(), locate(), abs(), sqrt(), bit_length(), mod() - - - - - coalesce() and nullif() - - - - - str() para converter valores numericos ou temporais para string - - - - - cast(... as ...), onde o segundo argumento é o nome do tipo - hibernate, eextract(... from ...) se ANSI - cast() e extract() é suportado pele - banco de dados usado - - - - - A função HQL index() , que se aplicam a referencias de - coleçôes associadas e indexadas - - - - - As funções hql que retornam expressões de coleções de valores: - size(), minelement(), maxelement(), minindex(), maxindex(), - junto com o elemento especial, elements(), - e funções de índice que podem ser quantificadas usando - some, all, exists, any, in. - - - - - Qualquer funçâo escalar pelo bando de dados como sign(), - trunc(), rtrim(), sin() - - - - - Parametros posicionais ao estilo JDBC ? - - - - - Parametros nomeados :name, :start_date, :x1 - - - - - Literais SQL 'foo', 69, 6.66E+2, - '1970-01-01 10:00:01.0' - - - - - Constantes Java public static final ex: Color.TABBY - - - - - - in e between podem ser usadas da seguinte maneira: - - - - - - - - e as formas negativas podem ser escritas - - - - - - - - Likewise, is null and is not null may be used to test - for null values. - Assim mesmo, , is null e is not null podem ser usados - para testar valores nulos. - - - - Booleanos podem ser facilmente usados em expressões, declarando as substituições da HQL query, - na configuração do Hibernate - - - true 1, false 0]]> - - - Isso irá substituir as palavras chave true e false - pelos literais 1 e 0 na tradução do HQL para SQL. - - - - - - Pode-se testar o tamanho de uma coleção com a propriedade especial size, - ou a função especial size(). - - - 0]]> - - 0]]> - - - Para coleções indexadas, você pode se referir aos índices máximo e mínimo, usando - as funções minindex e maxindex. Similarmente, - pode-se referir aos elementos máximo e mínimo de uma coleção de tipos básicos usando - as funções minelement e maxelement. - - - current_date]]> - - 100]]> - - 10000]]> - - - As funções SQL any, some, all, exists, in são suportadas quando passado o - elemento ou o conjunto de índices de uma coleção (elements e - indices de funções), ou o resultado de uma subquery (veja abaixo). - - - - - - - - - all elements(p.scores)]]> - - - - - Note que essas construções - size, elements, - indices, minindex, maxindex, - minelement, maxelement– - só podem ser usados na clausula where do Hibernate3. - - - - Elementos de coleções com índice (arrays, lists, maps), podem ser referenciadas - pelo índice (apenas na clausula where): - - - - - - - - - - - - A expressão entre colchetes [], pode ser até uma expressão aritimética. - - - - - - O HQL também provê a função interna index(), para elementos de - associação um-pra-muitos ou coleção de valores. - - - - - - Funções escalares SQL, suportadas pelo banco de dados subjacente. - - - - - - 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: - - - - - - Hint: something like - - - - - - - - A clausula order by - - - A lista retornada pela query pode ser ordenada por qualquer propriedade da classe ou componente retornado: - - - - - - As opções asc ou desc indicam ordem crescente ou decrescente, - respectivamente. - - - - - A clausula group by - - - Uma query que retorne valores agregados, podem ser agrupados por qualquer propriedade de uma classe - ou componente retornado: - - - - - - - - Uma clausula having também é permitida. - - - - - - Funções SQL e funções agregadas são permitidas nas clausulas - having e order by, se suportadas pelo banco - de dados subjacente (ex: não no MySQL). - - - 100 -order by count(kitten) asc, sum(kitten.weight) desc]]> - - - Note que, nem a clausula group by ou - order by, podem conter expressões aritiméticas. - - - - - - Subqueries - - - 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. - - - ( - select avg(cat.weight) from DomesticCat cat -)]]> - - - - - - - - - - - Note que HQL subqueries podem aparecer apenas dentro de clausulas select ou where. - - - - Para subqueries com mais de uma expressão na lista do select, pode-se usar um construtor - de tuplas: - - - - - - 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. - - - - - - Qual é equivalente ao mais verbalizado: - - - - - - 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. - - - - - - Exemplos de HQL - - - 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. - - - - 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 ORDER, ORDER_LINE, PRODUCT, - CATALOG e PRICE, tem quatro inner joins e um - (não correlacionado) subselect. - - - = 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]]> - - - Que monstro! Atualmente, na vida real, eu não sou muito afeiçoado a subqueries, então - minha query seria mais parecida com isto: - - - :minAmount -order by sum(price.amount) desc]]> - - - A próxima query conta o número de pagamentos em cada status, tirando todos os pagamentos com - status AWAITING_APPROVAL, onde a mais recente mudança de status foi feita - pelo usuário corrente. Traduz-se para uma query SQL com dois inner joins e - um subselect correlacionado, nas tabelas PAYMENT, - PAYMENT_STATUS e PAYMENT_STATUS_CHANGE . - - - 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]]> - - - Se eu tivesse mapeado a Collection statusChanges como um List, ao invés de um - Set, a query teria sido muito mais simples de escrever. - - - PaymentStatus.AWAITING_APPROVAL - or payment.statusChanges[ maxIndex(payment.statusChanges) ].user <> :currentUser -group by status.name, status.sortOrder -order by status.sortOrder]]> - - - A próxima query usa a função isNull() 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 com três inner joins, - um outer join e um subselect nas tabelas ACCOUNT, PAYMENT, - PAYMENT_STATUS,ACCOUNT_TYPE, - ORGANIZATION e ORG_USER . - - - - - - Para alguns bancos de dados, precisaremos eleminar o subselect (correlacionado). - - - - - - - - update e delete em lote - - - Agora o HQL suporta declarações, update, - delete e insert ... select ... - Veja , para mais detalhes. - - - - - Dicas e Truques - - - Pode-se contar o número de resultados da query, sem realmente retorna-los. - - - - - - Para ordenar um resultado pelo tamanho de uma Collection, use a query a seguir. - - - - - - 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: - - - = 1]]> - - - Se seu banco de dados não suporta subselects, use a query a seguir: - - - = 1]]> - - - Com essa solução não se pode retornar um User com sem - nenhuma menssagem, por causa do "inner join", a forma a seguir também é útil. - - - - - - As propriedades de um JavaBean podem ser limitadas à parâmetros nomeados da query: - - - - - - As Collections são paginaveis, usando a interface Query com um filtro: - - - - - - Os elementos da Collection podem ser ordenados ou agrupados - usando um filtro de query: - - - - - - Pode-se achar o tamanho de uma Collection sem inicializa-la: - - - - - - - - + + HQL: A linguagem de Queries do Hibernate + + + 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. + + + + Case Sensitíve + + + As Queries não são case-sensitive, exceto pelo nomes das classes e propriedades Java. + sELEct e o mesmo que + SELECT mas + org.hibernate.eg.FOO não é + org.hibernate.eg.Foo e + foo.barSet não é + foo.BARSET. + + + + + 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. + + + + + + A clausula from + + + A mais simples query possível do Hibernate é a assim: + + + + + + Ela irá retornar todas as instancias da classe eg.Cat. + Necessariamente não precisamos qualificar o nome da classe, pois é realizado + auto-import por padrão. Por isso na maior parte do tempos + nós simplesmente escrevemos: + + + + + + Na maior parte do tempo, você precisará atribuir um alias, + desde que você queira se referia ao Cat em outras partes da + query. + + + + + + Essa query atribui um alias a cat para as instancias de + Cat, então nós podemos usar esse alias depois na query. + A palavra chave as é opcional; poderíamos escrever assim: + + + + + + Múltiplas classes pode ser envolvidas, resultando em um produto cartesiano ou "cross" join. + + + + + + + É 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: domesticCat). + + + + + + Associações e joins + + + Nós também podemos querer atribuir aliases em uma entidade associada, ou mesmo + em elementos de uma coleção de valores, usando um join. + + + + + + + + + + Os tipos de joins suportados foram inspirados no SQL ANSI: + + + + + + inner join + + + + + left outer join + + + + + right outer join + + + + + full join (geralmente não é útil) + + + + + + The inner join, left outer join and + right outer join constructs may be abbreviated. + As construções inner join, left outer join e + right outer join podem ser abreviadas. + + + + + + Você pode fornecer condições extras de join usando a palavra + chave do HQL with. + + + with kitten.bodyWeight > 10.0]]> + + + 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 para mais informações. + + + fetchcat.mate + left join fetchcat.kittens]]> + + + Usualmente, um fetchjoin não precisa atribuir um alias, pois o objeto associado não + deve ser usado na clausula where (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: + + + fetchcat.mate + left join fetchcat.kittens child + left join fetchchild.kittens]]> + + + Observe que a construção fetch não deve ser usada em queries invocadas usando + iterate() (embora possa ser usado com scroll()). O + fetch também não deve ser usado junto com o setMaxResults() ou + setFirstResult() 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 fetch não deve ser usado junto com uma condição with em + uma condição with 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 + full join fetch e right join fetch não são significativos. + + + + + Se está usando o nível de propriedade lazy (com instrumentação de bytecode), é possível + forçar o Hibernate a buscar as propriedades lazy imediatamente (na primeira query), + usando fetch all properties . + + + fetchall properties order by name]]> + fetchall properties where lower(doc.name) like '%cats%']]> + + + + + Formas e sintaxe de joins + + + O HQL suporta duas formas de associação para união: implícita e explicita. + + + + As queries apresentadas na seção anterior usam a forma explicita, onde a + palavra chave "join" é explicitamente usada na clausula "from". Essa é a forma recomendada. + + + + A forma implícita 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 implícita resulta em declarações + SQL que contem inner joins. + + + + + + + Refering to identifier property + + + There are, generally speaking, 2 ways to refer to an entity's identifier property: + + + + + The special property (lowercase) id may be used to reference the identifier + property of an entity provided that entity does not define a non-identifier property + named id. + + + + + If the entity defines a named identifier property, you may use that property name. + + + + + + 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 id property + can be used to rerference the identifier property. + + + + Note: this has changed significantly starting in version 3.2.2. In previous versions, + id always referred to the identifier property no + matter what its actual name. A ramification of that decision was that non-identifier + properties named id could never be referenced in Hibernate queries. + + + + + Clausula select + + + A clausula select seleciona quais obetos e propriedades retornam + no resultado da query. Considere: + + + + + + A query selecionará mates (companheiros), de outros Cats. + Atualmente, podemos expressar a query de forma mais compacta como: + + + + + + Queries podem retornar propriedades de qualquer tipo de valor, incluindo propriedades de tipo de componente: + + + + + + + + + Queries podem retornar múltiplos objetos e/ou propriedades como um array do + tipo Object[], + + + + + + ou como um List, + + + + + + ou como um objeto Java typesafe, + + + + + + assumindo que a classe Family tenha um construtor apropriado. + + + + Pode-se designar referencias a expressões selecionadas, as: + + + + + + Isto é bem mais útil quando usado junto com select new map: + + + + + + Esta query retorna um Map de referencias para valores selecionados. + + + + + + Funções de agregação + + + As queries HQL podem retornar o resultado de funções agregadas nas propriedades. + + + + + + + + As funções agregadas suportadas são: + + + + + + avg(...), sum(...), min(...), max(...) + + + + + count(*) + + + + + count(...), count(distinct ...), count(all...) + + + + + + Pode-se usar operadores aritiméticos, concatenação e funções SQL + reconhecidas na clausula select: + + + + + + + + As palavras distinct e all podem ser usadas e têm + a mesma semântica como no SQL. + + + + + + + + Queries polimórficas + + + A query: + + + + + + retorna instancias não só de Cat, mas também de subclasses como + DomesticCat. As queries do Hibernate podem nomear qualquer classe Java + ou interface na clausula from. 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: + + + + + + A interface Named pode ser implementada por várias classes persistentes: + + + + + + Note que as duas últimas queries requerem mais de um SQL SELECT . Isto significa que a clausula + order by não ordena corretamente todo o resultado. (Isso também significa que + você não pode chamar essas queries usando Query.scroll().) + + + + + + A clausula where + + + A clausula where permite estreitar a lista de instancias retornada. + Se não houver referencia alguma, pode-se referir a propriedades pelo nome: + + + + + + Se houver uma referência, use o nome da propriedade qualificada: + + + + + + retorna instancias de Cat com nome ‘Fritz’. + + + + + + retornará todas as instancias de Foo, para cada + um que tiver uma instancia de bar com a propriedade + date igual a propriedade + startDate de + Foo. Expressões de filtro compostas fazem da + clausula where, extremamente poderosa. Consideremos: + + + + + + Esta query traduzida para uma query SQL com uma tabela (inner) join. Se fosse + escrever algo como: + + + + + + Poderia-se terminar com uma query que necessitasse de join de quatro tabelas, + no SQL. + + + + O operador = pode ser uasdo para comparar não apenas propriedades, + mas também instancias: + + + + + + + + A propriedade especial (lowercase) id pode ser usada para referenciar + o identificador único de um objeto. (Pode-se usar também o nome de sua propriedade) + + + + + + A Segunda query é eficiente. Nenhuma união de tabelas é necessária! + + + + As propriedades de identificadores compostas também podem ser usadas. Suponha que + Person tenha um identificador composto que consiste de + country e medicareNumber. + + + + + + + + Mais uma vez, a Segunda query não precisa de nenhum join de tabela. + + + + Assim mesmo, a propriedade especial class 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. + + + + + + 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 com um componente address. + + + + + + Um tipo "any" tem as propriedades id e class especiais, + nôs permitindo expressar um join da seguinte forma (onde AuditLog.item é + uma propriedade mapeada com <any>) + + + + + + Veja que log.item.class e payment.class podem + referir-se a valores de colunas de banco de dados completamente diferentes, na query acima. + + + + + + Expressões + + + As expressões permitidas na cláusula where inclui a maioria + das coisas que você poderia escrever no SQL: + + + + + + operadores matemáticos +, -, *, / + + + + + operadores de comparação binários =, >=, <=, <>, !=, like + + + + + operadores lógicos and, or, not + + + + + parenteses ( ), indicating grouping + + + + + in, + not in, + between, + is null, + is not null, + is empty, + is not empty, + member of and + not member of + + + + + case "simples" , case ... when ... then ... else ... end, and + "searched" case, case when ... then ... else ... end + + + + + concatenação de string ...||... ou concat(...,...) + + + + + current_date(), current_time(), + current_timestamp() + + + + + second(...), minute(...), + hour(...), day(...), + month(...), year(...), + + + + + qualquer funcao ou operador definida pela EJB-QL 3.0: substring(), trim(), + lower(), upper(), length(), locate(), abs(), sqrt(), bit_length(), mod() + + + + + coalesce() and nullif() + + + + + str() para converter valores numericos ou temporais para string + + + + + cast(... as ...), onde o segundo argumento é o nome do tipo + hibernate, eextract(... from ...) se ANSI + cast() e extract() é suportado pele + banco de dados usado + + + + + A função HQL index() , que se aplicam a referencias de + coleçôes associadas e indexadas + + + + + As funções hql que retornam expressões de coleções de valores: + size(), minelement(), maxelement(), minindex(), maxindex(), + junto com o elemento especial, elements(), + e funções de índice que podem ser quantificadas usando + some, all, exists, any, in. + + + + + Qualquer funçâo escalar pelo bando de dados como sign(), + trunc(), rtrim(), sin() + + + + + Parametros posicionais ao estilo JDBC ? + + + + + Parametros nomeados :name, :start_date, :x1 + + + + + Literais SQL 'foo', 69, 6.66E+2, + '1970-01-01 10:00:01.0' + + + + + Constantes Java public static final ex: Color.TABBY + + + + + + in e between podem ser usadas da seguinte maneira: + + + + + + + + e as formas negativas podem ser escritas + + + + + + + + Likewise, is null and is not null may be used to test + for null values. + Assim mesmo, , is null e is not null podem ser usados + para testar valores nulos. + + + + Booleanos podem ser facilmente usados em expressões, declarando as substituições da HQL query, + na configuração do Hibernate + + + true 1, false 0]]> + + + Isso irá substituir as palavras chave true e false + pelos literais 1 e 0 na tradução do HQL para SQL. + + + + + + Pode-se testar o tamanho de uma coleção com a propriedade especial size, + ou a função especial size(). + + + 0]]> + + 0]]> + + + Para coleções indexadas, você pode se referir aos índices máximo e mínimo, usando + as funções minindex e maxindex. Similarmente, + pode-se referir aos elementos máximo e mínimo de uma coleção de tipos básicos usando + as funções minelement e maxelement. + + + current_date]]> + + 100]]> + + 10000]]> + + + As funções SQL any, some, all, exists, in são suportadas quando passado o + elemento ou o conjunto de índices de uma coleção (elements e + indices de funções), ou o resultado de uma subquery (veja abaixo). + + + + + + + + + all elements(p.scores)]]> + + + + + Note que essas construções - size, elements, + indices, minindex, maxindex, + minelement, maxelement– + só podem ser usados na clausula where do Hibernate3. + + + + Elementos de coleções com índice (arrays, lists, maps), podem ser referenciadas + pelo índice (apenas na clausula where): + + + + + + + + + + + + A expressão entre colchetes [], pode ser até uma expressão aritimética. + + + + + + O HQL também provê a função interna index(), para elementos de + associação um-pra-muitos ou coleção de valores. + + + + + + Funções escalares SQL, suportadas pelo banco de dados subjacente. + + + + + + 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: + + + + + + Hint: something like + + + + + + + + A clausula order by + + + A lista retornada pela query pode ser ordenada por qualquer propriedade da classe ou componente retornado: + + + + + + As opções asc ou desc indicam ordem crescente ou decrescente, + respectivamente. + + + + + A clausula group by + + + Uma query que retorne valores agregados, podem ser agrupados por qualquer propriedade de uma classe + ou componente retornado: + + + + + + + + Uma clausula having também é permitida. + + + + + + Funções SQL e funções agregadas são permitidas nas clausulas + having e order by, se suportadas pelo banco + de dados subjacente (ex: não no MySQL). + + + 100 +order by count(kitten) asc, sum(kitten.weight) desc]]> + + + Note que, nem a clausula group by ou + order by, podem conter expressões aritiméticas. + + + + + + Subqueries + + + 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. + + + ( + select avg(cat.weight) from DomesticCat cat +)]]> + + + + + + + + + + + Note que HQL subqueries podem aparecer apenas dentro de clausulas select ou where. + + + + Note that subqueries can also utilize row value constructor syntax. See + for more details. + + + + + Exemplos de HQL + + + 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. + + + + 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 ORDER, ORDER_LINE, PRODUCT, + CATALOG e PRICE, tem quatro inner joins e um + (não correlacionado) subselect. + + + = 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]]> + + + Que monstro! Atualmente, na vida real, eu não sou muito afeiçoado a subqueries, então + minha query seria mais parecida com isto: + + + :minAmount +order by sum(price.amount) desc]]> + + + A próxima query conta o número de pagamentos em cada status, tirando todos os pagamentos com + status AWAITING_APPROVAL, onde a mais recente mudança de status foi feita + pelo usuário corrente. Traduz-se para uma query SQL com dois inner joins e + um subselect correlacionado, nas tabelas PAYMENT, + PAYMENT_STATUS e PAYMENT_STATUS_CHANGE . + + + 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]]> + + + Se eu tivesse mapeado a Collection statusChanges como um List, ao invés de um + Set, a query teria sido muito mais simples de escrever. + + + PaymentStatus.AWAITING_APPROVAL + or payment.statusChanges[ maxIndex(payment.statusChanges) ].user <> :currentUser +group by status.name, status.sortOrder +order by status.sortOrder]]> + + + A próxima query usa a função isNull() 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 com três inner joins, + um outer join e um subselect nas tabelas ACCOUNT, PAYMENT, + PAYMENT_STATUS,ACCOUNT_TYPE, + ORGANIZATION e ORG_USER . + + + + + + Para alguns bancos de dados, precisaremos eleminar o subselect (correlacionado). + + + + + + + + update e delete em lote + + + Agora o HQL suporta declarações, update, + delete e insert ... select ... + Veja , para mais detalhes. + + + + + Dicas e Truques + + + Pode-se contar o número de resultados da query, sem realmente retorna-los. + + + + + + Para ordenar um resultado pelo tamanho de uma Collection, use a query a seguir. + + + + + + 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: + + + = 1]]> + + + Se seu banco de dados não suporta subselects, use a query a seguir: + + + = 1]]> + + + Com essa solução não se pode retornar um User com sem + nenhuma menssagem, por causa do "inner join", a forma a seguir também é útil. + + + + + + As propriedades de um JavaBean podem ser limitadas à parâmetros nomeados da query: + + + + + + As Collections são paginaveis, usando a interface Query com um filtro: + + + + + + Os elementos da Collection podem ser ordenados ou agrupados + usando um filtro de query: + + + + + + Pode-se achar o tamanho de uma Collection sem inicializa-la: + + + + + + + + diff --git a/documentation/manual/pt-BR/src/main/docbook/content/query_sql.xml b/documentation/manual/pt-BR/src/main/docbook/content/query_sql.xml index 8fd6879383..2eb9baa35d 100755 --- a/documentation/manual/pt-BR/src/main/docbook/content/query_sql.xml +++ b/documentation/manual/pt-BR/src/main/docbook/content/query_sql.xml @@ -1,7 +1,7 @@ - + Native SQL You may also express queries in the native SQL dialect of your diff --git a/documentation/manual/pt-BR/src/main/docbook/content/session_api.xml b/documentation/manual/pt-BR/src/main/docbook/content/session_api.xml index 3d5fdbc7ca..59aa2f06dd 100755 --- a/documentation/manual/pt-BR/src/main/docbook/content/session_api.xml +++ b/documentation/manual/pt-BR/src/main/docbook/content/session_api.xml @@ -1,1248 +1,1270 @@ - - Trabalhando com objetos - - - 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 gerenciamento de estado - para objetos. Isto é, ao contrário do gerenciamento de instruções - SQL em camadas de persistência JDBC/SQL comuns, uma visão natural da persistência - orientada a objetos em aplicações Java. - - - - Em outras palavras, desenvolvedores de aplicações Hibernate podem sempre pensar em - relação ao estado 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. - - - - Estado dos objetos no Hibernate - - - O Hibernate define e suporta os seguintes estados de um objetos: - - - - - - Transient - um objeto é transiente se ele foi instanciando - usando apenas o operador new, e não foi associado com uma - Session 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 Session 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). - - - - - Persistent -– 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 - Session. 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 UPDATE, ou instruções de DELETE - quando o objeto deve ser passado para transiente. - - - - - Detached – uma instância desaclopada é um objeto que - foi persistido, mas sua Session foi fechada. A referência - ao objeto continua válida, é claro, e a instância destacada desaclopada pode - ser acoplada a uma nova Session 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 transações da aplicação, i.e. uma unidade - de trabalho do ponto de vista do usuário. - - - - - - Agora iremos discutir os estados e suas transições ( e os métodos do Hibernate que - disparam uma transição) em mais detalhes. - - - - - - Tornando os objetos persistentes - - - Instâncias recentemente instanciadas de uma classe persistente são - consideradas transientes pelo Hibernate. - Podemos tornar uma instância transiente em persistente - associando-a a uma sessão: - - - - - - Se Cat possui um identificador gerado, o identificador - é gerado e atribuído a cat quando save() - for chamada. Se Cat possuir um identificador - Associado, ou uma chave composta, o identificador deve ser - atribuído à instância de cat antes que save() - seja chamado. Pode-se usar também persist() ao invés de - save(), com a semântica definada no novo esboço do EJB3. - - - - Alternativamente, pode-se atribuir o identificador usando uma versão - sobrecarregada de save(). - - - - - - Se o objeto persistido possuir objetos associados (e.g. a coleção - kittens no exemplo anterior), esses objetos podem ser - tornar persistente em qualquer ordem que se queira ao menos que se tenha uma - restrição NOT NULL 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 NOT NULL se - save() for usada nos objetos em uma ordem errada. - - - - Geralmente você não deve se importar com esses detalhes, muito provavelmente se - usará a característica de persistência transitiva do Hibernate - para salvar os objetos associados automaticamente. Então, enquanto uma restrição - NOT NULL não ocorrer – Hibernate tomará conta de tudo. - Persistência transitiva será discutida futuramente nesse capítulo. - - - - - - Carregando o objetos - - - O método load() de uma Session nos - fornece um meio para recuperar uma instância persistente se o identificador - for conhecido. load() recebe uma classe do objeto e carregará - o estado em uma instância mais recente dessa classe, no estado persistente. - - - - - - - - Alternatively, you can load state into a given instance: -Alternativamente, pode-se carregar um estado em uma instância dada: - - - - - - Repare que load() 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, load() - 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 batch-size estiver para o mapeamento da - classe. - - - - Se você não tiver certeza da existencia do registro no banco, você deve - usar o metodo get(), que consulta o banco - imediantamente e retorna um null se não existir o registro. - - - - - - Também pode-se carregar um objeto usando SELECT ... FOR UPDATE, - usando um LockMode. Veja a documentação da API para maiores - informações. - - - - - - Note that any associated instances or contained collections are - not selected FOR UPDATE, unless you decide - to specify lock or all as a - cascade style for the association. - - - - O recarregamento de um objeto e todas as suas coleções é possível a qualquer momento, - usando o método refresh(). Util quando as triggers do banco de - dados são usados para inicializar algumas propriedades do objeto. - - - - - - Uma importante questão geralmente aparece neste ponto: O quanto Hibernate carrega - do banco de dados e quantos SQL SELECT ele irá usar? Isto - depende da estratégia de recuperaçãousada e explicada na - . - - - - - - Consultando - - - 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. - - - - Executando consultas - - - Consultas HQL e SQL nativa são representadas por uma instância de org.hibernate.Query. - 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 Query usando a - Session atual: - - - - - - Geralmente uma consulta é executada ao invocar list(), - 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 uniqueResult() 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 Set. - - - - Interagindo com resultados - - - Ocasionalmente, deves-se ser capaz de atingir performances melhores com - a execução de consultas usando o método iterate(). - 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, iterate() - será mais devagar do que list() e pode ser necessário vários - acessos ao banco de dados para um simples consulta, geralmente 1 - para a seleção inicial que retorna apenas identificadores, e n - consultas adicionais para inicializar as instâncias reais. - - - - - - - Consultas que retornam tuplas - - - Algumas vezes as consultas do Hibernate retornam tuplas de objetos, nesse caso - cada tupla é retornada como um array: - - - - - - - - Resultados escalares - - - Consultas devem especificar uma propriedade da classe na clausula - select. 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). - - - - - - - - Bind parameters - - - Methods on Query are provided for binding values to - named parameters or JDBC-style ? parameters. - Contrary to JDBC, Hibernate numbers parameters from zero. - Named parameters are identifiers of the form :name in - the query string. The advantages of named parameters are: - - - - - - named parameters are insensitive to the order they occur in the - query string - - - - - they may occur multiple times in the same query - - - - - they are self-documenting - - - - - - - - - - - - - - Pagination - - - 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 Query interface: - - - - - - Hibernate knows how to translate this limit query into the native - SQL of your DBMS. - - - - - - Scrollable iteration - - - If your JDBC driver supports scrollable ResultSets, the - Query interface may be used to obtain a - ScrollableResults object, which allows flexible - navigation of the query results. - - - i++ ) && cats.next() ) pageOfCats.add( cats.get(1) ); - -} -cats.close()]]> - - - Note that an open database connection (and cursor) is required for this - functionality, use setMaxResult()/setFirstResult() - if you need offline pagination functionality. - - - - - - Externalizing named queries - - - You may also define named queries in the mapping document. (Remember to use a - CDATA section if your query contains characters that could - be interpreted as markup.) - - - ? -] ]>]]> - - - Parameter binding and executing is done programatically: - - - - - - 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. - - - - Also note that a query declaration inside a <hibernate-mapping> - element requires a global unique name for the query, while a query declaration inside a - <class> element is made unique automatically by prepending the - fully qualified name of the class, for example - eg.Cat.ByNameAndMaximumWeight. - - - - - - - - Filtering collections - - A collection filter is a special type of query that may be applied to - a persistent collection or array. The query string may refer to this, - meaning the current collection element. - - - - - - 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). - - - - Observe that filters do not require a from clause (though they may have - one if required). Filters are not limited to returning the collection elements themselves. - - - - - - Even an empty filter query is useful, e.g. to load a subset of elements in a - huge collection: - - - - - - - - Criteria queries - - - 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 Criteria query API for these cases: - - - - - - The Criteria and the associated Example - API are discussed in more detail in . - - - - - - Queries in native SQL - - - You may express a query in SQL, using createSQLQuery() and - let Hibernate take care of the mapping from result sets to objects. Note - that you may at any time call session.connection() and - use the JDBC Connection directly. If you chose to use the - Hibernate API, you must enclose SQL aliases in braces: - - - - - - - - SQL queries may contain named and positional parameters, just like Hibernate queries. - More information about native SQL queries in Hibernate can be found in - . - - - - - - - - Modifying persistent objects - - - Transactional persistent instances (ie. objects loaded, saved, created or - queried by the Session) may be manipulated by the application - and any changes to persistent state will be persisted when the Session - is flushed (discussed later in this chapter). There is no need - to call a particular method (like update(), which has a different - purpose) to make your modifications persistent. So the most straightforward way to update - the state of an object is to load() it, - and then manipulate it directly, while the Session is open: - - - - - - Sometimes this programming model is inefficient since it would require both an SQL - SELECT (to load an object) and an SQL UPDATE - (to persist its updated state) in the same session. Therefore Hibernate offers an - alternate approach, using detached instances. - - - - Note that Hibernate does not offer its own API for direct execution of - UPDATE or DELETE statements. Hibernate is a - state management service, you don't have to think in - statements to use it. JDBC is a perfect API for executing - SQL statements, you can get a JDBC Connection at any time - by calling session.connection(). Furthermore, the notion - of mass operations conflicts with object/relational mapping for online - transaction processing-oriented applications. Future versions of Hibernate - may however provide special mass operation functions. See - for some possible batch operation tricks. - - - - - - Modifying detached objects - - - 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. - - - - Hibernate supports this model by providing for reattachment of detached instances - using the Session.update() or Session.merge() - methods: - - - - - - If the Cat with identifier catId had already - been loaded by secondSession when the application tried to - reattach it, an exception would have been thrown. - - - - Use update() if you are sure that the session does - not contain an already persistent instance with the same identifier, and - merge() if you want to merge your modifications at any time - without consideration of the state of the session. In other words, update() - 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. - - - - The application should individually update() detached instances - reachable from the given detached instance if and only if it wants - their state also updated. This can be automated of course, using transitive - persistence, see . - - - - The lock() method also allows an application to reassociate - an object with a new session. However, the detached instance has to be unmodified! - - - - - - Note that lock() can be used with various - LockModes, see the API documentation and the - chapter on transaction handling for more information. Reattachment is not - the only usecase for lock(). - - - - Other models for long units of work are discussed in . - - - - - - Automatic state detection - - - 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 saveOrUpdate() method implements this functionality. - - - - - - The usage and semantics of saveOrUpdate() 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 update(), - saveOrUpdate(), or merge(). Some whole - applications will never use either of these methods. - - - - Usually update() or saveOrUpdate() are used in - the following scenario: - - - - - - the application loads an object in the first session - - - - - the object is passed up to the UI tier - - - - - some modifications are made to the object - - - - - the object is passed back down to the business logic tier - - - - - the application persists these modifications by calling - update() in a second session - - - - - - saveOrUpdate() does the following: - - - - - - if the object is already persistent in this session, do nothing - - - - - if another object associated with the session has the same identifier, - throw an exception - - - - - if the object has no identifier property, save() it - - - - - if the object's identifier has the value assigned to a newly instantiated - object, save() it - - - - - if the object is versioned (by a <version> or - <timestamp>), and the version property value - is the same value assigned to a newly instantiated object, - save() it - - - - - otherwise update() the object - - - - - - and merge() is very different: - - - - - - 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 - - - - - if there is no persistent instance currently associated with the session, - try to load it from the database, or create a new persistent instance - - - - - the persistent instance is returned - - - - - the given instance does not become associated with the session, it - remains detached - - - - - - - - Deleting persistent objects - - - Session.delete() 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 delete() as making a persistent instance - transient. - - - - - - You may delete objects in any order you like, without risk of foreign key - constraint violations. It is still possible to violate a NOT - NULL 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. - - - - - - Replicating object between two different datastores - - - 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. - - - - - - The ReplicationMode determines how replicate() - will deal with conflicts with existing rows in the database. - - - - - - ReplicationMode.IGNORE - ignore the object when there is - an existing database row with the same identifier - - - - - ReplicationMode.OVERWRITE - overwrite any existing database - row with the same identifier - - - - - ReplicationMode.EXCEPTION - throw an exception if there is - an existing database row with the same identifier - - - - - ReplicationMode.LATEST_VERSION - overwrite the row if its - version number is earlier than the version number of the object, or ignore - the object otherwise - - - - - - 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. - - - - - - Flushing the Session - - - From time to time the Session will execute the SQL statements - needed to synchronize the JDBC connection's state with the state of objects held in - memory. This process, flush, occurs by default at the following - points - - - - - - before some query executions - - - - - from org.hibernate.Transaction.commit() - - - - - from Session.flush() - - - - - - The SQL statements are issued in the following order - - - - - - all entity insertions, in the same order the corresponding objects - were saved using Session.save() - - - - - all entity updates - - - - - all collection deletions - - - - - all collection element deletions, updates and insertions - - - - - all collection insertions - - - - - all entity deletions, in the same order the corresponding objects - were deleted using Session.delete() - - - - - - (An exception is that objects using native ID generation are - inserted when they are saved.) - - - - Except when you explicity flush(), there are absolutely no - guarantees about when the Session executes - the JDBC calls, only the order in which they are executed. - However, Hibernate does guarantee that the Query.list(..) - will never return stale data; nor will they return the wrong data. - - - - It is possible to change the default behavior so that flush occurs less frequently. - The FlushMode class defines three different modes: only flush - at commit time (and only when the Hibernate Transaction API - is used), flush automatically using the explained routine, or never flush unless - flush() is called explicitly. The last mode is useful for long running - units of work, where a Session is kept open and disconnected for - a long time (see ). - - - - - - 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 . - - - - - - Transitive persistence - - - 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: - - - - 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. - - - - 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 persistence by reachability by default. - - - - For each basic operation of the Hibernate session - including persist(), merge(), - saveOrUpdate(), delete(), lock(), refresh(), evict(), replicate() - there is a - corresponding cascade style. Respectively, the cascade styles are named create, - merge, save-update, delete, lock, refresh, evict, replicate. If you want an - operation to be cascaded along an association, you must indicate that in the mapping - document. For example: - - - ]]> - - - Cascade styles my be combined: - - - ]]> - - - You may even use cascade="all" to specify that all - operations should be cascaded along the association. The default cascade="none" - specifies that no operations are to be cascaded. - - - - A special cascade style, delete-orphan, applies only to one-to-many - associations, and indicates that the delete() operation should - be applied to any child object that is removed from the association. - - - - - Recommendations: - - - - - - It doesn't usually make sense to enable cascade on a <many-to-one> - or <many-to-many> association. Cascade is often useful for - <one-to-one> and <one-to-many> - associations. - - - - - If the child object's lifespan is bounded by the lifespan of the parent - object, make it a life cycle object by specifying - cascade="all,delete-orphan". - - - - - 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 cascade="persist,merge,save-update". - - - - - - Mapping an association (either a single valued association, or a collection) with - cascade="all" marks the association as a - parent/child style relationship where save/update/delete of the - parent results in save/update/delete of the child or children. - - - 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 not automatically deleted, except - in the case of a <one-to-many> association mapped with - cascade="delete-orphan". The precise semantics of cascading - operations for a parent/child relationship are as follows: - - - - - - If a parent is passed to persist(), all children are passed to - persist() - - - - - If a parent is passed to merge(), all children are passed to - merge() - - - - - If a parent is passed to save(), update() or - saveOrUpdate(), all children are passed to saveOrUpdate() - - - - - If a transient or detached child becomes referenced by a persistent parent, - it is passed to saveOrUpdate() - - - - - If a parent is deleted, all children are passed to delete() - - - - - If a child is dereferenced by a persistent parent, nothing - special happens - the application should explicitly delete - the child if necessary - unless cascade="delete-orphan", - in which case the "orphaned" child is deleted. - - - - - - Finally, note that cascading of operations can be applied to an object graph at - call time or at flush time. All operations, - if enabled, are cascaded to associated entities reachable when the operation is - executed. However, save-upate and delete-orphan - are transitive for all associated entities reachable during flush of the - Session. - - - - - - Usando metadados - - - 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). - - - O Hibernate expõe o metadados via interfaces ClassMetadata - e CollectionMetadata e pela hierarquia Type. - Instâncias das interfaces de metadados podem ser obtidas a partir do - SessionFactory. - - - - - - - - + + Trabalhando com objetos + + + 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 gerenciamento de estado + para objetos. Isto é, ao contrário do gerenciamento de instruções + SQL em camadas de persistência JDBC/SQL comuns, uma visão natural da persistência + orientada a objetos em aplicações Java. + + + + Em outras palavras, desenvolvedores de aplicações Hibernate podem sempre pensar em + relação ao estado 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. + + + + Estado dos objetos no Hibernate + + + O Hibernate define e suporta os seguintes estados de um objetos: + + + + + + Transient - um objeto é transiente se ele foi instanciando + usando apenas o operador new, e não foi associado com uma + Session 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 Session 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). + + + + + Persistent -– 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 + Session. 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 UPDATE, ou instruções de DELETE + quando o objeto deve ser passado para transiente. + + + + + Detached – uma instância desaclopada é um objeto que + foi persistido, mas sua Session foi fechada. A referência + ao objeto continua válida, é claro, e a instância destacada desaclopada pode + ser acoplada a uma nova Session 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 transações da aplicação, i.e. uma unidade + de trabalho do ponto de vista do usuário. + + + + + + Agora iremos discutir os estados e suas transições ( e os métodos do Hibernate que + disparam uma transição) em mais detalhes. + + + + + + Tornando os objetos persistentes + + + Instâncias recentemente instanciadas de uma classe persistente são + consideradas transientes pelo Hibernate. + Podemos tornar uma instância transiente em persistente + associando-a a uma sessão: + + + + + + Se Cat possui um identificador gerado, o identificador + é gerado e atribuído a cat quando save() + for chamada. Se Cat possuir um identificador + Associado, ou uma chave composta, o identificador deve ser + atribuído à instância de cat antes que save() + seja chamado. Pode-se usar também persist() ao invés de + save(), com a semântica definada no novo esboço do EJB3. + + + + + + persist() 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. + persist() also guarantees that it will not execute an + INSERT statement if it is called outside of transaction + boundaries. This is useful in long-running conversations with an extended + Session/persistence context. + + + + + save() 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. + + + + + Alternativamente, pode-se atribuir o identificador usando uma versão + sobrecarregada de save(). + + + + + + Se o objeto persistido possuir objetos associados (e.g. a coleção + kittens no exemplo anterior), esses objetos podem ser + tornar persistente em qualquer ordem que se queira ao menos que se tenha uma + restrição NOT NULL 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 NOT NULL se + save() for usada nos objetos em uma ordem errada. + + + + Geralmente você não deve se importar com esses detalhes, muito provavelmente se + usará a característica de persistência transitiva do Hibernate + para salvar os objetos associados automaticamente. Então, enquanto uma restrição + NOT NULL não ocorrer – Hibernate tomará conta de tudo. + Persistência transitiva será discutida futuramente nesse capítulo. + + + + + + Carregando o objetos + + + O método load() de uma Session nos + fornece um meio para recuperar uma instância persistente se o identificador + for conhecido. load() recebe uma classe do objeto e carregará + o estado em uma instância mais recente dessa classe, no estado persistente. + + + + + + + + Alternatively, you can load state into a given instance: +Alternativamente, pode-se carregar um estado em uma instância dada: + + + + + + Repare que load() 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, load() + 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 batch-size estiver para o mapeamento da + classe. + + + + Se você não tiver certeza da existencia do registro no banco, você deve + usar o metodo get(), que consulta o banco + imediantamente e retorna um null se não existir o registro. + + + + + + Também pode-se carregar um objeto usando SELECT ... FOR UPDATE, + usando um LockMode. Veja a documentação da API para maiores + informações. + + + + + + Note that any associated instances or contained collections are + not selected FOR UPDATE, unless you decide + to specify lock or all as a + cascade style for the association. + + + + O recarregamento de um objeto e todas as suas coleções é possível a qualquer momento, + usando o método refresh(). Util quando as triggers do banco de + dados são usados para inicializar algumas propriedades do objeto. + + + + + + Uma importante questão geralmente aparece neste ponto: O quanto Hibernate carrega + do banco de dados e quantos SQL SELECT ele irá usar? Isto + depende da estratégia de recuperaçãousada e explicada na + . + + + + + + Consultando + + + 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. + + + + Executando consultas + + + Consultas HQL e SQL nativa são representadas por uma instância de org.hibernate.Query. + 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 Query usando a + Session atual: + + + + + + Geralmente uma consulta é executada ao invocar list(), + 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 uniqueResult() 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 Set. + + + + Interagindo com resultados + + + Ocasionalmente, deves-se ser capaz de atingir performances melhores com + a execução de consultas usando o método iterate(). + 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, iterate() + será mais devagar do que list() e pode ser necessário vários + acessos ao banco de dados para um simples consulta, geralmente 1 + para a seleção inicial que retorna apenas identificadores, e n + consultas adicionais para inicializar as instâncias reais. + + + + + + + Consultas que retornam tuplas + + + Algumas vezes as consultas do Hibernate retornam tuplas de objetos, nesse caso + cada tupla é retornada como um array: + + + + + + + + Resultados escalares + + + Consultas devem especificar uma propriedade da classe na clausula + select. 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). + + + + + + + + Bind parameters + + + Methods on Query are provided for binding values to + named parameters or JDBC-style ? parameters. + Contrary to JDBC, Hibernate numbers parameters from zero. + Named parameters are identifiers of the form :name in + the query string. The advantages of named parameters are: + + + + + + named parameters are insensitive to the order they occur in the + query string + + + + + they may occur multiple times in the same query + + + + + they are self-documenting + + + + + + + + + + + + + + Pagination + + + 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 Query interface: + + + + + + Hibernate knows how to translate this limit query into the native + SQL of your DBMS. + + + + + + Scrollable iteration + + + If your JDBC driver supports scrollable ResultSets, the + Query interface may be used to obtain a + ScrollableResults object, which allows flexible + navigation of the query results. + + + i++ ) && cats.next() ) pageOfCats.add( cats.get(1) ); + +} +cats.close()]]> + + + Note that an open database connection (and cursor) is required for this + functionality, use setMaxResult()/setFirstResult() + if you need offline pagination functionality. + + + + + + Externalizing named queries + + + You may also define named queries in the mapping document. (Remember to use a + CDATA section if your query contains characters that could + be interpreted as markup.) + + + ? +] ]>]]> + + + Parameter binding and executing is done programatically: + + + + + + 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. + + + + Also note that a query declaration inside a <hibernate-mapping> + element requires a global unique name for the query, while a query declaration inside a + <class> element is made unique automatically by prepending the + fully qualified name of the class, for example + eg.Cat.ByNameAndMaximumWeight. + + + + + + + + Filtering collections + + A collection filter is a special type of query that may be applied to + a persistent collection or array. The query string may refer to this, + meaning the current collection element. + + + + + + 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). + + + + Observe that filters do not require a from clause (though they may have + one if required). Filters are not limited to returning the collection elements themselves. + + + + + + Even an empty filter query is useful, e.g. to load a subset of elements in a + huge collection: + + + + + + + + Criteria queries + + + 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 Criteria query API for these cases: + + + + + + The Criteria and the associated Example + API are discussed in more detail in . + + + + + + Queries in native SQL + + + You may express a query in SQL, using createSQLQuery() and + let Hibernate take care of the mapping from result sets to objects. Note + that you may at any time call session.connection() and + use the JDBC Connection directly. If you chose to use the + Hibernate API, you must enclose SQL aliases in braces: + + + + + + + + SQL queries may contain named and positional parameters, just like Hibernate queries. + More information about native SQL queries in Hibernate can be found in + . + + + + + + + + Modifying persistent objects + + + Transactional persistent instances (ie. objects loaded, saved, created or + queried by the Session) may be manipulated by the application + and any changes to persistent state will be persisted when the Session + is flushed (discussed later in this chapter). There is no need + to call a particular method (like update(), which has a different + purpose) to make your modifications persistent. So the most straightforward way to update + the state of an object is to load() it, + and then manipulate it directly, while the Session is open: + + + + + + Sometimes this programming model is inefficient since it would require both an SQL + SELECT (to load an object) and an SQL UPDATE + (to persist its updated state) in the same session. Therefore Hibernate offers an + alternate approach, using detached instances. + + + + Note that Hibernate does not offer its own API for direct execution of + UPDATE or DELETE statements. Hibernate is a + state management service, you don't have to think in + statements to use it. JDBC is a perfect API for executing + SQL statements, you can get a JDBC Connection at any time + by calling session.connection(). Furthermore, the notion + of mass operations conflicts with object/relational mapping for online + transaction processing-oriented applications. Future versions of Hibernate + may however provide special mass operation functions. See + for some possible batch operation tricks. + + + + + + Modifying detached objects + + + 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. + + + + Hibernate supports this model by providing for reattachment of detached instances + using the Session.update() or Session.merge() + methods: + + + + + + If the Cat with identifier catId had already + been loaded by secondSession when the application tried to + reattach it, an exception would have been thrown. + + + + Use update() if you are sure that the session does + not contain an already persistent instance with the same identifier, and + merge() if you want to merge your modifications at any time + without consideration of the state of the session. In other words, update() + 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. + + + + The application should individually update() detached instances + reachable from the given detached instance if and only if it wants + their state also updated. This can be automated of course, using transitive + persistence, see . + + + + The lock() method also allows an application to reassociate + an object with a new session. However, the detached instance has to be unmodified! + + + + + + Note that lock() can be used with various + LockModes, see the API documentation and the + chapter on transaction handling for more information. Reattachment is not + the only usecase for lock(). + + + + Other models for long units of work are discussed in . + + + + + + Automatic state detection + + + 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 saveOrUpdate() method implements this functionality. + + + + + + The usage and semantics of saveOrUpdate() 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 update(), + saveOrUpdate(), or merge(). Some whole + applications will never use either of these methods. + + + + Usually update() or saveOrUpdate() are used in + the following scenario: + + + + + + the application loads an object in the first session + + + + + the object is passed up to the UI tier + + + + + some modifications are made to the object + + + + + the object is passed back down to the business logic tier + + + + + the application persists these modifications by calling + update() in a second session + + + + + + saveOrUpdate() does the following: + + + + + + if the object is already persistent in this session, do nothing + + + + + if another object associated with the session has the same identifier, + throw an exception + + + + + if the object has no identifier property, save() it + + + + + if the object's identifier has the value assigned to a newly instantiated + object, save() it + + + + + if the object is versioned (by a <version> or + <timestamp>), and the version property value + is the same value assigned to a newly instantiated object, + save() it + + + + + otherwise update() the object + + + + + + and merge() is very different: + + + + + + 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 + + + + + if there is no persistent instance currently associated with the session, + try to load it from the database, or create a new persistent instance + + + + + the persistent instance is returned + + + + + the given instance does not become associated with the session, it + remains detached + + + + + + + + Deleting persistent objects + + + Session.delete() 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 delete() as making a persistent instance + transient. + + + + + + You may delete objects in any order you like, without risk of foreign key + constraint violations. It is still possible to violate a NOT + NULL 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. + + + + + + Replicating object between two different datastores + + + 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. + + + + + + The ReplicationMode determines how replicate() + will deal with conflicts with existing rows in the database. + + + + + + ReplicationMode.IGNORE - ignore the object when there is + an existing database row with the same identifier + + + + + ReplicationMode.OVERWRITE - overwrite any existing database + row with the same identifier + + + + + ReplicationMode.EXCEPTION - throw an exception if there is + an existing database row with the same identifier + + + + + ReplicationMode.LATEST_VERSION - overwrite the row if its + version number is earlier than the version number of the object, or ignore + the object otherwise + + + + + + 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. + + + + + + Flushing the Session + + + From time to time the Session will execute the SQL statements + needed to synchronize the JDBC connection's state with the state of objects held in + memory. This process, flush, occurs by default at the following + points + + + + + + before some query executions + + + + + from org.hibernate.Transaction.commit() + + + + + from Session.flush() + + + + + + The SQL statements are issued in the following order + + + + + + all entity insertions, in the same order the corresponding objects + were saved using Session.save() + + + + + all entity updates + + + + + all collection deletions + + + + + all collection element deletions, updates and insertions + + + + + all collection insertions + + + + + all entity deletions, in the same order the corresponding objects + were deleted using Session.delete() + + + + + + (An exception is that objects using native ID generation are + inserted when they are saved.) + + + + Except when you explicity flush(), there are absolutely no + guarantees about when the Session executes + the JDBC calls, only the order in which they are executed. + However, Hibernate does guarantee that the Query.list(..) + will never return stale data; nor will they return the wrong data. + + + + It is possible to change the default behavior so that flush occurs less frequently. + The FlushMode class defines three different modes: only flush + at commit time (and only when the Hibernate Transaction API + is used), flush automatically using the explained routine, or never flush unless + flush() is called explicitly. The last mode is useful for long running + units of work, where a Session is kept open and disconnected for + a long time (see ). + + + + + + 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 . + + + + + + Transitive persistence + + + 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: + + + + 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. + + + + 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 persistence by reachability by default. + + + + For each basic operation of the Hibernate session - including persist(), merge(), + saveOrUpdate(), delete(), lock(), refresh(), evict(), replicate() - there is a + corresponding cascade style. Respectively, the cascade styles are named create, + merge, save-update, delete, lock, refresh, evict, replicate. If you want an + operation to be cascaded along an association, you must indicate that in the mapping + document. For example: + + + ]]> + + + Cascade styles my be combined: + + + ]]> + + + You may even use cascade="all" to specify that all + operations should be cascaded along the association. The default cascade="none" + specifies that no operations are to be cascaded. + + + + A special cascade style, delete-orphan, applies only to one-to-many + associations, and indicates that the delete() operation should + be applied to any child object that is removed from the association. + + + + + Recommendations: + + + + + + It doesn't usually make sense to enable cascade on a <many-to-one> + or <many-to-many> association. Cascade is often useful for + <one-to-one> and <one-to-many> + associations. + + + + + If the child object's lifespan is bounded by the lifespan of the parent + object, make it a life cycle object by specifying + cascade="all,delete-orphan". + + + + + 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 cascade="persist,merge,save-update". + + + + + + Mapping an association (either a single valued association, or a collection) with + cascade="all" marks the association as a + parent/child style relationship where save/update/delete of the + parent results in save/update/delete of the child or children. + + + 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 not automatically deleted, except + in the case of a <one-to-many> association mapped with + cascade="delete-orphan". The precise semantics of cascading + operations for a parent/child relationship are as follows: + + + + + + If a parent is passed to persist(), all children are passed to + persist() + + + + + If a parent is passed to merge(), all children are passed to + merge() + + + + + If a parent is passed to save(), update() or + saveOrUpdate(), all children are passed to saveOrUpdate() + + + + + If a transient or detached child becomes referenced by a persistent parent, + it is passed to saveOrUpdate() + + + + + If a parent is deleted, all children are passed to delete() + + + + + If a child is dereferenced by a persistent parent, nothing + special happens - the application should explicitly delete + the child if necessary - unless cascade="delete-orphan", + in which case the "orphaned" child is deleted. + + + + + + Finally, note that cascading of operations can be applied to an object graph at + call time or at flush time. All operations, + if enabled, are cascaded to associated entities reachable when the operation is + executed. However, save-upate and delete-orphan + are transitive for all associated entities reachable during flush of the + Session. + + + + + + Usando metadados + + + 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). + + + O Hibernate expõe o metadados via interfaces ClassMetadata + e CollectionMetadata e pela hierarquia Type. + Instâncias das interfaces de metadados podem ser obtidas a partir do + SessionFactory. + + + + + + + + diff --git a/documentation/manual/pt-BR/src/main/docbook/content/toolset_guide.xml b/documentation/manual/pt-BR/src/main/docbook/content/toolset_guide.xml index 9a9a6df9d6..e513b8b10b 100755 --- a/documentation/manual/pt-BR/src/main/docbook/content/toolset_guide.xml +++ b/documentation/manual/pt-BR/src/main/docbook/content/toolset_guide.xml @@ -1,7 +1,7 @@ - + Toolset Guide diff --git a/documentation/manual/pt-BR/src/main/docbook/content/transactions.xml b/documentation/manual/pt-BR/src/main/docbook/content/transactions.xml index 489933e3cf..5f62199047 100755 --- a/documentation/manual/pt-BR/src/main/docbook/content/transactions.xml +++ b/documentation/manual/pt-BR/src/main/docbook/content/transactions.xml @@ -1,1150 +1,1148 @@ - - Transações e Concorrência - - - 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. - - - - 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 Session, 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). - - - - 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 - SELECT FOR UPDATE. O controle de concorrência otimista e esta - API são discutidos mais tarde neste capítulo. - - - - Nós começamos a discussão do controle de concorrência no Hibernate com a granularidade - do Configuration, SessionFactory, e - Session, além de transações de base de dados e conversações longas. - - - - Session e escopos de transações - - - Um SessionFactory é 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 Configuration. - - - - Uma Session é 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 Session não obterá um - JDBC Connection (ou um Datasource) a menos que - necessite, conseqüentemente não consome nenhum recurso até ser usado. - - - - 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. - - - - Qual é o escopo de uma unidade de trabalho? Pode uma únicoa Session - do Hibernate gerenciar diversas transações ou é esta um o relacionamento um-para-um dos - escopos? Quando deve você abrir e fechar uma Session e como você - demarca os limites da transação? - - - - Unidade de trabalho - - - Primeiro, não use o antipattern sessão-por-operação, - isto é, não abra e não feche uma Session 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. - - - - O pattern mais comum em uma aplicação multi-usuário cliente/servidor é - sessão-por-requisição. Neste modelo, uma requisição do cliente é - enviada ao servidor (onde a camada de persistência do Hibernate roda), uma - Session 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 Session. - O relacionamento entre os dois é um-para-um e este modelo é um ajuste perfeito para muitas - aplicações. - - - - 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 ServletFilter, - 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 Transaction do Hibernate mostrada mais adiante neste - capítulo, para fácilidade no uso e portabilidade de código. - - - - Seu código de aplicação pode acessar a "sessão atual" para processar a requisição - fazendo uma chamada simples a sessionFactory.getCurrentSession() em - qualquer lugar e com a frequencia necessária. Você sempre conseguirá uma - Session limitada a transação atual. Isto tem que ser configurado - para recurso local ou os ambientes JTA. Veja . - - - - Às vezes é conveniente estender o escopo de uma Session 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 Open Session in View. - - - - - - - Longas conversações - - - 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: - - - - - - A primeira tela de um diálogo abre os dados carregado pelo usuário em através de - Session e transação particulares. O usuário está livre - modificar os objetos. - - - - - 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. - - - - - - Nós chamamos esta unidade de trabalho, do ponto da visão do usuário, executando uma - longa conversação (ou transação da aplicação). - Há muitas maneiras de você pode implementar em sua aplicação. - - - - - Uma primeira implementação simples pode manter aSession 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. - - - - 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: - - - - - - Versionamento automático - 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. - - - - - Detached Objects- se você se decidir usar o já discutido - pattern session-per-request, 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 - session-per-request-with-detached-objects. - É usado versionamento automatico para isolar as modificações concorrentes. - - - - - Extended (or Long) Session A Session - 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 - session-per-conversation e faz o reatamento uniforme - desnecessário. Versionamento automático é usado para isolar modificações - concorrentes e a session-per-conversation usualmente - não é permitido para ser nivelado automaticamente, e sim explicitamente. - - - - - - Ambos session-per-request-with-detached-objects e - session-per-conversation possuem vantagens e desvantagens, - nos discutiremos mais tarde neste capítulo no contexto do controle de - concorrência otimista. - - - - - - Considerando a identidade do objeto - - - Uma aplicação pode acessar concorrentemente o mesmo estado persistente em duas - Sessions diferentes. Entretanto, uma instância de uma classe - persistente nunca é compartilhada entre duas instâncias Session. - Por tanto, há duas noções diferentes da identidade: - - - - - Identidade da base de dados - - - foo.getId().equals( bar.getId() ) - - - - - Identidade da JVM - - - foo==bar - - - - - - - Então para os objetos acoplados a um Session em particular - (isto é no escopo de um Session), 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. - - - - - 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 Session. Dentro de uma Session a - aplicação pode usar com segurança o == para comparar objetos. - - - - Com tudo, uma aplicação que usa == fora de uma Session, - pode ver resultados inesperados. Isto pode ocorrer mesmo em alguns lugares inesperados, por - exemplo, se você colocar duas instâncias desacopladas em um mesmo Set. - 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 equals() e - hashCode() 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 - Set, mudar o hashcode quebra o contrato do Set. - 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. - - - - - - Edições comuns - - - Nunca use o anti-patterns session-per-user-session ou - session-per-application (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: - - - - - - Uma Session 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 Session for compartilhada. Se você mantiver - sua Session do Hibernate em seu HttpSession - (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 Session em duas threads executando concorrentemente. - - - - - 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 Session imediatamente - (discutido mais tarde em maiores detalhes). Se sua Session é - 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. - - - - - O Session 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 - clear() e evict() para controlar o cache - da Session, 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 . Manter uma Session aberta - durante uma sessão do usuário significa também uma probabilidade elevada de se acabar - com dados velhos. - - - - - - - - - - Demarcação de transações de bancos de dados - - - 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. - - - - 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. - - - - 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. - - - - Geralmente, finalizar um Sessionenvolve quatro fases distintas: - - - - - - flush da sessão - - - - - commitar a transação - - - - - fechar a sessão - - - - - tratar as exceções - - - - - - 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. - - - - - Ambiente não gerenciado - - - 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: - - - - - - Você não pode chamar flush() do Session() - explicitamente - a chamada ao commit() dispara automaticamente - a sincronização para a sessão (dependendo do - FlushMode). Uma chamada ao close() marca o fim de uma sessão. - A principal implicação do close() é 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. - - - - Uma solução muito mais flexível é gerência integrada de contexto da "sessão atual" - do Hibernate, como descrito anteriormente: - - - - - - 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 RuntimeException (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 SessionFactory. - A manipulação de exceção é discutida mais tarde neste capítulo. - - - - Note que você deve selecionar org.hibernate.transaction.JDBCTransactionFactory - (que é o padrão) e para o segundo exemplo "thread" como seu - hibernate.current_session_context_class. - - - - - - Usando JTA - - - 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. - - - - 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. - - - - - - Se você quiser usar um Session limitada por transação, isto é, - a funcionalidade do getCurrentSession() para a propagação fácil - do contexto, você terá que usar diretamente a API JTA UserTransaction: - - - - - - 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: - - - - - - Em um CMT/EJB mesmo um rollback acontece automaticamente, desde que uma exeção RuntimeException - não tratável seja lançada por um método de um session bean que informa ao contêiner ajustar a - transação global ao rollback. Isto significa que você não necessita usar a API - Transaction do Hibernate em tudo com BMT ou CMT e você obtém a propagação - automática do Session "atual" limitada à transação. - - - - Veja que você deverá escolher org.hibernate.transaction.JTATransactionFactory - se você usar o JTA diretamente (BMT) e org.hibernate.transaction.CMTTransactionFactory - em um CMT session bean, quando você configura a fábrica de transação do Hibernate. Lembre-se também de - configurar o hibernate.transaction.manager_lookup_class. Além disso, certifique-se - que seu hibernate.current_session_context_class ou não é configurado (compatibilidade - com o legado) ou é definido para "jta". - - - - - A operação getCurrentSession() tem um aspecto negativo em um ambiente JTA. - Há uma advertência para o uso do método liberado de conexão after_statement, - o qual é usado então por padrão. Devido a uma limitação simples da especificação JTA, não é - possível para o Hibernate automaticamente limpar quaisquer instâncias ScrollableResults - ou Iterator abertas retornadas pelo scroll() ou - iterate(). Você deve liberar o cursor subjacente da - base de dados chamando ScrollableResults.close() ou - Hibernate.close(Iterator) explicitamente de um bloco finally. - (Claro que a maioria de aplicações podem facilmente evitar o uso do scroll() ou - do iterate() em todo código provindo do JTA ou do CMT.) - - - - - - - Tratamento de Exceção - - - Se a Session levantar uma exceção (incluindo qualquer - SQLException), você deve imediatamente dar um rollback - na transação do banco, chamando Session.close() e descartando - a instância da Session. Certos métodos da Session - não deixarão a sessão em um estado inconsistente. Nenhuma exceção - lançada pelo Hibernate pode ser recuperada. Certifique-se que a Session - será fechada chamando close() no bloco finally. - - - - A exceção HibernateException, a qual envolve a maioria dos erros - que podem ocorrer em uma camada de persistência do Hibernate, é uma exceção unchecked ( - não estava em umas versões mais antigas de Hibernate). Em nossa opinião, nós não devemos - forçar o desenvolvedor a tratar uma exceção irrecuperável em uma camada mais baixa. - Na maioria dos sistemas, as exceções unchecked e fatais são tratadas em um dos primeiros - frames da pilha da chamada do método (isto é, em umas camadas mais elevadas) e uma mensagem - de erro é apresentada ao usuário da aplicação (ou a alguma outra ação apropriada é feita). - Note que Hibernate pode também lançar outras exceções unchecked que não são um - HibernateException. Estas, também são, irrecuperáveis e uma ação - apropriada deve ser tomada. - - - - O Hibernate envolve SQLExceptions lançadas ao interagir com a base de dados - em um JDBCException. Na realidade, o Hibernate tentará converter a exceção em - em uma sub classe mais significativa da JDBCException. A - SQLException subjacente está sempre disponível através de - JDBCException.getCause(). - - - - O Hibernate converte a SQLException em uma sub classe - JDBCException apropriada usando SQLExceptionConverter - associado ao SessionFactory. Por padrão, o SQLExceptionConverter é definido - pelo dialeto configurado; entretanto, é também possível conectar em uma implementação customizada - (veja o javadoc para mais detalhes da classe SQLExceptionConverterFactory). - Os subtipos padrão de JDBCException são: - - - - - - JDBCConnectionException - indica um erro com a comunicação subjacente de JDBC. - - - - - SQLGrammarException - indica um problema da gramática ou da sintaxe com o SQL emitido. - - - - - ConstraintViolationException - indica algum forma de violação de confinamento de integridade. - - - - - LockAcquisitionException - indica um erro ao adquirir um nível de bloqueio necessário para realizar a operação de requisição. - - - - - GenericJDBCException - uma exceção genérica que não cai em algumas das outras categorias. - - - - - - - - Timeout de Transação - - - Uma característica extremamente importante fornecida por um ambiente - gerenciado como EJB e que nunca é fornecido pelo código não gerenciado é o timeout - de transação. Timeouts de transação asseguram que nenhuma transação possa - reter indefinidamente recursos enquanto não retorna nenhuma resposta ao usuário. - Fora de um ambiente controlado (JTA), o Hibernate não pode fornecer inteiramente - esta funcionalidade. Entretanto, o Hibernate pode afinal controlar as operações - do acesso a dados, assegurando que o nível de deadlocks e queries do banco de - dados com imensos resultados definidos sejam limitados pelo timeout. Em um ambiente - gerenciado, o Hibernate pode delegar o timeout da transação ao JTA. Esta funcionalidade - é abstraída pelo objeto Transaction do Hibernate. - - - - - - Veja que setTimeout() não pode ser chamado em um CMT bean, - onde os timeouts das transações devem ser definidos declarativamente. - - - - - - - - Controle de concorrência otimista - - - O único caminho que é consistente com a elevada concorrência e escalabilidade - é controle de concorrência otimista com versionamento. Checagem de versão usa - número de versão, ou timestamps, para detectar conflitos de atualizações (e para - impedir atualizações perdidas). O Hibernate fornece três caminhos possíveis para - escrever aplicações que usam concorrência otimista. Os casos de uso que nós mostramos - estão no contexto de conversações longas, mas a checagem de versão também tem o - benefício de impedir atualizações perdidas em únicas transações. - - - - Checagem de versão da aplicação - - - Em uma implementação sem muita ajuda do Hibernate, cada interação com o banco de dados - ocorre em uma nova Session e o desenvolvedor é responsável para - recarregar todas as instâncias persistentes da base de dados antes de manipulá-las. - Este caminho força a aplicação a realizar sua própria checagem de versão para assegurar - a conversação do isolamento da transação. Este caminho é menos eficiente em termos de - acesso ao banco de dados. É a caminho mais similar a EJBs entity. - - - - - - A propriedade version é mapeada usando <version>, - e o Hibernate vai incrementá-lo-á automaticamente durante o flush se a entidade - estiver alterada. - - - - Claro, se você se estiver operando em um ambiente de baixa concorrência de dados - e não requerer a checagem de versão, você pode usar este caminho e apenas saltar a - checagem de versão. Nesse caso, o ultimo commit realizdo é - a estratégia padrão para suas conversações longas. Mantenha em mente que isto pode - confundir os usuários da aplicação, assim como eles podem experimentar atualizações - perdidas sem mensagens de erro ou uma possibilidade ajustar mudanças de conflito. - - - - - Claro que, checagem manual da versão é somente praticável em circunstâncias triviais - e não para a maioria de aplicações. Freqüentemente, os grafos completos de objetos - modificados têm que ser verificados, não somente únicas instâncias. O Hibernate oferece - checagem de versão automática com uma Session estendida ou instâncias - desatachadas como o paradigma do projeto. - - - - - - Sessão estendida e versionamento automático - - - Uma única instância de Session e suas instâncias persistentes - são usadas para a conversação inteira, isto é conhecido como - session-per-conversation. O Hibernate verifica versões da instância - no momento dio flush, lançando uma exceção se a modificação concorrente for detectada. - Até o desenvolvedor pegar e tratar essa exceção (as opções comuns são a oportunidade - para que o usuário intercale as mudanças ou reinicie a conversação do negócio com - dados não antigos). - - - - The Session is disconnected from any underlying JDBC connection - when waiting for user interaction. This approach is the most efficient in terms - of database access. The application need not concern itself with version checking or - with reattaching detached instances, nor does it have to reload instances in every - database transaction. - A Session é desconectada de toda a conexão JDBC subjacente - enquanto espera a interação do usuário. Este caminho é a mais eficiente em termos - de acesso a bancos de dados. A aplicação não necessita concernir-se com a checagem - de versão ou com as instâncias destacadas reatadas, nem tem que recarregar instâncias - em cada transação. - - - - - O objeto foo sabe que Session já foi carregada. Começando - uma nova transação em uma sessão velha obtém uma conexão nova e recomeça a sessão. Commitando - uma transação desconecta uma sessão da conexão JDBC e retorna a conexão ao pool. Após a reconexão, - forçar uma checagem de versão em dados que você não está atualizando, você pode chamar - Session.lock() com o LockMode.READ em todos os objetos - que possam ter sido atualizados por uma outra transação. Você não necessita bloquear nenhum - dado para atualizar. Geralmente você configuraria FlushMode.MANUAL em uma - Session estendida, de modo que somente o último ciclo da transação tenha - permissão de persistir todas as modificações feitas nesta conversação. Disso, somente esta última - transação incluiria a operação flush() e então chamar também close() - da sessão para terminar a conversação. - - - - Este pattern é problemático se a Session for demasiadamente grande para - ser armazenado durante o tempo que usuário pensar, por exemplo um HttpSession - estiver mantido tão pequeno quanto possível. Como o Session é também cache - de primeiro nível (imperativo) e contém todos os objetos carregados, nós podemos provavelmente - usar esta estratégia somente para alguns ciclos de requisição/resposta. Você deve usar a - Session somente para uma única conversação, porque ela logo também - estará com dados velhos. - - - - (Note que versões mais atuais de Hibernate requerem a desconexão e o reconexão explícitas de - uma Session. Estes métodos são desatualizados, como o início e término de - uma transação tem o mesmo efeito.) - - - - Note também que você deve manter a Session desconectada fechada - para a camada de persistência. Ou seja, use um EJB stateful session bean para - prender a Session em um ambiente do três camadas e não o - transferir à camada web (ou até serializá-lo para uma camada separada) - para armazená-lo no HttpSession. - - - - - O pattern sessão estendida, ou session-per-conversation, é mais - difícil de implementar com gerenciamento automático de sessão atual. Você precisa fornecer - sua própria implementação do CurrentSessionContext para isto - (veja o Hibernate Wiki para exemplos). - - - - - - Objetos destacados e versionamento automático - - - Cada interação com o armazenamento persistente ocorre em uma Session nova. - Entretanto, as mesmas instâncias persistentes são reusadas para cada interação com o banco de dados. - A aplicação manipula o estado das instâncias desatachadas originalmente carregadas em um outro - Session e reata-os então usando Session.update(), - Session.saveOrUpdate() ou Session.merge(). - - - - - - Outra vez, o Hibernate verificará versões da instância durante o flush, - lançando uma exceção se ocorrer conflitos de atualizações. - - - - Você pode também chamar o lock() em vez de update() - e usar LockMode.READ (executando uma checagem de versão, ignorando - todos os caches) se você estiver certo de que o objeto não foi modificado. - - - - - - Versionamento automático customizado - - - Você pode desabilitar o incremento da versão automática de Hibernate para propriedades - e coleções particulares configurando o mapeamento do atributo optimistic-lock - para false. O Hibernate então não irá incrementa versões se a propriedade estiver - modificada. - - - - Os esquemas da base de dados legada são freqüentemente estáticos e não podem ser modificados. - Ou outras aplicações puderam também acessar a mesma base de dados e não sabem tratar a - versão dos números ou timestamps. Em ambos os casos, o versionamento não pode confiar em uma - coluna particular em uma tabela. Para forçar uma checagem de versão sem uma versão ou mapeamento - da propriedade do timestamp com uma comparação do estado de todos os campos em uma linha, - configure optimistic-lock="all" no mapeamento <class>. - Note que isto conceitualmente é somente feito em trabalhos se Hibernate puder comparar o estado - velho e novo, isto é, se você usa um único Session longo e não - session-per-request-with-detached-objects. - - - - Às vezes a modificação concorrente pode ser permitida tão longa quanto às mudanças que - tiveram sido feitas que não sobrepuseram. Se você configurar optimistic-lock="dirty" - ao mapear o <class>, o Hibernate comparará somente campos - modificados durante o flush. - - - - Em ambos os casos, com as colunas dedicadas da versão/timestamp ou com comparação do - campo cheio/modificados, o Hibernate usa uma única declaração UPDATE (com uma cláusula - WHERE apropriada ) por entidade para executar a checagem da versão e atualizar a informação. - Se você usa a persistência transitiva para cascatear o reatamento das entidades associadas, - o Hibernate pode executar atualizações desnecessárias. Isso não é geralmente um problema, - mas triggers on update em um banco de dados podem ser executados - mesmo quando nenhuma mudança foi feita nas instâncias destacadas. Você pode customizar - este comportamento configurando select-before-update="true" no - mapeamento <class>, forçando o Hibernate a dá um SELECT nas - instâncias para assegurar-se esse as mudanças ocorreram realmente, antes de atualizar - a linha. - - - - - - - - Locking pessimista - - - Não se pretende que os usuários gastam muitas horas se preocupando com suas estratégias de - locking. Geralmente é o bastante para especificar um nível de isolamento para as conexões - JDBC e então deixar simplesmente o banco de dados fazer todo o trabalho. Entretanto, os - usuários avançados podem às vezes desejar obter locks pessimistas exclusivos, ou re-obter - locks no início de uma nova transação. - - - - O Hibernate usará sempre o mecanismo de lock da base de dados, nunca trava objetos - na memória! - - - - A classe LockMode define os diferentes níveis de lock que o Hibernate - pode adquirir. Um lock é obtido pelos seguintes mecanismos: - - - - - - - LockMode.WRITE é adquirido automaticamente quando o Hibernate atualiza - ou insere uma linha. - - - - - LockMode.UPGRADE pode ser adquirido explicitamente pelo usuário - usando SELECT ... FOR UPDATE em um banco de dados que suporte - esse sintaxe. - - - - - LockMode.UPGRADE_NOWAIT pode ser adquirido explicitamente pelo usuário - usando SELECT ... FOR UPDATE NOWAIT no Oracle. - - - - - - LockMode.READ é adquirido automaticamente quando o Hibernate lê - dados em um nível Repeatable Read ou Serializable isolation. Pode ser readquirido - explicitamente pelo usuário. - - - - - LockMode.NONE representa a ausência do lock. Todos os objetos mudam para - esse estado de lock no final da Transaction. Objetos associados com a sessão - através do método update() ou saveOrUpdate() também são - inicializados com esse lock mode. - - - - - - O lock obtido "explicitamente pelo usuário" se dá em uma das seguintes maneiras: - - - - - - Uma chamada a Session.load(), especificando - o LockMode. - - - - - Uma chamada a Session.lock(). - - - - - Uma chamada a Query.setLockMode(). - - - - - - Se uma Session.load() é invocada com UPGRADE ou - UPGRADE_NOWAIT, e o objeto requisitado ainda não foi carregado - pela sessão, o objeto é carregado usando SELECT ... FOR UPDATE. - Se load() for chamado para um objeto que já foi carregado - com um lock menos restritivo que o novo lock solicitado, o Hibernate invoca o - método lock() para aquele objeto. - - - - O método Session.lock() executa uma verificação no número da versão - se o modo de lock especificado for READ, UPGRADE ou - UPGRADE_NOWAIT.. (No caso do UPGRADE ou - UPGRADE_NOWAIT, é usado SELECT ... FOR UPDATE.) - - - - Se o banco de dados não suportar o lock mode solicitado, o Hibernate vai usar um modo - alternativo apropriado (ao invés de lançar uma exceção). Isso garante que a aplicação - vai ser portável. - - - - - - Modos de liberar a Connection - - - O comportamento legado do Hibernate (2.x) em consideração ao gerenciamento da conexão - via JDBC fez com que a Session precisasse obter uma conexão - quando ela precisasse pela primeira vez e depois manter a conexão enquanto - a sessão não fosse fechada. O Hibernate 3.x introduz a idéia de modos de liberar a - sessão, para informar a sessão a forma como deve manusear a sua conexão JDBC. - Veja que essa discussão só é pertinente para conexões fornecidas com um - ConnectionProvider configurado; conexões fornecidas pelo usuário - estão fora do escopo dessa discussão. Os diferentes modos de liberação estão definidos - pelos valores da enumeração - org.hibernate.ConnectionReleaseMode: - - - - - - - ON_CLOSE - essencialmente é o modo legado descrito acima. A sessão - do Hibernate obtêm a conexão quando precisar executar alguma operação JDBC pela - primeira vez e mantem enquanto a conexão não for fechada. - - - - - AFTER_TRANSACTION – informa que a conexão deve ser - liberada após a conclusão de uma org.hibernate.Transaction. - - - - - AFTER_STATEMENT (também conhecida com liberação agressiva) – informa - que a conexão deve ser liberada após a execução de cada statement. A liberação agressiva - não ocorre se o statement deixa pra trás algum recurso aberto associado com a sessão - obtida; atualmente, a única situação em que isso é possível é com o uso de - org.hibernate.ScrollableResults. - - - - - - O parâmetro de configuração hibernate.connection.release_mode é usado - para especificar qual modo de liberação deve ser usado. Opções disponíveis: - - - - - - auto (padrão) – essa opção delega ao modo de liberação retornado pelo - método org.hibernate.transaction.TransactionFactory.getDefaultReleaseMode(). - Para JTATransactionFactory, ele retorna ConnectionReleaseMode.AFTER_STATEMENT; para - JDBCTransactionFactory, ele retorna ConnectionReleaseMode.AFTER_TRANSACTION. - Raramente é uma boa idéia alterar padrão, como frequencia ao se fazer isso temos falhas - que parecem bugs e/ou suposições inválidas no código do usuário. - - - - - on_close - indica o uso da ConnectionReleaseMode.ON_CLOSE. Essa opção - foi deixada para manter a compatibilidade, mas seu uso é fortemente desencorajado. - - - - - after_transaction – indica o uso da ConnectionReleaseMode.AFTER_TRANSACTION. - Essa opção nada deve ser usada com ambientes JTA. Também note que no caso da - ConnectionReleaseMode.AFTER_TRANSACTION, se a sessão foi colocada no modo auto-commit a - conexão vai ser liberada de forma similar ao modo AFTER_STATEMENT. - - - - - after_statement – indica o uso ConnectionReleaseMode.AFTER_STATEMENT. - Adicionalmente, o ConnectionProvider configurado é consultado para - verificar se suporta essa configuração ((supportsAggressiveRelease()). - Se não suportar, o modo de liberação é redefinido como ConnectionRelease-Mode.AFTER_TRANSACTION. - Essa configuração só é segura em ambientes onde podemos readquirir a mesma conexão JDBC - toda vez que o método ConnectionProvider.getConnection() for chamado ou - em um ambiente auto-commit onde não importa se nós recuperamos a mesma conexão. - - - - - - - - + + Transações e Concorrência + + + 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. + + + + 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 Session, 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). + + + + 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 + SELECT FOR UPDATE. O controle de concorrência otimista e esta + API são discutidos mais tarde neste capítulo. + + + + Nós começamos a discussão do controle de concorrência no Hibernate com a granularidade + do Configuration, SessionFactory, e + Session, além de transações de base de dados e conversações longas. + + + + Session e escopos de transações + + + Um SessionFactory é 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 Configuration. + + + + Uma Session é 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 Session não obterá um + JDBC Connection (ou um Datasource) a menos que + necessite, conseqüentemente não consome nenhum recurso até ser usado. + + + + 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. + + + + Qual é o escopo de uma unidade de trabalho? Pode uma únicoa Session + do Hibernate gerenciar diversas transações ou é esta um o relacionamento um-para-um dos + escopos? Quando deve você abrir e fechar uma Session e como você + demarca os limites da transação? + + + + Unidade de trabalho + + + Primeiro, não use o antipattern sessão-por-operação, + isto é, não abra e não feche uma Session 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. + + + + O pattern mais comum em uma aplicação multi-usuário cliente/servidor é + sessão-por-requisição. Neste modelo, uma requisição do cliente é + enviada ao servidor (onde a camada de persistência do Hibernate roda), uma + Session 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 Session. + O relacionamento entre os dois é um-para-um e este modelo é um ajuste perfeito para muitas + aplicações. + + + + 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 ServletFilter, + 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 Transaction do Hibernate mostrada mais adiante neste + capítulo, para fácilidade no uso e portabilidade de código. + + + + Seu código de aplicação pode acessar a "sessão atual" para processar a requisição + fazendo uma chamada simples a sessionFactory.getCurrentSession() em + qualquer lugar e com a frequencia necessária. Você sempre conseguirá uma + Session limitada a transação atual. Isto tem que ser configurado + para recurso local ou os ambientes JTA. Veja . + + + + Às vezes é conveniente estender o escopo de uma Session 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 Open Session in View. + + + + + + + Longas conversações + + + 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: + + + + + + A primeira tela de um diálogo abre os dados carregado pelo usuário em através de + Session e transação particulares. O usuário está livre + modificar os objetos. + + + + + 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. + + + + + + Nós chamamos esta unidade de trabalho, do ponto da visão do usuário, executando uma + longa conversação (ou transação da aplicação). + Há muitas maneiras de você pode implementar em sua aplicação. + + + + + Uma primeira implementação simples pode manter aSession 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. + + + + 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: + + + + + + Versionamento automático - 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. + + + + + Detached Objects- se você se decidir usar o já discutido + pattern session-per-request, 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 + session-per-request-with-detached-objects. + É usado versionamento automatico para isolar as modificações concorrentes. + + + + + Extended (or Long) Session A Session + 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 + session-per-conversation e faz o reatamento uniforme + desnecessário. Versionamento automático é usado para isolar modificações + concorrentes e a session-per-conversation usualmente + não é permitido para ser nivelado automaticamente, e sim explicitamente. + + + + + + Ambos session-per-request-with-detached-objects e + session-per-conversation possuem vantagens e desvantagens, + nos discutiremos mais tarde neste capítulo no contexto do controle de + concorrência otimista. + + + + + + Considerando a identidade do objeto + + + Uma aplicação pode acessar concorrentemente o mesmo estado persistente em duas + Sessions diferentes. Entretanto, uma instância de uma classe + persistente nunca é compartilhada entre duas instâncias Session. + Por tanto, há duas noções diferentes da identidade: + + + + + Identidade da base de dados + + + foo.getId().equals( bar.getId() ) + + + + + Identidade da JVM + + + foo==bar + + + + + + + Então para os objetos acoplados a um Session em particular + (isto é no escopo de um Session), 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. + + + + + 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 Session. Dentro de uma Session a + aplicação pode usar com segurança o == para comparar objetos. + + + + Com tudo, uma aplicação que usa == fora de uma Session, + pode ver resultados inesperados. Isto pode ocorrer mesmo em alguns lugares inesperados, por + exemplo, se você colocar duas instâncias desacopladas em um mesmo Set. + 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 equals() e + hashCode() 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 + Set, mudar o hashcode quebra o contrato do Set. + 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. + + + + + + Edições comuns + + + Nunca use o anti-patterns session-per-user-session ou + session-per-application (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: + + + + + + Uma Session 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 Session for compartilhada. Se você mantiver + sua Session do Hibernate em seu HttpSession + (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 Session em duas threads executando concorrentemente. + + + + + 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 Session imediatamente + (discutido mais tarde em maiores detalhes). Se sua Session é + 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. + + + + + O Session 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 + clear() e evict() para controlar o cache + da Session, 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 . Manter uma Session aberta + durante uma sessão do usuário significa também uma probabilidade elevada de se acabar + com dados velhos. + + + + + + + + + + Demarcação de transações de bancos de dados + + + 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. + + + + 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. + + + + 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. + + + + Geralmente, finalizar um Sessionenvolve quatro fases distintas: + + + + + + flush da sessão + + + + + commitar a transação + + + + + fechar a sessão + + + + + tratar as exceções + + + + + + 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. + + + + + Ambiente não gerenciado + + + 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: + + + + + + Você não pode chamar flush() do Session() + explicitamente - a chamada ao commit() dispara automaticamente + a sincronização para a sessão (dependendo do + FlushMode). Uma chamada ao close() marca o fim de uma sessão. + A principal implicação do close() é 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. + + + + Uma solução muito mais flexível é gerência integrada de contexto da "sessão atual" + do Hibernate, como descrito anteriormente: + + + + + + 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 RuntimeException (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 SessionFactory. + A manipulação de exceção é discutida mais tarde neste capítulo. + + + + Note que você deve selecionar org.hibernate.transaction.JDBCTransactionFactory + (que é o padrão) e para o segundo exemplo "thread" como seu + hibernate.current_session_context_class. + + + + + + Usando JTA + + + 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. + + + + 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. + + + + + + Se você quiser usar um Session limitada por transação, isto é, + a funcionalidade do getCurrentSession() para a propagação fácil + do contexto, você terá que usar diretamente a API JTA UserTransaction: + + + + + + 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: + + + + + + Em um CMT/EJB mesmo um rollback acontece automaticamente, desde que uma exeção RuntimeException + não tratável seja lançada por um método de um session bean que informa ao contêiner ajustar a + transação global ao rollback. Isto significa que você não necessita usar a API + Transaction do Hibernate em tudo com BMT ou CMT e você obtém a propagação + automática do Session "atual" limitada à transação. + + + + Veja que você deverá escolher org.hibernate.transaction.JTATransactionFactory + se você usar o JTA diretamente (BMT) e org.hibernate.transaction.CMTTransactionFactory + em um CMT session bean, quando você configura a fábrica de transação do Hibernate. Lembre-se também de + configurar o hibernate.transaction.manager_lookup_class. Além disso, certifique-se + que seu hibernate.current_session_context_class ou não é configurado (compatibilidade + com o legado) ou é definido para "jta". + + + + + A operação getCurrentSession() tem um aspecto negativo em um ambiente JTA. + Há uma advertência para o uso do método liberado de conexão after_statement, + o qual é usado então por padrão. Devido a uma limitação simples da especificação JTA, não é + possível para o Hibernate automaticamente limpar quaisquer instâncias ScrollableResults + ou Iterator abertas retornadas pelo scroll() ou + iterate(). Você deve liberar o cursor subjacente da + base de dados chamando ScrollableResults.close() ou + Hibernate.close(Iterator) explicitamente de um bloco finally. + (Claro que a maioria de aplicações podem facilmente evitar o uso do scroll() ou + do iterate() em todo código provindo do JTA ou do CMT.) + + + + + + + Tratamento de Exceção + + + Se a Session levantar uma exceção (incluindo qualquer + SQLException), você deve imediatamente dar um rollback + na transação do banco, chamando Session.close() e descartando + a instância da Session. Certos métodos da Session + não deixarão a sessão em um estado inconsistente. Nenhuma exceção + lançada pelo Hibernate pode ser recuperada. Certifique-se que a Session + será fechada chamando close() no bloco finally. + + + + A exceção HibernateException, a qual envolve a maioria dos erros + que podem ocorrer em uma camada de persistência do Hibernate, é uma exceção unchecked ( + não estava em umas versões mais antigas de Hibernate). Em nossa opinião, nós não devemos + forçar o desenvolvedor a tratar uma exceção irrecuperável em uma camada mais baixa. + Na maioria dos sistemas, as exceções unchecked e fatais são tratadas em um dos primeiros + frames da pilha da chamada do método (isto é, em umas camadas mais elevadas) e uma mensagem + de erro é apresentada ao usuário da aplicação (ou a alguma outra ação apropriada é feita). + Note que Hibernate pode também lançar outras exceções unchecked que não são um + HibernateException. Estas, também são, irrecuperáveis e uma ação + apropriada deve ser tomada. + + + + O Hibernate envolve SQLExceptions lançadas ao interagir com a base de dados + em um JDBCException. Na realidade, o Hibernate tentará converter a exceção em + em uma sub classe mais significativa da JDBCException. A + SQLException subjacente está sempre disponível através de + JDBCException.getCause(). + + O Hibernate converte a SQLException em uma sub classe + JDBCException apropriada usando SQLExceptionConverter + associado ao SessionFactory. Por padrão, o SQLExceptionConverter é definido + pelo dialeto configurado; entretanto, é também possível conectar em uma implementação customizada + (veja o javadoc para mais detalhes da classe SQLExceptionConverterFactory). + Os subtipos padrão de JDBCException são: + + + + + + JDBCConnectionException - indica um erro com a comunicação subjacente de JDBC. + + + + + SQLGrammarException - indica um problema da gramática ou da sintaxe com o SQL emitido. + + + + + ConstraintViolationException - indica algum forma de violação de confinamento de integridade. + + + + + LockAcquisitionException - indica um erro ao adquirir um nível de bloqueio necessário para realizar a operação de requisição. + + + + + GenericJDBCException - uma exceção genérica que não cai em algumas das outras categorias. + + + + + + + + Timeout de Transação + + + Uma característica extremamente importante fornecida por um ambiente + gerenciado como EJB e que nunca é fornecido pelo código não gerenciado é o timeout + de transação. Timeouts de transação asseguram que nenhuma transação possa + reter indefinidamente recursos enquanto não retorna nenhuma resposta ao usuário. + Fora de um ambiente controlado (JTA), o Hibernate não pode fornecer inteiramente + esta funcionalidade. Entretanto, o Hibernate pode afinal controlar as operações + do acesso a dados, assegurando que o nível de deadlocks e queries do banco de + dados com imensos resultados definidos sejam limitados pelo timeout. Em um ambiente + gerenciado, o Hibernate pode delegar o timeout da transação ao JTA. Esta funcionalidade + é abstraída pelo objeto Transaction do Hibernate. + + + + + + Veja que setTimeout() não pode ser chamado em um CMT bean, + onde os timeouts das transações devem ser definidos declarativamente. + + + + + + + + Controle de concorrência otimista + + + O único caminho que é consistente com a elevada concorrência e escalabilidade + é controle de concorrência otimista com versionamento. Checagem de versão usa + número de versão, ou timestamps, para detectar conflitos de atualizações (e para + impedir atualizações perdidas). O Hibernate fornece três caminhos possíveis para + escrever aplicações que usam concorrência otimista. Os casos de uso que nós mostramos + estão no contexto de conversações longas, mas a checagem de versão também tem o + benefício de impedir atualizações perdidas em únicas transações. + + + + Checagem de versão da aplicação + + + Em uma implementação sem muita ajuda do Hibernate, cada interação com o banco de dados + ocorre em uma nova Session e o desenvolvedor é responsável para + recarregar todas as instâncias persistentes da base de dados antes de manipulá-las. + Este caminho força a aplicação a realizar sua própria checagem de versão para assegurar + a conversação do isolamento da transação. Este caminho é menos eficiente em termos de + acesso ao banco de dados. É a caminho mais similar a EJBs entity. + + + + + + A propriedade version é mapeada usando <version>, + e o Hibernate vai incrementá-lo-á automaticamente durante o flush se a entidade + estiver alterada. + + + + Claro, se você se estiver operando em um ambiente de baixa concorrência de dados + e não requerer a checagem de versão, você pode usar este caminho e apenas saltar a + checagem de versão. Nesse caso, o ultimo commit realizdo é + a estratégia padrão para suas conversações longas. Mantenha em mente que isto pode + confundir os usuários da aplicação, assim como eles podem experimentar atualizações + perdidas sem mensagens de erro ou uma possibilidade ajustar mudanças de conflito. + + + + + Claro que, checagem manual da versão é somente praticável em circunstâncias triviais + e não para a maioria de aplicações. Freqüentemente, os grafos completos de objetos + modificados têm que ser verificados, não somente únicas instâncias. O Hibernate oferece + checagem de versão automática com uma Session estendida ou instâncias + desatachadas como o paradigma do projeto. + + + + + + Sessão estendida e versionamento automático + + + Uma única instância de Session e suas instâncias persistentes + são usadas para a conversação inteira, isto é conhecido como + session-per-conversation. O Hibernate verifica versões da instância + no momento dio flush, lançando uma exceção se a modificação concorrente for detectada. + Até o desenvolvedor pegar e tratar essa exceção (as opções comuns são a oportunidade + para que o usuário intercale as mudanças ou reinicie a conversação do negócio com + dados não antigos). + + + + The Session is disconnected from any underlying JDBC connection + when waiting for user interaction. This approach is the most efficient in terms + of database access. The application need not concern itself with version checking or + with reattaching detached instances, nor does it have to reload instances in every + database transaction. + A Session é desconectada de toda a conexão JDBC subjacente + enquanto espera a interação do usuário. Este caminho é a mais eficiente em termos + de acesso a bancos de dados. A aplicação não necessita concernir-se com a checagem + de versão ou com as instâncias destacadas reatadas, nem tem que recarregar instâncias + em cada transação. + + + + + O objeto foo sabe que Session já foi carregada. Começando + uma nova transação em uma sessão velha obtém uma conexão nova e recomeça a sessão. Commitando + uma transação desconecta uma sessão da conexão JDBC e retorna a conexão ao pool. Após a reconexão, + forçar uma checagem de versão em dados que você não está atualizando, você pode chamar + Session.lock() com o LockMode.READ em todos os objetos + que possam ter sido atualizados por uma outra transação. Você não necessita bloquear nenhum + dado para atualizar. Geralmente você configuraria FlushMode.MANUAL em uma + Session estendida, de modo que somente o último ciclo da transação tenha + permissão de persistir todas as modificações feitas nesta conversação. Disso, somente esta última + transação incluiria a operação flush() e então chamar também close() + da sessão para terminar a conversação. + + + + Este pattern é problemático se a Session for demasiadamente grande para + ser armazenado durante o tempo que usuário pensar, por exemplo um HttpSession + estiver mantido tão pequeno quanto possível. Como o Session é também cache + de primeiro nível (imperativo) e contém todos os objetos carregados, nós podemos provavelmente + usar esta estratégia somente para alguns ciclos de requisição/resposta. Você deve usar a + Session somente para uma única conversação, porque ela logo também + estará com dados velhos. + + + + (Note que versões mais atuais de Hibernate requerem a desconexão e o reconexão explícitas de + uma Session. Estes métodos são desatualizados, como o início e término de + uma transação tem o mesmo efeito.) + + + + Note também que você deve manter a Session desconectada fechada + para a camada de persistência. Ou seja, use um EJB stateful session bean para + prender a Session em um ambiente do três camadas e não o + transferir à camada web (ou até serializá-lo para uma camada separada) + para armazená-lo no HttpSession. + + + + + O pattern sessão estendida, ou session-per-conversation, é mais + difícil de implementar com gerenciamento automático de sessão atual. Você precisa fornecer + sua própria implementação do CurrentSessionContext para isto + (veja o Hibernate Wiki para exemplos). + + + + + + Objetos destacados e versionamento automático + + + Cada interação com o armazenamento persistente ocorre em uma Session nova. + Entretanto, as mesmas instâncias persistentes são reusadas para cada interação com o banco de dados. + A aplicação manipula o estado das instâncias desatachadas originalmente carregadas em um outro + Session e reata-os então usando Session.update(), + Session.saveOrUpdate() ou Session.merge(). + + + + + + Outra vez, o Hibernate verificará versões da instância durante o flush, + lançando uma exceção se ocorrer conflitos de atualizações. + + + + Você pode também chamar o lock() em vez de update() + e usar LockMode.READ (executando uma checagem de versão, ignorando + todos os caches) se você estiver certo de que o objeto não foi modificado. + + + + + + Versionamento automático customizado + + + Você pode desabilitar o incremento da versão automática de Hibernate para propriedades + e coleções particulares configurando o mapeamento do atributo optimistic-lock + para false. O Hibernate então não irá incrementa versões se a propriedade estiver + modificada. + + + + Os esquemas da base de dados legada são freqüentemente estáticos e não podem ser modificados. + Ou outras aplicações puderam também acessar a mesma base de dados e não sabem tratar a + versão dos números ou timestamps. Em ambos os casos, o versionamento não pode confiar em uma + coluna particular em uma tabela. Para forçar uma checagem de versão sem uma versão ou mapeamento + da propriedade do timestamp com uma comparação do estado de todos os campos em uma linha, + configure optimistic-lock="all" no mapeamento <class>. + Note que isto conceitualmente é somente feito em trabalhos se Hibernate puder comparar o estado + velho e novo, isto é, se você usa um único Session longo e não + session-per-request-with-detached-objects. + + + + Às vezes a modificação concorrente pode ser permitida tão longa quanto às mudanças que + tiveram sido feitas que não sobrepuseram. Se você configurar optimistic-lock="dirty" + ao mapear o <class>, o Hibernate comparará somente campos + modificados durante o flush. + + + + Em ambos os casos, com as colunas dedicadas da versão/timestamp ou com comparação do + campo cheio/modificados, o Hibernate usa uma única declaração UPDATE (com uma cláusula + WHERE apropriada ) por entidade para executar a checagem da versão e atualizar a informação. + Se você usa a persistência transitiva para cascatear o reatamento das entidades associadas, + o Hibernate pode executar atualizações desnecessárias. Isso não é geralmente um problema, + mas triggers on update em um banco de dados podem ser executados + mesmo quando nenhuma mudança foi feita nas instâncias destacadas. Você pode customizar + este comportamento configurando select-before-update="true" no + mapeamento <class>, forçando o Hibernate a dá um SELECT nas + instâncias para assegurar-se esse as mudanças ocorreram realmente, antes de atualizar + a linha. + + + + + + + + Locking pessimista + + + Não se pretende que os usuários gastam muitas horas se preocupando com suas estratégias de + locking. Geralmente é o bastante para especificar um nível de isolamento para as conexões + JDBC e então deixar simplesmente o banco de dados fazer todo o trabalho. Entretanto, os + usuários avançados podem às vezes desejar obter locks pessimistas exclusivos, ou re-obter + locks no início de uma nova transação. + + + + O Hibernate usará sempre o mecanismo de lock da base de dados, nunca trava objetos + na memória! + + + + A classe LockMode define os diferentes níveis de lock que o Hibernate + pode adquirir. Um lock é obtido pelos seguintes mecanismos: + + + + + + + LockMode.WRITE é adquirido automaticamente quando o Hibernate atualiza + ou insere uma linha. + + + + + LockMode.UPGRADE pode ser adquirido explicitamente pelo usuário + usando SELECT ... FOR UPDATE em um banco de dados que suporte + esse sintaxe. + + + + + LockMode.UPGRADE_NOWAIT pode ser adquirido explicitamente pelo usuário + usando SELECT ... FOR UPDATE NOWAIT no Oracle. + + + + + + LockMode.READ é adquirido automaticamente quando o Hibernate lê + dados em um nível Repeatable Read ou Serializable isolation. Pode ser readquirido + explicitamente pelo usuário. + + + + + LockMode.NONE representa a ausência do lock. Todos os objetos mudam para + esse estado de lock no final da Transaction. Objetos associados com a sessão + através do método update() ou saveOrUpdate() também são + inicializados com esse lock mode. + + + + + + O lock obtido "explicitamente pelo usuário" se dá em uma das seguintes maneiras: + + + + + + Uma chamada a Session.load(), especificando + o LockMode. + + + + + Uma chamada a Session.lock(). + + + + + Uma chamada a Query.setLockMode(). + + + + + + Se uma Session.load() é invocada com UPGRADE ou + UPGRADE_NOWAIT, e o objeto requisitado ainda não foi carregado + pela sessão, o objeto é carregado usando SELECT ... FOR UPDATE. + Se load() for chamado para um objeto que já foi carregado + com um lock menos restritivo que o novo lock solicitado, o Hibernate invoca o + método lock() para aquele objeto. + + + + O método Session.lock() executa uma verificação no número da versão + se o modo de lock especificado for READ, UPGRADE ou + UPGRADE_NOWAIT.. (No caso do UPGRADE ou + UPGRADE_NOWAIT, é usado SELECT ... FOR UPDATE.) + + + + Se o banco de dados não suportar o lock mode solicitado, o Hibernate vai usar um modo + alternativo apropriado (ao invés de lançar uma exceção). Isso garante que a aplicação + vai ser portável. + + + + + + Modos de liberar a Connection + + + O comportamento legado do Hibernate (2.x) em consideração ao gerenciamento da conexão + via JDBC fez com que a Session precisasse obter uma conexão + quando ela precisasse pela primeira vez e depois manter a conexão enquanto + a sessão não fosse fechada. O Hibernate 3.x introduz a idéia de modos de liberar a + sessão, para informar a sessão a forma como deve manusear a sua conexão JDBC. + Veja que essa discussão só é pertinente para conexões fornecidas com um + ConnectionProvider configurado; conexões fornecidas pelo usuário + estão fora do escopo dessa discussão. Os diferentes modos de liberação estão definidos + pelos valores da enumeração + org.hibernate.ConnectionReleaseMode: + + + + + + + ON_CLOSE - essencialmente é o modo legado descrito acima. A sessão + do Hibernate obtêm a conexão quando precisar executar alguma operação JDBC pela + primeira vez e mantem enquanto a conexão não for fechada. + + + + + AFTER_TRANSACTION – informa que a conexão deve ser + liberada após a conclusão de uma org.hibernate.Transaction. + + + + + AFTER_STATEMENT (também conhecida com liberação agressiva) – informa + que a conexão deve ser liberada após a execução de cada statement. A liberação agressiva + não ocorre se o statement deixa pra trás algum recurso aberto associado com a sessão + obtida; atualmente, a única situação em que isso é possível é com o uso de + org.hibernate.ScrollableResults. + + + + + + O parâmetro de configuração hibernate.connection.release_mode é usado + para especificar qual modo de liberação deve ser usado. Opções disponíveis: + + + + + + auto (padrão) – essa opção delega ao modo de liberação retornado pelo + método org.hibernate.transaction.TransactionFactory.getDefaultReleaseMode(). + Para JTATransactionFactory, ele retorna ConnectionReleaseMode.AFTER_STATEMENT; para + JDBCTransactionFactory, ele retorna ConnectionReleaseMode.AFTER_TRANSACTION. + Raramente é uma boa idéia alterar padrão, como frequencia ao se fazer isso temos falhas + que parecem bugs e/ou suposições inválidas no código do usuário. + + + + + on_close - indica o uso da ConnectionReleaseMode.ON_CLOSE. Essa opção + foi deixada para manter a compatibilidade, mas seu uso é fortemente desencorajado. + + + + + after_transaction – indica o uso da ConnectionReleaseMode.AFTER_TRANSACTION. + Essa opção nada deve ser usada com ambientes JTA. Também note que no caso da + ConnectionReleaseMode.AFTER_TRANSACTION, se a sessão foi colocada no modo auto-commit a + conexão vai ser liberada de forma similar ao modo AFTER_STATEMENT. + + + + + after_statement – indica o uso ConnectionReleaseMode.AFTER_STATEMENT. + Adicionalmente, o ConnectionProvider configurado é consultado para + verificar se suporta essa configuração ((supportsAggressiveRelease()). + Se não suportar, o modo de liberação é redefinido como ConnectionRelease-Mode.AFTER_TRANSACTION. + Essa configuração só é segura em ambientes onde podemos readquirir a mesma conexão JDBC + toda vez que o método ConnectionProvider.getConnection() for chamado ou + em um ambiente auto-commit onde não importa se nós recuperamos a mesma conexão. + + + + + + + + diff --git a/documentation/manual/pt-BR/src/main/docbook/content/tutorial.xml b/documentation/manual/pt-BR/src/main/docbook/content/tutorial.xml index 91fca25a00..f2995b292f 100755 --- a/documentation/manual/pt-BR/src/main/docbook/content/tutorial.xml +++ b/documentation/manual/pt-BR/src/main/docbook/content/tutorial.xml @@ -1,1533 +1,1550 @@ - - Introdução ao Hibernate - - - Prefácio - - - Este capítulo é um tutorial introdutório para novos usuários do Hibernate. Nós iniciaremos com uma simples linha de comando em uma aplicação usando uma base de dados em memória tornando isto um passo de fácil de compreender. - - - - Este tutorial é voltado para novos usuários do Hibernate, mas requer um conhecimento de Java e SQL. Este tutorial é baseado no tutorial de Michael Gloegl, as bibliotecas Third Party foram nomeadas para JDK 1.4 e 5.0. Você pode precisar de outras bibliotecas para JDK 1.3. - - - - O código fonte para o tutorial está incluído no diretório da distribuição - doc/reference/tutorial/. - - - - - - Parte 1 – A primeira aplicação Hibernate - - - Primeiro, iremos criar uma simples aplicação Hibernate baseada em console. Usaremos uma base de dados Java (HSQL DB), então não teremos que instalar nenhum servidor de base de dados. - - - - Vamos supor que precisemos de uma aplicação com um banco de dados pequeno que possa armazenar e atender os eventos que queremos, e as informaççes sobre os hosts destes eventos. - - - - A primeira coisa que devemos fazer é configurar nosso diretório de desenvolvimento, - e colocar todas as bibliotecas Java que precisamos dentro dele. Faça o download da - distribuição do Hibernate no site do Hibernate. Descompacte o pacote e coloque todas - as bibliotecas necessárias encontradas no diretório /lib, dentro do - diretório /lib do seu novo projeto. Você deverá ter algo parecido - com isso: - - - - - - Esta é a configuração mínima requerida das bibliotecas (observe que também foi copiado - o hibernate3.jar da pasta principal do Hibernate) para o Hibernate na hora do desenvolvimento. O Hibernate permite que você utilize mais ou menos bibliotecas. - Veja o arquivo README.txt no diretório lib/ da distribuição - do Hibernate para maiores informaççes sobre bibliotecas requeridas e opcionais. - (Atualmente, a biblioteca Log4j não é requerida, mas é preferida por muitos desenvolvedores.) - - - - Agora, iremos criar uma classe que representa o evento que queremos armazenar na base de dados.. - - - - A primeira Classe - - - Nossa primeira classe de persistência é uma simples classe JavaBean com algumas propriedades: - - - - - - Você pode ver que esta classe usa o padrão JavaBean para o nomeamento convencional da propriedade getter e dos métodos setter, como também a visibilidade private dos campos. Este é um padrão de projeto recomendado, mas não requerido. O Hibernate pode também acessar campos diretamente, o benefício para os métodos de acesso é a robustez para o Refactoring. O construtor sem argumento é requerido para instanciar um objeto desta classe com a reflexão. - - - - A propriedade id mantém um único valor de identificação para um evento - particular. Todas as classes persistentes da entidade (bem como aquelas classes dependentes - de menos importância) precisam de uma propriedade de identificação, caso nós queiramos usar o - conjunto completo de características do Hibernate. De fato, a maioria das aplicações - (esp. aplicações web) precisam destinguir os objetos pelo identificador, então você deverá - considerar esta, uma característica em lugar de uma limitação. Porém, nós normalmente não - manipulamos a identidade de um objeto, consequentemente o método setter deverá ser privado. - O Hibernate somente nomeará os identificadores quando um objeto for salvo. Você pode ver como - o Hibernate pode acessar métodos públicos, privados, e protegidos, como também campos - (públicos, privados, protegidos) diretamente. A escolha está até você, e você pode combinar - isso para adaptar seu projeto de aplicação - - - - O construtor sem argumentos é um requerimento para todas as classes persistentes; - O Hibernate tem que criar para você os objetos usando Java Reflection. O construtor - pode ser privado, porém, a visibilidade do pacote é requerida para a procuração da - geração em tempo de execução e recuperação eficiente dos dados sem a instrumentação - de bytecode - - - - Coloque este fonte Java no diretório chamado src na pasta de desenvolvimento, - e em seu pacote correto. O diretório deverá ser parecido como este: - - - -+src - +events - Event.java]]> - - - No próximo passo, iremos falar sobre as classes de persistência do Hibernate.. - - - - - - O mapeamento do arquivo - - - O Hibernate precisa saber como carregar e armazenar objetos da classe de - persistência. Isto será onde o mapeamento do arquivo do Hibernate entrará em - jogo. O arquivo mapeado informa ao Hibernate, qual tabela no banco de dados - ele deverá acessar, e quais as colunas na tabela ele deverá usar. - - - - A estrutura básica de um arquivo de mapeamento é parecida com: - - - - - - -[...] -]]> - - - Note que o Hibernate DTD é muito sofisticado. Você pode usar isso para auto-conclusão - no mapeamento XML dos elementos e atributos no seu editor ou IDE. Você também pode - abrir o arquivo DTD no seu editor – é a maneira mais fácil de ter uma visão geral - de todos os elementos e atributos e dos padrões, como também alguns comentários. - Note que o Hibernate não irá carregar o arquivo DTD da web, e sim do diretório - da aplicação (classpath). O arquivo DTD está incluído no hibernate3.jar como - também no diretório src/ da distribuição do Hibernate. - - - - Nós omitiremos a declaração do DTD nos exemplos futuros para encurtar o código. Isto, é claro, não é opcional. - - - - Entre os dois tags hibernate-mapping, inclua um elemento class. - Todas as classes persistentes da entidade (novamente, poderá haver - mais tarde, dependências sobre as classes que não são classes-primárias - de entidades) necessitam do tal mapeamento, para uma tabela na base - de dados SQL - - - - - - - - -]]> - - - Mais adiante iremos dizer ao Hibernate como fazer para persistir e carregar objetos da classe - Event da tabela EVENTS, cada instancia representada por - uma coluna na tabela. Agora, continuaremos com o mapeamento de uma única propriedade identificadora - para as chaves primárias da tabela. Além disso, nós não iremos se importar com esta propriedade - identificadora, nós iremos configurar uma estratégia de geração de id’s para uma chave primária - de uma surrogate key: - - - - - - - - - - -]]> - - - O elemento id é a declaração da propriedade identificadora, - o name="id" declara o nome da propriedade Java – - o Hibernate irá usar os métodos getter e setter para acessar a propriedade. - O atributo da coluna informa ao Hibernate qual coluna da tabela EVENTS nós - iremos usar como chave primária. O elemento generator especifica - a estratégia de geração do identificador, neste caso usaremos native, que - escolhe a melhor estratégia dependendo da base de dados (dialeto) configurada. - O Hibernate suporta a base de dados gerada, globalmente única, bem como a atribuição - aos identificadores da aplicação (ou toda estratégia escrita para uma extensão). - - - - Finalmente incluiremos as declarações para as propriedades persistentes da classe - no arquivo mapeado. Por default, nenhuma das propriedades da classe é considerada persistente: - - - - - - - - - - - - -]]> - - - Da mesma maneira que com o elemento id, o atributo name do elemento - property informa ao Hibernate qual método getter e setter deverá usar. - Assim, neste caso, o Hibernate irá procurar pelo getDate()/setDate(), - como também pelo getTitle()/setTitle(). - - - - Porque fazer o mapeamento da propriedade date incluído no - atributo column, e no title não fazer? - Sem o atributo column o Hibernate por padrão usa o nome - da propriedade como o nome da coluna. Isto trabalha muito - bem para o title. Entretanto o date é uma palavra-chave reservada - na maioria dos bancos de dados, assim nós melhoramos o mapeamentos - disto com um nome diferente. - - - - A próxima coisa interessante é que mapemanto do title - também falta o atributo type. O tipo que declaramos e o uso nos - arquivos mapeados, não são como você pôde esperar, atributos de dados Java. - Eles não são como os tipos de base de dados SQL. - Esses tipos podem ser chamados de Tipos de mapeamento Hibernate, que são conversores - que podem traduzir tipos de dados do Java para os tipos de dados SQL e vice-versa. - Novamente, o Hibernate irá tentar determinar a conversão correta e mapeará o type - próprio, caso o tipo do atributo não estiver presente no mapeamento. - Em alguns casos, esta detecção automática (que usa Reflection sobre as classes Java) - poderá não ter padrão que você espera ou necessita. - Este é o caso com a propriedade date. O Hibernate não pode saber se a propriedade - (que é do java.util.Date) pode mapear para uma coluna do tipo date - do SQL, timestamp, ou time . - Nós preservamos a informação cheia de datas e horas pelo mapeamento da propriedade com um conversor - timestamp. - - - - Este arquivo de mapeamento deve ser salvo como Event.hbm.xml, - corretamente no diretório próximo ao arquivo fonte da Classe Java Event. - O nomeamento dos arquivos de mapeamento podem ser arbitrários, porém o sufixo - hbm.xml é uma convenção da comunidade dos desenvolvedores do Hibernate. - Esta estrutura do diretório deve agora se parecer com isso: - - - -+src - +events - Event.java - Event.hbm.xml]]> - - - Nós iremos continuar com a configuração principal do Hibernate. - - - - - - Configuração do Hibernate - - - Agora nós temos uma classe persistente e este arquivo de mapeamento no lugar. - Está na hora de configurar o Hibernate. Antes de fazermos isso, iremos precisar de uma base de dados. - O HSQL DB, um SQL DBMS feito em java, pode ser baixado através do site do HSQL DB(http://hsqldb.org/). - Atualmente, você só precisa baixar o hsqldb.jar. - Coloque este arquivo no diretório da pasta de desenvolvimento lib/. - - - - Crie um diretório chamado data no diretório root de desenvolvimento – - Isto será onde o HSQL DB irá armazenar arquivos de dados. Agora iremos iniciar o banco de dados - executando java -classpath ../lib/hsqldb.jar org.hsqldb.Server neste diretório de dados. - Você pode ver ele iniciando e conectando ao socket TCP/IP, isto será onde nossa aplicação irá se - conectar depois. Se você deseja iniciar uma nova base de dados durante este tutorial, - finalize o HSQL DB(pressionando o CTRL + C na janela), delete todos os - arquivos no diretório data/, e inicie o HSQL BD novamente. - - - - O Hibernate é uma camada na sua aplicação na qual se conecta com a base de dados, para isso - necessita de informação da conexão. As conexões são feitas através de um pool de conexão JDBC, - na qual teremos que configurar. A distribuição do Hibernate contém diversas ferramentas de pooling - da conexão JDBC de fonte aberta, mas iremos usar o pool de conexão interna para este tutorial. - Note que você tem que copiar a biblioteca necessária em seu classpath e use configurações - diferentes para pooling de conexão caso você deseje utilizar um software de pooling JDBC terceirizado - para qualidade de produção. - - - - Para as configurações do Hibernate, nós podemos usar um arquivo simples hibernate.properties, - um arquivo mais ligeiramente sofisticado hibernate.cfg.xml ou até mesmo uma - instalação programática completa. A maioria dos usuários preferem utilizar o arquivo de configuração XML - - - - - - - - - - - org.hsqldb.jdbcDriver - jdbc:hsqldb:hsql://localhost - sa - - - - 1 - - - org.hibernate.dialect.HSQLDialect - - - thread - - - org.hibernate.cache.NoCacheProvider - - - true - - - create - - - - - -]]> - - - Note que esta configuração XML usa um diferente DTD. Nós configuraremos - as SessionFactory do Hibernate – uma factory global responsável - por uma base de dedados particular. Se você tiver diversas bases de dados, - use diversas configurações <session-factory>, geralmente - em diversos arquivos de configuração (para uma partida mais fácil). - - - - As primeiras quatro propriedades do elemento contém a configuração - necessária para a conexão ao JDBC. A propriedade propriedade dialect - do elemento especifica a variante particular do SQL que o Hibernate gera. - O gerenciamento automático de sessão do Hibernate para contextos de persistência - estará disponível em breve. A opção hbm2ddl.auto habilita a geração - automática de schemas da base de dados – diretamente na base de dados. - Isto também pode ser naturalmente desligado (removendo a opção de configuração) ou redirecionando - para um arquivo com ajuda do SchemaExport nas tarefas do Ant. - Finalmente, iremos adicionar os arquivos das classes de persistência mapeadas na configuração. - - - - Copie este arquivo no diretório fonte, assim isto irá terminar na raiz (root) do - classpath. O Hibernate automaticamente procura por um arquivo chamado - hibernate.cfg.xml na raiz do classpath, no startup. - - - - - - Construindo com o Ant - - - Nos iremos, agora, construir o tutorial com Ant. Você ira precisar o Ant instalado – - se encontra disponível na página de download do Ant. - Como instalar o Ant, não será abordado aqui. Caso tenha alguma dúvida, por favor, - vá ao Ant manual. - Depois que tiver instalado o Ant, podemos começar a criar o arquivo de construção build.xml. - Este arquivo será chamado de build.xml e posto diretamente no diretório de desenvolvimento. - - - - Um arquivo básico de build, se parece com isto: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -]]> - - - Isto irá avisar ao Ant para adicionar todos os arquivos no diretório lib terminando com - .jar, para o classpath usado para compilação. Irá também copiar todos os - arquivos não-java para o diretório alvo (arquivos de configuração, mapeamento). Se você rodar - o ant agora, deverá ter esta saída. - - - ant -Buildfile: build.xml - -copy-resources: - [copy] Copying 2 files to C:\hibernateTutorial\bin - -compile: - [javac] Compiling 1 source file to C:\hibernateTutorial\bin - -BUILD SUCCESSFUL -Total time: 1 second ]]> - - - - - Startup and helpers - - - É hora de carregar e arquivar alguns objetos Event, mas primeiro - nós temos de completar o setup com algum código de infraestrutura. Este startup - inclui a construção de um objeto SessionFactory global e armazenar - isto em algum lugar de fácil acesso para o código da aplicação. - Uma SessionFactory pode abrir novas Session's. - Uma Session representa uma unidade single-theaded do trabalho, a - SessionFactory é um objeto global thread-safe, instanciado uma vez. - - - - Nos iremos criar uma classe de ajuda HibernateUtil, que toma - conta do startup e faz acesso a uma SessionFactory conveniente. - Vamos dar uma olhada na implementação: - - - - - - Esta classe não só produz a global SessionFactory no seu static initializer - (chamado uma vez pela JVM quando a classe é carregada), mas também esconde o fato - de que isto usa um static singleton. Ela pode muito bem, enxergar a - SessionFactory do JNDI em um application server. - - - - Se você der à SessionFactory um nome, no seu arquivo de configuração. - O Hibernate irá, de fato, tentar uni-lo ao JNDI depois que estiver construído. - Para evitar este completamente este código, você também poderia usar JMX deployment - e deixar o contêiner JMX capaz, instanciar e unir um HibernateService - no JNDI. Essas opções avançadas são discutidas no documento de referência do Hibernate. - - - - Coloque o HibernateUtil.java no diretório de arquivos - de desenvolvimento(source), em um pacote após o events: - - - -+src - +events - Event.java - Event.hbm.xml - +util - HibernateUtil.java - hibernate.cfg.xml -+data -build.xml]]> - - - Novamente, isto deve compilar sem problemas. Finalmente, nós precisamos configurar - um sistema de logging – o Hibernate usa commons logging e deixa você escolher entre o - Log4j e o logging do JDK 1.4 . A maioria dos desenvolvedores preferem o Log4j: copie - log4j.properties da distribuição do Hibernate (está no diretório - etc/), para seu diretório src, - depois vá em hibernate.cfg.xml. Dê uma olhada no exemplo de configuração e mude as - configurações se você quizer ter uma saída mais detalhada. Por default, apenas as - mensagems de startup e shwwn do Hibernate é mostrada no stdout. - - - - O tutorial de infra-estrutura está completo - e nós já estamos preparados para algum - trabalho de verdade com o Hibernate. - - - - - - Carregando e salvando objetos - - - Finalmente, nós podemos usar o Hibernate para carregar e armazenar objetos. - Nós escrevemos uma classe EventManager com um método main(): - - - - - - Nós criamos um novo objeto Event, e passamos para o Hibernate. - O Hibernate sabe como tomar conta do SQL e executa INSERTs - no banco de dados. Vamos dar uma olhada na Session e no - código Transaction-handling antes de executarmos. - - - - Um Session é uma unidade simples de trabalho. Por agora nós - iremos pegar coisas simples e assumir uma granularidade de um-pra-um entre uma - Session do Hibernate e uma transação de banco de dados. - Para proteger nosso código de um atual sistema subjacente de transação (nesse - caso puro JDBC, mas também poderia rodar com JTA), nos usamos a API - Transaction, que está disponível na Session do Hibernate. - - - - O que a sessionFactory.getCurrentSession() faz? Primeiro, você pode - chamar quantas vezes e de onde quiser, uma vez você recebe sua SessionFactory - (fácil graças ao HibernateUtil). O método getCurrentSession() - sempre retorna a unidade de trabalho "corrente". Lembra de que nós mudamos a opção - de configuração desse mecanismo para thread no hibernate.cfg.xml? Daqui em - diante, o escopo da unidade de trabalho corrente é a thread Java - corrente que executa nossa aplicação. Entretanto, esta não é toda a verdade. Uma - Session começa quando é primeiramente necessária, quando é feita a - primeira chamada à getCurrentSession(). É então limitado pelo Hibernate - para thread corrente. Quando a transação termina, tanto com commit quanto rollback, - o Hibernate também desune a Session da thread e fecha isso pra você. - Se você chamar getCurrentSession() novamente, você receberá uma nova - Session e pode começar uma nova unidade de trabalho. Esse modelo de - programação de limite de thread thread-bound, é o modo mais popular - de se usar o Hibernate. - - - - Dê uma olhada no para mais informações a - respeito de manipulação de transação e demarcação. Nós também pulamos qualquer - manipulação de erro e rollback no exemplo anterior. - - - - Para executar esta primeira rotina, nos teremos que adicionar um ponto de chamada - para o arquivo de build do Ant: - - - - - - - -]]> - - - O valor do argumento action, é setado na linha de comando quando chamando esse ponto: - - - ant run -Daction=store]]> - - - Você deverá ver, após a compilação, o startup do Hibernate e, dependendo da sua - configuração, muito log de saída. No final você verá a seguinte linha: - - - - - - Este é o INSERT executado pelo Hibernate, os pontos de interrogação - representam parêmetros de união do JDBC. Para ver os valores substituídos, ou para diminuir a - verbalidade do log, check seu llog4j.properties. - - - - Agora nós gostaríamos de listar os eventos arquivados, então nós adicionamos uma - opção para o método main: - - - - - - Nos também adicionamos um novo método listEvents(): - - - - - - O que nós fazemos aqui, é usar uma query HQL (Hibernate Query Language), - para carregar todos os objetos Event exitentes no banco de dados. - O Hibernate irá gerar o SQL apropriado, enviar para o banco de dados e popular objetos - Event com os dados. Você pode criar queries mais complexas com - HQL, claro. - - - - Agora, para executar e testar tudo isso, siga os passos a seguir: - - - - - - Execute ant run -Daction=store para armazenar algo no banco de dados - e, claro, gerar o esquema do banco de dados antes pelo hbm2ddl. - - - - - Agora desabilite hbm2ddl comentando a propriedade no seu arquivo hibernate.cfg.xml. - Normalmente só se deixa habilitado em teste unitários contínuos, mas outra carga de hbm2ddl - pode remover tudo que você já tenha arquivado. Sa configuração - create, atualmente são traduzidas para "apague todas as tabelas do esquema, - então recrie todas quando a SessionFactory estiver pronta". - - - - - - Se você agora chamar o Ant com -Daction=list, você deverá ver os - eventos que você acabou de criar. Você pode também chamar a ação store - mais algumas vezes. - - - - Nota: A maioria dos novos usuários do Hibernate falha nesse ponto e nós regularmente, vemos - questões sobre mensagens de erro de tabela não encontrada . - Entretanto, se você seguir os passos marcados acima, você não terá esse problema, - com o hbm2ddl criando o esquema do banco de dados na primeira execução, e restarts - subsequentes da aplicação irão usar este esquema. Se você mudar o mapeamento e/ou - o esquema do banco de dados, terá de re-habilitar o hbm2ddl mais uma vez. - - - - - - - - Part 2 - Mapeando associações - - - Nós mapeamos uma classe de entidade de persistência para uma tabela. Agora vamos continuar - e adicionar algumas associações de classe. Primeiro nos iremos adicionar pessoas a nossa aplicação, - e armazenar os eventos de que elas participam. - - - - Mapeando a classe Person - - - O primeiro código da classe Person é simples: - - - - - - Crie um novo arquivo de mapeamento, chamado Person.hbm.xml (não - esqueça a referencia ao DTD no topo) - - - - - - - - - - - - - -]]> - - - Finalmente, adicione o novo mapeamento a configuração do Hibernate: - - - -]]> - - - Nos iremos agora criar uma associação entre estas duas entidades. Obviamente, - pessoas (Person) podem participar de eventos, e eventos possuem participantes. - As questões de design com que teremos de lidar são: direcionalidade, multiplicidade e - comportamento de coleção. - - - - - - Uma associação Set-based unidirectional - - - Nos iremos adicionar uma coleção de eventos na classe Person. Desse jeito - poderemos navegar pelos eventos de uma pessoa em particular, sem executar uma query explicitamente – - apenas chamando aPerson.getEvents(). Nos usaremos uma coleção Java, um - Set, porquê a coleção não conterá elementos duplicados e a ordem não é - relevante para nós. - - - - Vamos escrever o código para isto nas classes Java e então mapear: - - - - - - Antes de mapearmos esta associação, pense no outro lado. Claramente, poderíamos apenas fazer isto de - forma unidirecional. Ou poderíamos criar outra coleção no Event, se quisermos - ser capaz de navegar bidirecionalmente, i.e. um - anEvent.getParticipants(). - Isto não é necessário, de perspectiva funcional. Você poderia sempre executar uma query explicita - que retornasse os participantes de um evento em particular. Esta é uma escolha de design que cabe - a você, mas o que é claro nessa discussão é a multiplicidade da associação: "muitos" valores em ambos - os lados, nós chamamos isto uma associação muitos-para-muitos. Daqui pra frente, - nos usaremos o mapeamento muitos-para-muitos do Hibernate: - - - - - - - - - - - - - - - -]]> - - - O Hibernate suporta todo tipo de mapeamento de coleção , sendo um <set> mais comum. - Para uma associação muitos-para-muitos (ou relacionamento de entidade n:m ), - uma tabela de associação é necessária. Cada linha nessa tabela representa um link entre uma pessoa e um - evento. O nome da tabela é configurado com o atributo table do elemento - set. O nome da coluna identificadora na associção, peloo lado da pessoa, - é definido com o elemento <key> , o nome da coluna pelo lado dos eventos, - e definido com o atributo column do <many-to-many>. - Você também precisa dizer para o Hibernate a classe dos objetos na sua coleção (a classe do outro - lado das coleções de referência). - - - - O esquema de mapeamento para o banco de dados está a seguir: - - - | *EVENT_ID | | | - | EVENT_DATE | | *PERSON_ID | <--> | *PERSON_ID | - | TITLE | |__________________| | AGE | - |_____________| | FIRSTNAME | - | LASTNAME | - |_____________| - ]]> - - - - - Trabalhando a associação - - - Vamos trazer juntos algumas pessoas e eventos em um novo método na classe EventManager:: - - - - - - Após carregar um Person e um Event, simplesmente - modifique a coleção usando os métodos normais de uma coleção. Como você pode ver, não há chamada explícita - para update() ou save(), o Hibernate detecta automaticamente - que a coleção foi modificada e necessita ser atualizada. Isso é chamado de checagem - suja automática, e você também pode usá-la modificando o nome ou a data de qualquer um dos - seus objetos. Assim que eles estiverem no estado persistent, ou seja, - limitado por uma Session do Hibernate em particular (i.e. eles foram carregados ou - salvos dentro de uma unidade de trabalho), o Hibernate monitora qualquer alteração e executa o SQL - em modo de escrita em segundo plano. O processo de sincronização do estado da memória com o banco de - dados, geralmente apenas no final de uma unidade de trabalho, é chamado de flushing. - No nosso código, a unidade de trabalho termina com o commit da transação do banco de dados – - como definido pela opção de configuração da thread da classe CurrentSessionContext. - - - - Você pode também querer carregar pessoas e eventos em diferentes unidades de trabalho. - Ou você modifica um objeto fora de uma Session, quando não se encontra no - estado persistent (se já esteve neste estado anteriormente, chamamos esse estado de - detached). Você pode até mesmo modificar uma coleção quando esta - se encontrar no estado detached. - - - - - - A chamada update cria um objeto persistent novamente, você poderia - dizer que ele liga o objeto a uma nova unidade de trabalho, assim qualquer modificação - que você faça neste objeto enquanto estiver no estado detached pode ser salvo no banco de dados. - Isso inclui qualquer modificação (adição/exclusão) que você faça em uma coleção da entidade deste objeto. - - - - Bom, isso não foi muito usado na nossa situação, porém, é um importante conceito que você - pode aplicar em seus aplicativos. Agora, complete este exercício adicionando uma nova ação - ao método main( ) da classe EventManager e chame-o pela linha de comando. - Se você precisar dos identificadores de uma pessoa ou evento – o método save() - retorna estes identificadores (você poderá modificar alguns dos métodos anteriores para retornar aquele - identificador): - - - - - - Este foi um exemplo de uma associação entre duas classes igualmente importantes, duas entidades. - Como mencionado anteriormente, há outras classes e tipos dentro de um modelo típico, - geralmente "menos importante". Alguns você já viu, como um int ou uma String. - Nós chamamos essas classes de value types, e suas instâncias depend - de uma entidade particular. As instâncias desses tipos não possuem sua própria identidade, nem são - compartilhados entre entidades (duas pessoas não referenciam o mesmo objeto firstname - mesmo se elas tiverem o mesmo objeto firstname). Naturalmente, os value types não são apenas encontrados - dentro da JDK (de fato, em um aplicativo Hibernate todas as classes JDK são consideradas como value types), - mas você pode também criar suas classes como, por exemplo, Address ou MonetaryAmount. - - - - - Você também pode criar uma coleção de value types. Isso é conceitualmente muito diferente - de uma coleção de referências para outras entidades, mas em Java parece ser quase a mesma coisa. - - - - - - Coleção de valores - - - Nós adicionamos uma coleção de objetos de tipo de valores à entidade Person. - Nós querermos armazenar endereços de e-mail, para isso utilizamos o tipo String, - e a coleção novamente será um Set: - - - - - O mapeamento deste Set: - - - - - -]]> - - - A diferença comparada com o mapeamento anterior se encontra na parte element, - que indica ao Hibernate que a coleção não contém referências à outra entidade, mas uma coleção de - elementos do tipo String (a tag name em miniscula indica que se trata de um - mapeamento do Hibernate para conversão de tipos). Mais uma vez, o atributo table - do elemento set determina o nome da tabela para a coleção. O elemento - key define o nome da coluna de chave estrangeira na tabela de coleção. - O atributo column dentro do elemento element define o - nome da coluna onde os valores da String serão armazenados. - - - - Dê uma olhada no esquema atualizado: - - - | *EVENT_ID | | | |___________________| - | EVENT_DATE | | *PERSON_ID | <--> | *PERSON_ID | <--> | *PERSON_ID | - | TITLE | |__________________| | AGE | | *EMAIL_ADDR | - |_____________| | FIRSTNAME | |___________________| - | LASTNAME | - |_____________| - ]]> - - - Você pode observar que a chave primária da tabela da coleção é de na verdade uma chave composta, - usando ambas colunas. Isso também implica que cada pessoa não pode ter endereços de e-mail - duplicados, o que é exatamente a semântica que precisamos para um set em Java. - - - - Você pode agora tentar adicionar elementos a essa coleção, do mesmo modo que fizemos - anteriormente ligando pessoas e eventos. È o mesmo código em Java: - - - - - - This time we didnt' use a fetch query to initialize the collection. - Hence, the call to its getter method will trigger an additional select to initialize - it, so we can add an element to it. Monitor the SQL log and try to optimize this with - an eager fetch. - - - - - - Associações bidirecionais - - - Agora iremos mapear uma associação bidirecional – fazendo a associação entre pessoas e - eventos, de ambos os lados, em Java. Logicamente, o esquema do banco de dados não muda, - nós continuamos tendo multiplicidades muitos-para-muitos. Um banco de dados é mais flexível do que - uma linguagem de programação para redes, ele não precisa de nenhuma direção de navegação – os - dados podem ser acessados em qualquer caminho possível. - - - - Primeiramente, adicione uma coleção de participantes à classe Event: - - - - - - Agora mapeie este lado da associação em Event.hbm.xml. - - - - - -]]> - - - Como você pode ver, esses é uma mapeamento normal usando set em ambos documenentos - de mapeamento. Observe que o nome das colunas em key e many-to-many - estão trocados em ambos os documentos de mapeamento. A adição mais importante feita está no atributo - inverse="true" no elemento set do mapeamento da coleção da classe Event. - - - - Isso significa que o Hibernate deve pegar o outro lado – a classe Person – - quando necessitar encontrar informação sobre a relação entre as duas entidades. Isso será muito - mais facilmente compreendido quando você analisar como a relação bidirecional entre as entidades é criada. - - - - - - Trabalhando com links bidirecionais - - - Primeiro tenha em mente que o Hibernate não afeta a semântica normal do Java. Como nós criamos - um link entre uma Person e um Event no exemplo unidirecional? - Nós adicionamos uma instância de Event, da coleção de referências de eventos, - a uma instância de Person. Então, obviamente, se nós queremos que este link funcione - bidirecionalmente, nós devemos fazer a mesma coisa para o outro lado – adicionando uma referência de - Person na coleção de um Event. Esse acerto de link de ambos - os lados é absolutamente necessário e você nunca deve esquecer de faze-lo. - - - - Muitos desenvolvedores programam de maneira defensiva e criam métodos - gerenciador de associações que ajusta corretamente ambos os lados: - - - - - - Observe que os métodos set e get da a coleção estão protegidos – isso permite que classes e - subclasses do mesmo pacote continuem acessando os métodos, mas previne que qualquer outra classe, - que não esteja no mesmo pacote, acesse a coleção diretamente. Você provavelmente deve fazer a mesma - coisa para a coleção do outro lado. - - - - E sobre o mapeamento do atributo inverse? Pra você, e para o Java, um link bidirecional - é simplesmente o fato de ajustar corretamente as referências de ambos os lados. O Hibernate, entretanto - não possui informação necessária para corretamente adaptar os estados INSERT e - UPDATE do SQL, e precisa de ajuda para manipular as propriedades das associações - bidirecionais. Fazer um lado da associação com o atributo inverse instrui o Hibernate - para basicamente ignora-lo, considerando-o uma cópia do outro lado. Isso é todo o - necessário para o Hibernate trabalhar com todas as possibilidades quando transformando um modelo de - navegação bidirecional em esquema de banco de dados do SQL. As regras que você possui para lembrar são - diretas: Todas associações bidirecionais necessitam que um lado possua o atributo inverse. Em uma - associação de um-para-muitos, o lado de "muitos" deve conter o atributo inverse, - já em uma associação de muitos-para-muitos você pode pegar qualquer lado, não há diferença. - - - - - - Agora, vamos portar este exemplo para um pequeno aplicativo para internet. - - - - - - - EventManager um aplicativo para internet - - - Um aplicativo para internet do Hibernate usa uma Session e uma Transaction - quase do mesmo modo que um aplicativo standalone. Entretanto, alguns patterns comuns são úteis. - Nós agora criaremos um EventManagerServlet. Esse servlet lista todos os eventos - salvos no banco de dados, e cria um formulário HTML para entrada de novos eventos. - - - - Criando um servlet básico - - - Crie uma nova classe no seu diretório fonte, no pacote events: - - - - - - O servlet manuseia somente requisições GET do HTTP, - portanto o método que iremos implementar é doGet(): - - - - - - O pattern que estamos aplicando neste código é chamado session-per-request. - Quando uma requisição chega ao servlet, uma nova Session do Hibernate é - aberta através da primeira chamada para getCurrentSession() em - SessionFactory. Então uma transação do banco de dados é inicializada - - todo acesso a dados deve ocorrer dentro de uma transação, não importando se o dado é de leitura ou escrita. - (nós não devemos usar o modo auto-commit em aplicações). - - - - - Agora, as possibilidades de ações de uma requisição serão processadas e uma resposta HTML será renderizada. - Nós já iremos chegar nesta parte. - - - - Finalmente, a unidade de trabalho termina quando o processamento e a restituição são completados. - Se ocorrer algum erro durante o processamento ou a restituição, uma exceção será lançada e a - transação do banco de dados encerrada. Isso completa o pattern session-per-request. - Em vez de usar código de demarcação de transação em todo servlet você pode também criar um filtro servlet. - Dê uma olhada no site do Hibernate e do Wiki para maiores informações sobre esse pattern, - chamado Open Session in View. - - - - - - Processando e renderizando - - - Vamos implementar o processamento da requisição e a restituição da página HTML. - - -Event Manager"); - -// Handle actions -if ( "store".equals(request.getParameter("action")) ) { - - String eventTitle = request.getParameter("eventTitle"); - String eventDate = request.getParameter("eventDate"); - - if ( "".equals(eventTitle) || "".equals(eventDate) ) { - out.println("Please enter event title and date."); - } else { - createAndStoreEvent(eventTitle, dateFormatter.parse(eventDate)); - out.println("Added event."); - } -} - -// Print page -printEventForm(out); -listEvents(out, dateFormatter); - -// Write HTML footer -out.println(""); -out.flush(); -out.close();]]> - - - O estilo de código acima, misturando linguagem HTML e Java não será funcional em um aplicativo - mais complexo—tenha em mente que neste manual nós estamos apenas ilustrando conceitos - básicos do Hibernate. O código imprime um cabeçalho HTML e um rodapé. Dentro desta página, - é mostrado um formulário em HTML, para entrada de novos eventos, e uma lista de todos - os eventos contidos no banco de dados. O primeiro método é trivial e apenas imprime - uma página HTML: - - - Add new event:"); - out.println("
"); - out.println("Title:
"); - out.println("Date (e.g. 24.12.2009):
"); - out.println(""); - out.println("
"); -}]]>
- - - O método listEvents() usa a Session do Hibernate - associada a thread atual para executar um query: - - - 0) { - out.println("

Events in database:

"); - out.println(""); - out.println(""); - out.println(""); - out.println(""); - out.println(""); - for (Iterator it = result.iterator(); it.hasNext();) { - Event event = (Event) it.next(); - out.println(""); - out.println(""); - out.println(""); - out.println(""); - } - out.println("
Event titleEvent date
" + event.getTitle() + "" + dateFormatter.format(event.getDate()) + "
"); - } -}]]>
- - - Finalmente, a action store é passada pra o método - createAndStoreEvent(), que também usa a - Session da thread atual: - - - - - - Pronto, o servlet está completo. Uma requisição para o servlet será processada - em uma Session e uma Transaction simples. - Como anteriormente, no aplicativo standalone, o Hibernate pode automaticamente - associar esses objetos a thread atual em execução. Isso possibilita a liberdade - de você modelar seu código e acessar o método SessionFactory - do jeito que achar melhor. Geralmente você irá usar um design mais sofisticado - e mover o código de acesso a dados para dentro de objetos de acesso a dados - (o patter DAO). Leia o Hibernate Wiki para maiores exemplos. - - -
- - - Instalando e testando - - - Para fazer o deploy desta aplicação você tem que criar um arquivo para web, um WAR. - Adicione o alvo Ant abaixo em seu build.xml: - - - - - - - - - - -]]> - - - Esta target cria um arquivo chamado hibernate-tutorial.war - no diretório do seu projeto. Ele empacota todas as bibliotecas e o arquivo de - descrição web.xml, o qual é esperado no diretório base do seu projeto: - - - - - - - Event Manager - events.EventManagerServlet - - - - Event Manager - /eventmanager - -]]> - - - Antes de você compilar e fazer o deploy desta aplicação web, note que uma biblioteca - adicional é requerida: jsdk.jar. Esse é o Java servlet development kit, - se você não possui esta biblioteca, faça seu download na página da Sun e copie-a - para seu diretório de bibliotecas. Entretanto, será usado somente para a compilação e - excluído do pacote WAR. - - - - Para compilar e instalar execute ant war no seu diretório do projeto - e copie o arquivo hibernate-tutorial.war para o diretório - webapp do Tomcat. Se você não possui o Tomcat instalado faça - o download e siga as instruções de instalação. Você não precisa modificar - nenhuma configuração do Tomcat para rodar este aplicativo. - - - - Uma vez feito o deploy e com Tomcat rodando, acesse o aplicativo em - http://localhost:8080/hibernate-tutorial/eventmanager. - Veja o log do Tomcat para observar a inicialização do Hibernate quando a - primeira requisição chega ao servlet (o inicializador estático dentro de - HibernateUtil é chamado) e para ter uma depuração - detalhada se ocorrer alguma exceção. - - - - -
- - - Sumário - - - Este manual cobriu os princípios básicos para criação de uma aplicação simples do Hibernate - e uma pequena aplicação web. - - - - Se você já se sente seguro com o Hibernate, continue navegando na documentação de referência - por tópicos que você acha interessante – os tópicos mais questionados são: - processo de transação (), uso da API () - e características de consulta (). - - - - Não esqueça de visitar o site do Hibernate para obter mais tutoriais especializados. - - - - -
+ + Introdução ao Hibernate + + + Prefácio + + + Este capítulo é um tutorial introdutório para novos usuários do Hibernate. Nós iniciaremos com uma simples linha de comando em uma aplicação usando uma base de dados em memória tornando isto um passo de fácil de compreender. + + + + Este tutorial é voltado para novos usuários do Hibernate, mas requer um conhecimento de Java e SQL. Este tutorial é baseado no tutorial de Michael Gloegl, as bibliotecas Third Party foram nomeadas para JDK 1.4 e 5.0. Você pode precisar de outras bibliotecas para JDK 1.3. + + + + O código fonte para o tutorial está incluído no diretório da distribuição + doc/reference/tutorial/. + + + + + + Parte 1 – A primeira aplicação Hibernate + + + Primeiro, iremos criar uma simples aplicação Hibernate baseada em console. Usaremos uma base de dados Java (HSQL DB), então não teremos que instalar nenhum servidor de base de dados. + + + + Vamos supor que precisemos de uma aplicação com um banco de dados pequeno que possa armazenar e atender os eventos que queremos, e as informaççes sobre os hosts destes eventos. + + + + A primeira coisa que devemos fazer é configurar nosso diretório de desenvolvimento, + e colocar todas as bibliotecas Java que precisamos dentro dele. Faça o download da + distribuição do Hibernate no site do Hibernate. Descompacte o pacote e coloque todas + as bibliotecas necessárias encontradas no diretório /lib, dentro do + diretório /lib do seu novo projeto. Você deverá ter algo parecido + com isso: + + + + + + Esta é a configuração mínima requerida das bibliotecas (observe que também foi copiado + o hibernate3.jar da pasta principal do Hibernate) para o Hibernate na hora do desenvolvimento. O Hibernate permite que você utilize mais ou menos bibliotecas. + Veja o arquivo README.txt no diretório lib/ da distribuição + do Hibernate para maiores informaççes sobre bibliotecas requeridas e opcionais. + (Atualmente, a biblioteca Log4j não é requerida, mas é preferida por muitos desenvolvedores.) + + + + Agora, iremos criar uma classe que representa o evento que queremos armazenar na base de dados.. + + + + A primeira Classe + + + Nossa primeira classe de persistência é uma simples classe JavaBean com algumas propriedades: + + + + + + Você pode ver que esta classe usa o padrão JavaBean para o nomeamento convencional da propriedade getter e dos métodos setter, como também a visibilidade private dos campos. Este é um padrão de projeto recomendado, mas não requerido. O Hibernate pode também acessar campos diretamente, o benefício para os métodos de acesso é a robustez para o Refactoring. O construtor sem argumento é requerido para instanciar um objeto desta classe com a reflexão. + + + + A propriedade id mantém um único valor de identificação para um evento + particular. Todas as classes persistentes da entidade (bem como aquelas classes dependentes + de menos importância) precisam de uma propriedade de identificação, caso nós queiramos usar o + conjunto completo de características do Hibernate. De fato, a maioria das aplicações + (esp. aplicações web) precisam destinguir os objetos pelo identificador, então você deverá + considerar esta, uma característica em lugar de uma limitação. Porém, nós normalmente não + manipulamos a identidade de um objeto, consequentemente o método setter deverá ser privado. + O Hibernate somente nomeará os identificadores quando um objeto for salvo. Você pode ver como + o Hibernate pode acessar métodos públicos, privados, e protegidos, como também campos + (públicos, privados, protegidos) diretamente. A escolha está até você, e você pode combinar + isso para adaptar seu projeto de aplicação + + + + O construtor sem argumentos é um requerimento para todas as classes persistentes; + O Hibernate tem que criar para você os objetos usando Java Reflection. O construtor + pode ser privado, porém, a visibilidade do pacote é requerida para a procuração da + geração em tempo de execução e recuperação eficiente dos dados sem a instrumentação + de bytecode + + + + Coloque este fonte Java no diretório chamado src na pasta de desenvolvimento, + e em seu pacote correto. O diretório deverá ser parecido como este: + + + ++src + +events + Event.java]]> + + + No próximo passo, iremos falar sobre as classes de persistência do Hibernate.. + + + + + + O mapeamento do arquivo + + + O Hibernate precisa saber como carregar e armazenar objetos da classe de + persistência. Isto será onde o mapeamento do arquivo do Hibernate entrará em + jogo. O arquivo mapeado informa ao Hibernate, qual tabela no banco de dados + ele deverá acessar, e quais as colunas na tabela ele deverá usar. + + + + A estrutura básica de um arquivo de mapeamento é parecida com: + + + + + + +[...] +]]> + + + Note que o Hibernate DTD é muito sofisticado. Você pode usar isso para auto-conclusão + no mapeamento XML dos elementos e atributos no seu editor ou IDE. Você também pode + abrir o arquivo DTD no seu editor – é a maneira mais fácil de ter uma visão geral + de todos os elementos e atributos e dos padrões, como também alguns comentários. + Note que o Hibernate não irá carregar o arquivo DTD da web, e sim do diretório + da aplicação (classpath). O arquivo DTD está incluído no hibernate3.jar como + também no diretório src/ da distribuição do Hibernate. + + + + Nós omitiremos a declaração do DTD nos exemplos futuros para encurtar o código. Isto, é claro, não é opcional. + + + + Entre os dois tags hibernate-mapping, inclua um elemento class. + Todas as classes persistentes da entidade (novamente, poderá haver + mais tarde, dependências sobre as classes que não são classes-primárias + de entidades) necessitam do tal mapeamento, para uma tabela na base + de dados SQL + + + + + + + + +]]> + + + Mais adiante iremos dizer ao Hibernate como fazer para persistir e carregar objetos da classe + Event da tabela EVENTS, cada instancia representada por + uma coluna na tabela. Agora, continuaremos com o mapeamento de uma única propriedade identificadora + para as chaves primárias da tabela. Além disso, nós não iremos se importar com esta propriedade + identificadora, nós iremos configurar uma estratégia de geração de id’s para uma chave primária + de uma surrogate key: + + + + + + + + + + +]]> + + + O elemento id é a declaração da propriedade identificadora, + o name="id" declara o nome da propriedade Java – + o Hibernate irá usar os métodos getter e setter para acessar a propriedade. + O atributo da coluna informa ao Hibernate qual coluna da tabela EVENTS nós + iremos usar como chave primária. O elemento generator especifica + a estratégia de geração do identificador, neste caso usaremos native, que + escolhe a melhor estratégia dependendo da base de dados (dialeto) configurada. + O Hibernate suporta a base de dados gerada, globalmente única, bem como a atribuição + aos identificadores da aplicação (ou toda estratégia escrita para uma extensão). + + + + Finalmente incluiremos as declarações para as propriedades persistentes da classe + no arquivo mapeado. Por default, nenhuma das propriedades da classe é considerada persistente: + + + + + + + + + + + + +]]> + + + Da mesma maneira que com o elemento id, o atributo name do elemento + property informa ao Hibernate qual método getter e setter deverá usar. + Assim, neste caso, o Hibernate irá procurar pelo getDate()/setDate(), + como também pelo getTitle()/setTitle(). + + + + Porque fazer o mapeamento da propriedade date incluído no + atributo column, e no title não fazer? + Sem o atributo column o Hibernate por padrão usa o nome + da propriedade como o nome da coluna. Isto trabalha muito + bem para o title. Entretanto o date é uma palavra-chave reservada + na maioria dos bancos de dados, assim nós melhoramos o mapeamentos + disto com um nome diferente. + + + + A próxima coisa interessante é que mapemanto do title + também falta o atributo type. O tipo que declaramos e o uso nos + arquivos mapeados, não são como você pôde esperar, atributos de dados Java. + Eles não são como os tipos de base de dados SQL. + Esses tipos podem ser chamados de Tipos de mapeamento Hibernate, que são conversores + que podem traduzir tipos de dados do Java para os tipos de dados SQL e vice-versa. + Novamente, o Hibernate irá tentar determinar a conversão correta e mapeará o type + próprio, caso o tipo do atributo não estiver presente no mapeamento. + Em alguns casos, esta detecção automática (que usa Reflection sobre as classes Java) + poderá não ter padrão que você espera ou necessita. + Este é o caso com a propriedade date. O Hibernate não pode saber se a propriedade + (que é do java.util.Date) pode mapear para uma coluna do tipo date + do SQL, timestamp, ou time . + Nós preservamos a informação cheia de datas e horas pelo mapeamento da propriedade com um conversor + timestamp. + + + + Este arquivo de mapeamento deve ser salvo como Event.hbm.xml, + corretamente no diretório próximo ao arquivo fonte da Classe Java Event. + O nomeamento dos arquivos de mapeamento podem ser arbitrários, porém o sufixo + hbm.xml é uma convenção da comunidade dos desenvolvedores do Hibernate. + Esta estrutura do diretório deve agora se parecer com isso: + + + ++src + +events + Event.java + Event.hbm.xml]]> + + + Nós iremos continuar com a configuração principal do Hibernate. + + + + + + Configuração do Hibernate + + + Agora nós temos uma classe persistente e este arquivo de mapeamento no lugar. + Está na hora de configurar o Hibernate. Antes de fazermos isso, iremos precisar de uma base de dados. + O HSQL DB, um SQL DBMS feito em java, pode ser baixado através do site do HSQL DB(http://hsqldb.org/). + Atualmente, você só precisa baixar o hsqldb.jar. + Coloque este arquivo no diretório da pasta de desenvolvimento lib/. + + + + Crie um diretório chamado data no diretório root de desenvolvimento – + Isto será onde o HSQL DB irá armazenar arquivos de dados. Agora iremos iniciar o banco de dados + executando java -classpath ../lib/hsqldb.jar org.hsqldb.Server neste diretório de dados. + Você pode ver ele iniciando e conectando ao socket TCP/IP, isto será onde nossa aplicação irá se + conectar depois. Se você deseja iniciar uma nova base de dados durante este tutorial, + finalize o HSQL DB(pressionando o CTRL + C na janela), delete todos os + arquivos no diretório data/, e inicie o HSQL BD novamente. + + + + O Hibernate é uma camada na sua aplicação na qual se conecta com a base de dados, para isso + necessita de informação da conexão. As conexões são feitas através de um pool de conexão JDBC, + na qual teremos que configurar. A distribuição do Hibernate contém diversas ferramentas de pooling + da conexão JDBC de fonte aberta, mas iremos usar o pool de conexão interna para este tutorial. + Note que você tem que copiar a biblioteca necessária em seu classpath e use configurações + diferentes para pooling de conexão caso você deseje utilizar um software de pooling JDBC terceirizado + para qualidade de produção. + + + + Para as configurações do Hibernate, nós podemos usar um arquivo simples hibernate.properties, + um arquivo mais ligeiramente sofisticado hibernate.cfg.xml ou até mesmo uma + instalação programática completa. A maioria dos usuários preferem utilizar o arquivo de configuração XML + + + + + + + + + + + org.hsqldb.jdbcDriver + jdbc:hsqldb:hsql://localhost + sa + + + + 1 + + + org.hibernate.dialect.HSQLDialect + + + thread + + + org.hibernate.cache.NoCacheProvider + + + true + + + create + + + + + +]]> + + + Note que esta configuração XML usa um diferente DTD. Nós configuraremos + as SessionFactory do Hibernate – uma factory global responsável + por uma base de dedados particular. Se você tiver diversas bases de dados, + use diversas configurações <session-factory>, geralmente + em diversos arquivos de configuração (para uma partida mais fácil). + + + + As primeiras quatro propriedades do elemento contém a configuração + necessária para a conexão ao JDBC. A propriedade propriedade dialect + do elemento especifica a variante particular do SQL que o Hibernate gera. + O gerenciamento automático de sessão do Hibernate para contextos de persistência + estará disponível em breve. A opção hbm2ddl.auto habilita a geração + automática de schemas da base de dados – diretamente na base de dados. + Isto também pode ser naturalmente desligado (removendo a opção de configuração) ou redirecionando + para um arquivo com ajuda do SchemaExport nas tarefas do Ant. + Finalmente, iremos adicionar os arquivos das classes de persistência mapeadas na configuração. + + + + Copie este arquivo no diretório fonte, assim isto irá terminar na raiz (root) do + classpath. O Hibernate automaticamente procura por um arquivo chamado + hibernate.cfg.xml na raiz do classpath, no startup. + + + + + + Construindo com o Ant + + + Nos iremos, agora, construir o tutorial com Ant. Você ira precisar o Ant instalado – + se encontra disponível na página de download do Ant. + Como instalar o Ant, não será abordado aqui. Caso tenha alguma dúvida, por favor, + vá ao Ant manual. + Depois que tiver instalado o Ant, podemos começar a criar o arquivo de construção build.xml. + Este arquivo será chamado de build.xml e posto diretamente no diretório de desenvolvimento. + + + + Um arquivo básico de build, se parece com isto: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +]]> + + + Isto irá avisar ao Ant para adicionar todos os arquivos no diretório lib terminando com + .jar, para o classpath usado para compilação. Irá também copiar todos os + arquivos não-java para o diretório alvo (arquivos de configuração, mapeamento). Se você rodar + o ant agora, deverá ter esta saída. + + + ant +Buildfile: build.xml + +copy-resources: + [copy] Copying 2 files to C:\hibernateTutorial\bin + +compile: + [javac] Compiling 1 source file to C:\hibernateTutorial\bin + +BUILD SUCCESSFUL +Total time: 1 second ]]> + + + + + Startup and helpers + + + É hora de carregar e arquivar alguns objetos Event, mas primeiro + nós temos de completar o setup com algum código de infraestrutura. Este startup + inclui a construção de um objeto SessionFactory global e armazenar + isto em algum lugar de fácil acesso para o código da aplicação. + Uma SessionFactory pode abrir novas Session's. + Uma Session representa uma unidade single-theaded do trabalho, a + SessionFactory é um objeto global thread-safe, instanciado uma vez. + + + + Nos iremos criar uma classe de ajuda HibernateUtil, que toma + conta do startup e faz acesso a uma SessionFactory conveniente. + Vamos dar uma olhada na implementação: + + + + + + Esta classe não só produz a global SessionFactory no seu static initializer + (chamado uma vez pela JVM quando a classe é carregada), mas também esconde o fato + de que isto usa um static singleton. Ela pode muito bem, enxergar a + SessionFactory do JNDI em um application server. + + + + Se você der à SessionFactory um nome, no seu arquivo de configuração. + O Hibernate irá, de fato, tentar uni-lo ao JNDI depois que estiver construído. + Para evitar este completamente este código, você também poderia usar JMX deployment + e deixar o contêiner JMX capaz, instanciar e unir um HibernateService + no JNDI. Essas opções avançadas são discutidas no documento de referência do Hibernate. + + + + Coloque o HibernateUtil.java no diretório de arquivos + de desenvolvimento(source), em um pacote após o events: + + + ++src + +events + Event.java + Event.hbm.xml + +util + HibernateUtil.java + hibernate.cfg.xml ++data +build.xml]]> + + + Novamente, isto deve compilar sem problemas. Finalmente, nós precisamos configurar + um sistema de logging – o Hibernate usa commons logging e deixa você escolher entre o + Log4j e o logging do JDK 1.4 . A maioria dos desenvolvedores preferem o Log4j: copie + log4j.properties da distribuição do Hibernate (está no diretório + etc/), para seu diretório src, + depois vá em hibernate.cfg.xml. Dê uma olhada no exemplo de configuração e mude as + configurações se você quizer ter uma saída mais detalhada. Por default, apenas as + mensagems de startup e shwwn do Hibernate é mostrada no stdout. + + + + O tutorial de infra-estrutura está completo - e nós já estamos preparados para algum + trabalho de verdade com o Hibernate. + + + + + + Carregando e salvando objetos + + + Finalmente, nós podemos usar o Hibernate para carregar e armazenar objetos. + Nós escrevemos uma classe EventManager com um método main(): + + + + + + Nós criamos um novo objeto Event, e passamos para o Hibernate. + O Hibernate sabe como tomar conta do SQL e executa INSERTs + no banco de dados. Vamos dar uma olhada na Session e no + código Transaction-handling antes de executarmos. + + + + Um Session é uma unidade simples de trabalho. Por agora nós + iremos pegar coisas simples e assumir uma granularidade de um-pra-um entre uma + Session do Hibernate e uma transação de banco de dados. + Para proteger nosso código de um atual sistema subjacente de transação (nesse + caso puro JDBC, mas também poderia rodar com JTA), nos usamos a API + Transaction, que está disponível na Session do Hibernate. + + + + O que a sessionFactory.getCurrentSession() faz? Primeiro, você pode + chamar quantas vezes e de onde quiser, uma vez você recebe sua SessionFactory + (fácil graças ao HibernateUtil). O método getCurrentSession() + sempre retorna a unidade de trabalho "corrente". Lembra de que nós mudamos a opção + de configuração desse mecanismo para thread no hibernate.cfg.xml? Daqui em + diante, o escopo da unidade de trabalho corrente é a thread Java + corrente que executa nossa aplicação. Entretanto, esta não é toda a verdade. Uma + + + + Session começa quando é primeiramente necessária, quando é feita a + primeira chamada à getCurrentSession(). É então limitado pelo Hibernate + para thread corrente. Quando a transação termina, tanto com commit quanto rollback, + o Hibernate também desune a Session da thread e fecha isso pra você. + Se você chamar getCurrentSession() novamente, você receberá uma nova + Session e pode começar uma nova unidade de trabalho. Esse modelo de + programação de limite de thread thread-bound, é o modo mais popular + de se usar o Hibernate. + + + Related to the unit of work scope, should the Hibernate Session be used to + execute one or several database operations? The above example uses one Session + for one operation. This is pure coincidence, the example is just not complex enough to show any + other approach. The scope of a Hibernate Session is flexible but you should + never design your application to use a new Hibernate Session for + every database operation. So even if you see it a few more times in + the following (very trivial) examples, consider session-per-operation + an anti-pattern. A real (web) application is shown later in this tutorial. + + + Dê uma olhada no para mais informações a + respeito de manipulação de transação e demarcação. Nós também pulamos qualquer + manipulação de erro e rollback no exemplo anterior. + + + + Para executar esta primeira rotina, nos teremos que adicionar um ponto de chamada + para o arquivo de build do Ant: + + + + + + + +]]> + + + O valor do argumento action, é setado na linha de comando quando chamando esse ponto: + + + ant run -Daction=store]]> + + + Você deverá ver, após a compilação, o startup do Hibernate e, dependendo da sua + configuração, muito log de saída. No final você verá a seguinte linha: + + + + + + Este é o INSERT executado pelo Hibernate, os pontos de interrogação + representam parêmetros de união do JDBC. Para ver os valores substituídos, ou para diminuir a + verbalidade do log, check seu llog4j.properties. + + + + Agora nós gostaríamos de listar os eventos arquivados, então nós adicionamos uma + opção para o método main: + + + + + + Nos também adicionamos um novo método listEvents(): + + + + + + O que nós fazemos aqui, é usar uma query HQL (Hibernate Query Language), + para carregar todos os objetos Event exitentes no banco de dados. + O Hibernate irá gerar o SQL apropriado, enviar para o banco de dados e popular objetos + Event com os dados. Você pode criar queries mais complexas com + HQL, claro. + + + + Agora, para executar e testar tudo isso, siga os passos a seguir: + + + + + + Execute ant run -Daction=store para armazenar algo no banco de dados + e, claro, gerar o esquema do banco de dados antes pelo hbm2ddl. + + + + + Agora desabilite hbm2ddl comentando a propriedade no seu arquivo hibernate.cfg.xml. + Normalmente só se deixa habilitado em teste unitários contínuos, mas outra carga de hbm2ddl + pode remover tudo que você já tenha arquivado. Sa configuração + create, atualmente são traduzidas para "apague todas as tabelas do esquema, + então recrie todas quando a SessionFactory estiver pronta". + + + + + + Se você agora chamar o Ant com -Daction=list, você deverá ver os + eventos que você acabou de criar. Você pode também chamar a ação store + mais algumas vezes. + + + + Nota: A maioria dos novos usuários do Hibernate falha nesse ponto e nós regularmente, vemos + questões sobre mensagens de erro de tabela não encontrada . + Entretanto, se você seguir os passos marcados acima, você não terá esse problema, + com o hbm2ddl criando o esquema do banco de dados na primeira execução, e restarts + subsequentes da aplicação irão usar este esquema. Se você mudar o mapeamento e/ou + o esquema do banco de dados, terá de re-habilitar o hbm2ddl mais uma vez. + + + + + + + + Part 2 - Mapeando associações + + + Nós mapeamos uma classe de entidade de persistência para uma tabela. Agora vamos continuar + e adicionar algumas associações de classe. Primeiro nos iremos adicionar pessoas a nossa aplicação, + e armazenar os eventos de que elas participam. + + + + Mapeando a classe Person + + + O primeiro código da classe Person é simples: + + + + + + Crie um novo arquivo de mapeamento, chamado Person.hbm.xml (não + esqueça a referencia ao DTD no topo) + + + + + + + + + + + + + +]]> + + + Finalmente, adicione o novo mapeamento a configuração do Hibernate: + + + +]]> + + + Nos iremos agora criar uma associação entre estas duas entidades. Obviamente, + pessoas (Person) podem participar de eventos, e eventos possuem participantes. + As questões de design com que teremos de lidar são: direcionalidade, multiplicidade e + comportamento de coleção. + + + + + + Uma associação Set-based unidirectional + + + Nos iremos adicionar uma coleção de eventos na classe Person. Desse jeito + poderemos navegar pelos eventos de uma pessoa em particular, sem executar uma query explicitamente – + apenas chamando aPerson.getEvents(). Nos usaremos uma coleção Java, um + Set, porquê a coleção não conterá elementos duplicados e a ordem não é + relevante para nós. + + + + Vamos escrever o código para isto nas classes Java e então mapear: + + + + + + Antes de mapearmos esta associação, pense no outro lado. Claramente, poderíamos apenas fazer isto de + forma unidirecional. Ou poderíamos criar outra coleção no Event, se quisermos + ser capaz de navegar bidirecionalmente, i.e. um - anEvent.getParticipants(). + Isto não é necessário, de perspectiva funcional. Você poderia sempre executar uma query explicita + que retornasse os participantes de um evento em particular. Esta é uma escolha de design que cabe + a você, mas o que é claro nessa discussão é a multiplicidade da associação: "muitos" valores em ambos + os lados, nós chamamos isto uma associação muitos-para-muitos. Daqui pra frente, + nos usaremos o mapeamento muitos-para-muitos do Hibernate: + + + + + + + + + + + + + + + +]]> + + + O Hibernate suporta todo tipo de mapeamento de coleção , sendo um <set> mais comum. + Para uma associação muitos-para-muitos (ou relacionamento de entidade n:m ), + uma tabela de associação é necessária. Cada linha nessa tabela representa um link entre uma pessoa e um + evento. O nome da tabela é configurado com o atributo table do elemento + set. O nome da coluna identificadora na associção, peloo lado da pessoa, + é definido com o elemento <key> , o nome da coluna pelo lado dos eventos, + e definido com o atributo column do <many-to-many>. + Você também precisa dizer para o Hibernate a classe dos objetos na sua coleção (a classe do outro + lado das coleções de referência). + + + + O esquema de mapeamento para o banco de dados está a seguir: + + + | *EVENT_ID | | | + | EVENT_DATE | | *PERSON_ID | <--> | *PERSON_ID | + | TITLE | |__________________| | AGE | + |_____________| | FIRSTNAME | + | LASTNAME | + |_____________| + ]]> + + + + + Trabalhando a associação + + + Vamos trazer juntos algumas pessoas e eventos em um novo método na classe EventManager:: + + + + + + Após carregar um Person e um Event, simplesmente + modifique a coleção usando os métodos normais de uma coleção. Como você pode ver, não há chamada explícita + para update() ou save(), o Hibernate detecta automaticamente + que a coleção foi modificada e necessita ser atualizada. Isso é chamado de checagem + suja automática, e você também pode usá-la modificando o nome ou a data de qualquer um dos + seus objetos. Assim que eles estiverem no estado persistent, ou seja, + limitado por uma Session do Hibernate em particular (i.e. eles foram carregados ou + salvos dentro de uma unidade de trabalho), o Hibernate monitora qualquer alteração e executa o SQL + em modo de escrita em segundo plano. O processo de sincronização do estado da memória com o banco de + dados, geralmente apenas no final de uma unidade de trabalho, é chamado de flushing. + No nosso código, a unidade de trabalho termina com o commit da transação do banco de dados – + como definido pela opção de configuração da thread da classe CurrentSessionContext. + + + + Você pode também querer carregar pessoas e eventos em diferentes unidades de trabalho. + Ou você modifica um objeto fora de uma Session, quando não se encontra no + estado persistent (se já esteve neste estado anteriormente, chamamos esse estado de + detached). Você pode até mesmo modificar uma coleção quando esta + se encontrar no estado detached. + + + + + + A chamada update cria um objeto persistent novamente, você poderia + dizer que ele liga o objeto a uma nova unidade de trabalho, assim qualquer modificação + que você faça neste objeto enquanto estiver no estado detached pode ser salvo no banco de dados. + Isso inclui qualquer modificação (adição/exclusão) que você faça em uma coleção da entidade deste objeto. + + + + Bom, isso não foi muito usado na nossa situação, porém, é um importante conceito que você + pode aplicar em seus aplicativos. Agora, complete este exercício adicionando uma nova ação + ao método main( ) da classe EventManager e chame-o pela linha de comando. + Se você precisar dos identificadores de uma pessoa ou evento – o método save() + retorna estes identificadores (você poderá modificar alguns dos métodos anteriores para retornar aquele + identificador): + + + + + + Este foi um exemplo de uma associação entre duas classes igualmente importantes, duas entidades. + Como mencionado anteriormente, há outras classes e tipos dentro de um modelo típico, + geralmente "menos importante". Alguns você já viu, como um int ou uma String. + Nós chamamos essas classes de value types, e suas instâncias depend + de uma entidade particular. As instâncias desses tipos não possuem sua própria identidade, nem são + compartilhados entre entidades (duas pessoas não referenciam o mesmo objeto firstname + mesmo se elas tiverem o mesmo objeto firstname). Naturalmente, os value types não são apenas encontrados + dentro da JDK (de fato, em um aplicativo Hibernate todas as classes JDK são consideradas como value types), + mas você pode também criar suas classes como, por exemplo, Address ou MonetaryAmount. + + + + + Você também pode criar uma coleção de value types. Isso é conceitualmente muito diferente + de uma coleção de referências para outras entidades, mas em Java parece ser quase a mesma coisa. + + + + + + Coleção de valores + + + Nós adicionamos uma coleção de objetos de tipo de valores à entidade Person. + Nós querermos armazenar endereços de e-mail, para isso utilizamos o tipo String, + e a coleção novamente será um Set: + + + + + O mapeamento deste Set: + + + + + +]]> + + + A diferença comparada com o mapeamento anterior se encontra na parte element, + que indica ao Hibernate que a coleção não contém referências à outra entidade, mas uma coleção de + elementos do tipo String (a tag name em miniscula indica que se trata de um + mapeamento do Hibernate para conversão de tipos). Mais uma vez, o atributo table + do elemento set determina o nome da tabela para a coleção. O elemento + key define o nome da coluna de chave estrangeira na tabela de coleção. + O atributo column dentro do elemento element define o + nome da coluna onde os valores da String serão armazenados. + + + + Dê uma olhada no esquema atualizado: + + + | *EVENT_ID | | | |___________________| + | EVENT_DATE | | *PERSON_ID | <--> | *PERSON_ID | <--> | *PERSON_ID | + | TITLE | |__________________| | AGE | | *EMAIL_ADDR | + |_____________| | FIRSTNAME | |___________________| + | LASTNAME | + |_____________| + ]]> + + + Você pode observar que a chave primária da tabela da coleção é de na verdade uma chave composta, + usando ambas colunas. Isso também implica que cada pessoa não pode ter endereços de e-mail + duplicados, o que é exatamente a semântica que precisamos para um set em Java. + + + + Você pode agora tentar adicionar elementos a essa coleção, do mesmo modo que fizemos + anteriormente ligando pessoas e eventos. È o mesmo código em Java: + + + + + + This time we didnt' use a fetch query to initialize the collection. + Hence, the call to its getter method will trigger an additional select to initialize + it, so we can add an element to it. Monitor the SQL log and try to optimize this with + an eager fetch. + + + + + + Associações bidirecionais + + + Agora iremos mapear uma associação bidirecional – fazendo a associação entre pessoas e + eventos, de ambos os lados, em Java. Logicamente, o esquema do banco de dados não muda, + nós continuamos tendo multiplicidades muitos-para-muitos. Um banco de dados é mais flexível do que + uma linguagem de programação para redes, ele não precisa de nenhuma direção de navegação – os + dados podem ser acessados em qualquer caminho possível. + + + + Primeiramente, adicione uma coleção de participantes à classe Event: + + + + + + Agora mapeie este lado da associação em Event.hbm.xml. + + + + + +]]> + + + Como você pode ver, esses é uma mapeamento normal usando set em ambos documenentos + de mapeamento. Observe que o nome das colunas em key e many-to-many + estão trocados em ambos os documentos de mapeamento. A adição mais importante feita está no atributo + inverse="true" no elemento set do mapeamento da coleção da classe Event. + + + + Isso significa que o Hibernate deve pegar o outro lado – a classe Person – + quando necessitar encontrar informação sobre a relação entre as duas entidades. Isso será muito + mais facilmente compreendido quando você analisar como a relação bidirecional entre as entidades é criada. + + + + + + Trabalhando com links bidirecionais + + + Primeiro tenha em mente que o Hibernate não afeta a semântica normal do Java. Como nós criamos + um link entre uma Person e um Event no exemplo unidirecional? + Nós adicionamos uma instância de Event, da coleção de referências de eventos, + a uma instância de Person. Então, obviamente, se nós queremos que este link funcione + bidirecionalmente, nós devemos fazer a mesma coisa para o outro lado – adicionando uma referência de + Person na coleção de um Event. Esse acerto de link de ambos + os lados é absolutamente necessário e você nunca deve esquecer de faze-lo. + + + + Muitos desenvolvedores programam de maneira defensiva e criam métodos + gerenciador de associações que ajusta corretamente ambos os lados: + + + + + + Observe que os métodos set e get da a coleção estão protegidos – isso permite que classes e + subclasses do mesmo pacote continuem acessando os métodos, mas previne que qualquer outra classe, + que não esteja no mesmo pacote, acesse a coleção diretamente. Você provavelmente deve fazer a mesma + coisa para a coleção do outro lado. + + + + E sobre o mapeamento do atributo inverse? Pra você, e para o Java, um link bidirecional + é simplesmente o fato de ajustar corretamente as referências de ambos os lados. O Hibernate, entretanto + não possui informação necessária para corretamente adaptar os estados INSERT e + UPDATE do SQL, e precisa de ajuda para manipular as propriedades das associações + bidirecionais. Fazer um lado da associação com o atributo inverse instrui o Hibernate + para basicamente ignora-lo, considerando-o uma cópia do outro lado. Isso é todo o + necessário para o Hibernate trabalhar com todas as possibilidades quando transformando um modelo de + navegação bidirecional em esquema de banco de dados do SQL. As regras que você possui para lembrar são + diretas: Todas associações bidirecionais necessitam que um lado possua o atributo inverse. Em uma + associação de um-para-muitos, o lado de "muitos" deve conter o atributo inverse, + já em uma associação de muitos-para-muitos você pode pegar qualquer lado, não há diferença. + + + + + + Agora, vamos portar este exemplo para um pequeno aplicativo para internet. + + + + + + + EventManager um aplicativo para internet + + + Um aplicativo para internet do Hibernate usa uma Session e uma Transaction + quase do mesmo modo que um aplicativo standalone. Entretanto, alguns patterns comuns são úteis. + Nós agora criaremos um EventManagerServlet. Esse servlet lista todos os eventos + salvos no banco de dados, e cria um formulário HTML para entrada de novos eventos. + + + + Criando um servlet básico + + + Crie uma nova classe no seu diretório fonte, no pacote events: + + + + + + O servlet manuseia somente requisições GET do HTTP, + portanto o método que iremos implementar é doGet(): + + + + + + O pattern que estamos aplicando neste código é chamado session-per-request. + Quando uma requisição chega ao servlet, uma nova Session do Hibernate é + aberta através da primeira chamada para getCurrentSession() em + SessionFactory. Então uma transação do banco de dados é inicializada - + todo acesso a dados deve ocorrer dentro de uma transação, não importando se o dado é de leitura ou escrita. + (nós não devemos usar o modo auto-commit em aplicações). + + + + Do not use a new Hibernate Session for + every database operation. Use one Hibernate Session that is + scoped to the whole request. Use getCurrentSession(), so that + it is automatically bound to the current Java thread. + + + Agora, as possibilidades de ações de uma requisição serão processadas e uma resposta HTML será renderizada. + Nós já iremos chegar nesta parte. + + + + Finalmente, a unidade de trabalho termina quando o processamento e a restituição são completados. + Se ocorrer algum erro durante o processamento ou a restituição, uma exceção será lançada e a + transação do banco de dados encerrada. Isso completa o pattern session-per-request. + Em vez de usar código de demarcação de transação em todo servlet você pode também criar um filtro servlet. + Dê uma olhada no site do Hibernate e do Wiki para maiores informações sobre esse pattern, + chamado Open Session in View. + + + + + + Processando e renderizando + + + Vamos implementar o processamento da requisição e a restituição da página HTML. + + +Event Manager"); + +// Handle actions +if ( "store".equals(request.getParameter("action")) ) { + + String eventTitle = request.getParameter("eventTitle"); + String eventDate = request.getParameter("eventDate"); + + if ( "".equals(eventTitle) || "".equals(eventDate) ) { + out.println("Please enter event title and date."); + } else { + createAndStoreEvent(eventTitle, dateFormatter.parse(eventDate)); + out.println("Added event."); + } +} + +// Print page +printEventForm(out); +listEvents(out, dateFormatter); + +// Write HTML footer +out.println(""); +out.flush(); +out.close();]]> + + + O estilo de código acima, misturando linguagem HTML e Java não será funcional em um aplicativo + mais complexo—tenha em mente que neste manual nós estamos apenas ilustrando conceitos + básicos do Hibernate. O código imprime um cabeçalho HTML e um rodapé. Dentro desta página, + é mostrado um formulário em HTML, para entrada de novos eventos, e uma lista de todos + os eventos contidos no banco de dados. O primeiro método é trivial e apenas imprime + uma página HTML: + + + Add new event:"); + out.println("
"); + out.println("Title:
"); + out.println("Date (e.g. 24.12.2009):
"); + out.println(""); + out.println("
"); +}]]>
+ + + O método listEvents() usa a Session do Hibernate + associada a thread atual para executar um query: + + + 0) { + out.println("

Events in database:

"); + out.println(""); + out.println(""); + out.println(""); + out.println(""); + out.println(""); + for (Iterator it = result.iterator(); it.hasNext();) { + Event event = (Event) it.next(); + out.println(""); + out.println(""); + out.println(""); + out.println(""); + } + out.println("
Event titleEvent date
" + event.getTitle() + "" + dateFormatter.format(event.getDate()) + "
"); + } +}]]>
+ + + Finalmente, a action store é passada pra o método + createAndStoreEvent(), que também usa a + Session da thread atual: + + + + + + Pronto, o servlet está completo. Uma requisição para o servlet será processada + em uma Session e uma Transaction simples. + Como anteriormente, no aplicativo standalone, o Hibernate pode automaticamente + associar esses objetos a thread atual em execução. Isso possibilita a liberdade + de você modelar seu código e acessar o método SessionFactory + do jeito que achar melhor. Geralmente você irá usar um design mais sofisticado + e mover o código de acesso a dados para dentro de objetos de acesso a dados + (o patter DAO). Leia o Hibernate Wiki para maiores exemplos. + + +
+ + + Instalando e testando + + + Para fazer o deploy desta aplicação você tem que criar um arquivo para web, um WAR. + Adicione o alvo Ant abaixo em seu build.xml: + + + + + + + + + + +]]> + + + Esta target cria um arquivo chamado hibernate-tutorial.war + no diretório do seu projeto. Ele empacota todas as bibliotecas e o arquivo de + descrição web.xml, o qual é esperado no diretório base do seu projeto: + + + + + + + Event Manager + events.EventManagerServlet + + + + Event Manager + /eventmanager + +]]> + + + Antes de você compilar e fazer o deploy desta aplicação web, note que uma biblioteca + adicional é requerida: jsdk.jar. Esse é o Java servlet development kit, + se você não possui esta biblioteca, faça seu download na página da Sun e copie-a + para seu diretório de bibliotecas. Entretanto, será usado somente para a compilação e + excluído do pacote WAR. + + + + Para compilar e instalar execute ant war no seu diretório do projeto + e copie o arquivo hibernate-tutorial.war para o diretório + webapp do Tomcat. Se você não possui o Tomcat instalado faça + o download e siga as instruções de instalação. Você não precisa modificar + nenhuma configuração do Tomcat para rodar este aplicativo. + + + + Uma vez feito o deploy e com Tomcat rodando, acesse o aplicativo em + http://localhost:8080/hibernate-tutorial/eventmanager. + Veja o log do Tomcat para observar a inicialização do Hibernate quando a + primeira requisição chega ao servlet (o inicializador estático dentro de + HibernateUtil é chamado) e para ter uma depuração + detalhada se ocorrer alguma exceção. + + + + +
+ + + Sumário + + + Este manual cobriu os princípios básicos para criação de uma aplicação simples do Hibernate + e uma pequena aplicação web. + + + + Se você já se sente seguro com o Hibernate, continue navegando na documentação de referência + por tópicos que você acha interessante – os tópicos mais questionados são: + processo de transação (), uso da API () + e características de consulta (). + + + + Não esqueça de visitar o site do Hibernate para obter mais tutoriais especializados. + + + + +
diff --git a/documentation/manual/pt-BR/src/main/docbook/content/xml.xml b/documentation/manual/pt-BR/src/main/docbook/content/xml.xml index d16911d9fe..c37c9428f8 100755 --- a/documentation/manual/pt-BR/src/main/docbook/content/xml.xml +++ b/documentation/manual/pt-BR/src/main/docbook/content/xml.xml @@ -1,7 +1,7 @@ - + Mapeamento XML