Hibernate.orgCommunity Documentation

Capítulo 28. Considerações da Portabilidade do Banco de Dados

28.1. Fundamentos da Portabilidade
28.2. Dialeto
28.3. Resolução do Dialeto
28.4. Geração do identificador
28.5. Funções do banco de dados
28.6. Tipos de mapeamentos

Um dos pontos de venda do Hibernate (e realmente Mapeamento do Objeto/Relacional como um conjunto) é a noção da portabilidade do banco de dados. Isto pode significar um usuário de TI interno migrando a partir de um fornecedor de banco de dados a outro, ou isto pode significar que um framework ou aplicativo implementável consumindo o Hibernate para produtos de banco de dados múltiplos de destinação simultaneamente pelos usuários. Independente do cenário exato, a idéia básica é que você queira que o Hibernate o ajude a rodar em referência a qualquer número de banco de dados sem as alterações a seu código e preferencialmente sem quaisquer alterações ao metadados de mapeamento.

A primeira linha de portabilidade para o Hibernate é o dialeto, que trata-se de uma especialização de um contrato org.hibernate.dialect.Dialect. Um dialeto encapsula todas as diferenças em como o Hibernate deve comunicar-se com um banco de dados particular para completar algumas tarefas como obter um valor de seqüência ou estruturar uma consulta SELECT. O Hibernate vincula uma variedade de dialetos para muitos dos bancos de dados mais populares. Se você achar que seu banco de dados particular não está seguindo os mesmos, não será difícil escrever o seu próprio.

Originalmente, o Hibernate sempre solicita que os usuários especifiquem qual dialeto a ser usado. No caso dos usuários buscarem banco de dados múltiplos de destinação simultaneamente com as próprias construções que eram problemáticas. Normalmente, isto solicita que seus próprios usuários configurem o dialeto do Hibernate ou definam o próprio método de determinação do valor.

Inicializando com a versão 3.2, o Hibernate introduziu a noção de detecção automática do dialeto para uso baseado no java.sql.DatabaseMetaData obtido a partir de um java.sql.Connection para aquele banco de dados. Era muito melhor, esperar que esta resolução limitada aos bancos de dados Hibernate soubesse com antecedência e que em ocasião alguma era configurável ou substituível.

Starting with version 3.3, Hibernate has a fare more powerful way to automatically determine which dialect to should be used by relying on a series of delegates which implement the org.hibernate.dialect.resolver.DialectResolver which defines only a single method:

public Dialect resolveDialect(DatabaseMetaData metaData) throws JDBCConnectionException

The basic contract here is that if the resolver 'understands' the given database metadata then it returns the corresponding Dialect; if not it returns null and the process continues to the next resolver. The signature also identifies org.hibernate.exception.JDBCConnectionException as possibly being thrown. A JDBCConnectionException here is interpreted to imply a "non transient" (aka non-recoverable) connection problem and is used to indicate an immediate stop to resolution attempts. All other exceptions result in a warning and continuing on to the next resolver.

A melhor parte destes solucionadores é que os usuários também podem registrar os seus próprios solucionadores personalizados dos quais serão processados antes dos Hibernates internos. Isto poderá ser útil em um número diferente de situações: permite uma integração fácil de auto-detecção de dialetos além daqueles lançados com o próprio Hibernate. Além disto, permite que você especifique o uso de um dialeto personalizado quando um banco de dados particular é reconhecido, etc. Para registrar um ou mais solucionadores, apenas especifique-os (separados por vírgula, tabs ou espaços) usando o conjunto de configuração 'hibernate.dialect_resolvers' (consulte a constante DIALECT_RESOLVERS no org.hibernate.cfg.Environment).

When considering portability between databases, another important decision is selecting the identifier generation stratagy you want to use. Originally Hibernate provided the native generator for this purpose, which was intended to select between a sequence, identity, or table strategy depending on the capability of the underlying database. However, an insidious implication of this approach comes about when targtetting some databases which support identity generation and some which do not. identity generation relies on the SQL definition of an IDENTITY (or auto-increment) column to manage the identifier value; it is what is known as a post-insert generation strategy becauase the insert must actually happen before we can know the identifier value. Because Hibernate relies on this identifier value to uniquely reference entities within a persistence context it must then issue the insert immediately when the users requests the entitiy be associated with the session (like via save() e.g.) regardless of current transactional semantics.

The underlying issue is that the actual semanctics of the application itself changes in these cases.

Starting with version 3.2.3, Hibernate comes with a set of enhanced identifier generators targetting portability in a much different way.

Nota

There are specifically 2 bundled enhancedgenerators:

  • org.hibernate.id.enhanced.SequenceStyleGenerator

  • org.hibernate.id.enhanced.TableGenerator

The idea behind these generators is to port the actual semantics of the identifer value generation to the different databases. For example, the org.hibernate.id.enhanced.SequenceStyleGenerator mimics the behavior of a sequence on databases which do not support sequences by using a table.

As funções SQL podem ser referenciadas em diversas maneiras pelos usuários. No entanto, nem todos os bancos de dados suportam o mesmo conjunto de função. O Hibernate fornece um significado de mapeamento do nome da função lógica para uma delegação que sabe como manusear aquela função em particular, mesmo quando usando uma chamada de função física totalmente diferente.

A seção está esquematizada para finalização numa data posterior...