A camada de persistência respeita por padrão os mesmo princípios da camada de serviço.
 

Generalidades

O mecanismo de persistência na base de dados responderá por padrão ao framework Hibernate. Em certos casos, que deverão ser justificados (por exigências particulares de performance ou vontade de recorrer diretamente à potência da linguagem SQL), as operações nas bases de dados poderão ser realizadas diretamente via JDBC.

O acesso à uma base de dados utilizará um DataSource associado à um pool de conexões definido ao nível do servidor de aplicações. Será acessado via JNDI.

DAO

As operações propostas pela camada de persistência serão os métodos nas classes chamadas DAO. A exemplo dos serviços das camadas de serviço e enterprise, os DAO também deverão estar preparados para receber DI, no caso do Hibernate para receber a SessionFactory. Isto já estará disponível no AbstractHibernateDAO do framework.

O métodos eventuais ou classes criadas pela fábrica de código ao nível dos DAO deverão estar disponíveis com uma visibilidade reduzida (mais restrito que public) a fim de impedir a sua chamada pelas outras camadas.

Visando o reuso e uma clara definição dos serviços propostos pela persistência, deverá se implementar os façades dos DAO sob a forma de interfaces Java que estarão suscetíveis a sofrer várias implementações. Esta escolha visa o desacoplamento das camadas.

Geralmente, deve-se procurar escrever uma classe DAO por entidade de negócio, esta classe será responsável por gerenciar a persistência da entidade de negócio.

Gestão das exceções

Por padrão todas as exceções serão unchecked, ou seja, não haverá tratamento explícito via código (try-catch) mas a assinatura de cada método deverá possuir o lançamento da exceção da camada em questão.
i.e. throws PersistenceException (exceção da camada de persistência)

Em casos específicos onde seja necessário tratar exceções nas camadas, poderão ser lançadas as exceções disponíveis por camada (G07) ou novas exceções poderão ser encapsuladas ou especializadas à partir destas exceções.
i.e. MySpecificPersistenceException extends PersistenceException

Gestão das transações

Nenhuma transação deverá ser criada, aberta ou fechada na camada de persistência porque isto é de responsabilidade das camadas superiores. A classe pai possui o método getSession() que permite acessar a sessão Hibernate indispensável para realizar as operações de acordo com a API deste framework.
Para as operações atômicas de uma entidade (criação, modificação, exclusão), esta entidade será recebida como parâmetro do método do DAO.

No caso do DAO se conectar à outro sistema diferente de uma base de dados (arquivo, MQ), deverá se respeitar os mesmo princípios do ponto de vista da API exposta à camada superior, a implementação dependerá somente da tecnologia em questão.

Mapeamenteo objeto-relacional

O mapeamento entre as tabelas da base de dados e classes representa as entidades de negócio e será definido nos arquivos de configuração do Hibernate em XML. Deverá ser criado um arquivo por classe de entidade.

Sempre que possível deve-se tentar coincidir o esquema relacional com o modelo de objetos, ou seja, na maioria das vezes, existirá uma classe por tabela e uma variável por coluna.

É recomendado o uso de identificadores técnicos numéricos que são naturais para o Hibernate e facilitam o desenvolvimento da camada cliente. Utilizar o mecanismo da base de dados para atribuir este identificador (chave primária alimentada por uma seqüência).

Evitar definir para os mapeamentos todas as relações entre as classes. Limitar-se aos casos mais úteis e de preferência utilizar como padrão o modo lazy loading.

A associação da palavra chave fetch indica ao Hibernate que ele deverá recuperar via a mesma requisição os dados correspondentes aos objetos em relação. Na sua ausência, a operação enviará n+1 requisições à base de dados afim de instanciar os objetos relacionados.
É preferível otimizar as requisições HQL, que retornam coleções de entidades em relação às outras entidades, utilizando a palavra chave fetch associada com join.
Para objetos estáticos e/ou somente de pesquisa utilizar a definição de classe mutable=”false” que também melhora muito a performance.
Para subqueries pode ser utilizada a definição batch-size=”50” para retornar vários registros (50) de uma vez só ocasionando em cláusulas IN nas subqueries.

Implementação

Interface Serviço de Persistência

Exemplo de código da interface de um serviço de persistência (DAO)

Mapeamento objeto-relacional com Hibernate

Por padrão o mapeamento objeto-relacional deverá ser realizado através do uso das anotações para persistência nas entidades que serão persistidas seguindo o padrão da API de persistência Java – JPA (anotações na entidade de negócio).
Exemplo do xml para definição de queries no Hibernate (hbm)