Luiz Carlos d´Oleron [email protected] SJCP Java Avançado Hibernate II.
Transcript of Luiz Carlos d´Oleron [email protected] SJCP Java Avançado Hibernate II.
Luiz Carlos d´Oleron – [email protected]
Hibernate• Continuaremos a conhecer os conceitos básicos de hibernate
• Compreenderemos os conceitos técnicos que fomos apresentados na aula anterior
• E seremos apresentados a novos conceitos
• Devido a carga horária reduzida, veremos apenas uma parte importante de Hibernate. Fique atento à bibliografia no fim da apresentação|!
• Manter em mente que hibernate é uma ferramenta para simplificar a persistência de aplicações orientadas a objetos em Java
• Dessa forma, precisaremos conceber o sistema corretamente, senão hibernate não terá valia
Luiz Carlos d´Oleron – [email protected]
Hibernate e DAO Pattern• Pergunta: Com hibernate, continuamos precisando do DAO
Pattern?
• Sim. Hibernate é uma camada de persistência que deve se encaixar acima de JDBC e abaixo do DAO
• DAO deve encapsular do resto do sistema que a tecnologia de persistência utilizada é hibernate
• Código hibernate não deve ser distribuído, em hipótese alguma, em regiões acima do DAO
• Manter em mente que estas subdivisões são lógicas, sendo, muitas vezes, os componentes de diferentes camadas, armazenados fisicamente no mesmo computador
Luiz Carlos d´Oleron – [email protected]
POJOs
• Hibernate fará a persistência de Objetos Java, em particular, Hibernate fará persistência de POJO´s
• Mais o que é um POJO?
• Como eu posso criar um POJO?
• POJO´s são formas de representar dados em objetos java
• Exemplo: classe Cliente
Luiz Carlos d´Oleron – [email protected]
POJOs
• Plain Old Java Objects
• Parecidos com JavaBeans
• Nome dado ao Objetos de Dados construídos com o velho padrão get/set
• Diferente de Javabeans, não precisam ser serializáveis (nem tem qualquer outra restrição sobre extrender uma classe específica ou mesmo implementar determinada interface)
Luiz Carlos d´Oleron – [email protected]
Identificando um POJO
• Existem algumas relações de interesse entre os objetos:
– Igualdade• Dois objetos são iguais pelo operador “==”
– Equivalência• Dois objetos são equivalente através do método equals
– Identidade• Dois objetos possuem o mesmo valor de chave primária
Luiz Carlos d´Oleron – [email protected]
Métodos equals e hashcode• Toda classe possui o método equals, com a assinatura a seguir:
public boolean equals(Object obj);
• Se a classe não definir um método equals, ela herdará o equals de Object (ou da superclasse)
• O método equals de Object utiliza apenas a igualdade pelo operador “==”
• Visto que dois objetos podem ser equivalentes mesmo não sendo a mesma instância, é comum que se sobre escreva o método equals de object
• Isto pode ser importante especialmente quando utilizamos coleções, visto que, por exemplo, muitas implementações do método java.util.Collection.contains(Object), chamam o método equals.
• Mas como isto deve ser feito?
• E o que o método hashcode tem haver com isso?
Luiz Carlos d´Oleron – [email protected]
Contrato do método equals
– equals implementa uma relação de equivalência para referências não nulas:
• Reflexivo: x.equals(x) deverá retorna true• Simétrico: x.equals(y) é true se somente se y.equals(x) é
true• Transitivo: Se x.equals(y) é true e y.equals(z) é true, então
x.equals(z) é true• Consistência: Múltiplas invocações de x.equals(y) deverão
retornar sempre true ou sempre false desde que x e y não se alterem
• Para x não nulo, x.equals(null) deverá retornar false.
– Quando se reescrever o método equals, deverá se reescrever o método hashcode
Luiz Carlos d´Oleron – [email protected]
Implementando o equals
Luiz Carlos d´Oleron – [email protected]
Contrato do método hashcode
• Utilizado em estruturas do tipo Hash, como java.util.Hashtable.
• O nº de hash deve permanecer igual para chamadas sucessivas, desde que o estado do objeto se mantenha o mesmo.
• Se dois objetos são equivalentes, pelo método equals, eles devem produzir o mesmo valor para hashcode
• Se dois objetos são diferentes, pelo método equals, eles podem retornar hashcodes diferentes ou iguais
• O hashcode implementado por Object produz valores diferentes para diferentes objeto (pelo equals de object), normalmente fazendo isso através de uma representação inteira da referência de Object.
Luiz Carlos d´Oleron – [email protected]
Implementando o hashcode
Luiz Carlos d´Oleron – [email protected]
Relacionamentos e Mapeamentos
• Objetos se relacionam de várias formas
• Representar todos os tipos de relacionamentos possíveis entre objetos é uma das tarefas mais árduas de ORM
• Em hibernate, os relacionamentos são representados pelas estruturas das classes e seus respectivos mapeamentos
• Neste curso, veremos os seguintes tipos de relacionamentos, com seus respectivos mapeamentos:
– Um para Muitos
– Um para Um
– Muitos para Muitos
– Hierarquia de classes
– Relacionamentos bidirecionais
Luiz Carlos d´Oleron – [email protected]
Associação Um para Muitos
• É o tipo mais simples de associação
• É o tipo mais comum de associação também
• Utilizados em agregações e composições
Luiz Carlos d´Oleron – [email protected]
Associação Um para Muitos
Na classe Cliente, a associação unidirecional é representada por:
•um atributo Set de telefones•seus respectivos métodos acessores
•No mapeamento, definimos um set•Observe que usamos a tag one-to-many
Luiz Carlos d´Oleron – [email protected]
inverse=“true|false”• O atributo inverse=“false” indica que a classe tem
responsabilidade de gerenciar a associação e as instâncias que estão nelas.
• No mapeamento anterior, a responsabilidade de gerenciar a associação e persistir as alterações dos objetos envolvidos é das instâncias de Cliente, e não de Telefone
• O atributo inverse=“true” indica que a responsabilidade de gerenciar a associação é do lado oposto da associação
Luiz Carlos d´Oleron – [email protected]
cascade
• Hibernate permite a persistência transitiva• Isto é feito quando você chama uma operação, tipo
save, em um objeto, sendo a operação propagada nos demais objetos associados
• Isto é feito com cascade• Cascade define quais operações serão propagadas nos
objetos associados• Alguns dos valores possíveis são:
– all– none– save-update– delete– all-delete-orphan
Luiz Carlos d´Oleron – [email protected]
Associação um para um• O mapeamento um para um é tão
simples (ou mais) que o mapeamento um-para-muitos
• O mapeamento de Endereco é simples, como em Telefone
• O mapeamento de Cliente possui agora a tag one-to-one
• Lembre-se de adicionar o mapeamento de Endereco ao hibernate.cfg.xml
Luiz Carlos d´Oleron – [email protected]
Associação muito para muitos
• Tente não usar associações muito para muitos
• Observe sempre se a relação não poderia ser desmembrada com uma entidade de relacionamento e duas associações do tipo um-para-muitos (Pattern Mediator)
• Uma instância simples de associação muitos-para-muitos é a associaçao muitos-para-muitos unidirecional
• Ela se parece bastante com o que já foi visto até agora:
<set name=“categorias” table=“tab_categoria_cliente” cascade=“save-update”>
<key column=“id_cliente”/>
<many-to-many class=“Categoria” column=“id_categoria”/>
</set>
Luiz Carlos d´Oleron – [email protected]
Associação muito para muitos
Luiz Carlos d´Oleron – [email protected]
Associações bidirecionais
• No exemplo visto até aqui, os clientes “conhecem” seus telefones, mas uma instância de telefone não possui nenhuma informação sobre seu proprietário
• A este tipo de associação, damos o nome de associação unidirecional
• Muitas vezes, é necessário representar uma associação bidirecional, aonde ambas as extremidades da associação tem conhecimento da outra
• Associações bidirecionais são mais difíceis de manter, visto que ambos os lados precisam sincronizar as alterações, quando elas ocorrem
Luiz Carlos d´Oleron – [email protected]
Associações bidirecionaisNuma associação Bidirecional, ambos os lados tem que ser
notificados, quando de uma alteração:
class Cliente{private Set<Categoria> categorias;...
}class Categoria{
private Set<Cliente> clientes;...
}...cliente.getCategorias().add(categoria);categoria.getClientes().add(cliente);...
Luiz Carlos d´Oleron – [email protected]
Associações bidirecionaisOs mapeamentos das classes:
<class name=“Cliente” table=“tab_clientes”>
...<set name=“categorias”>
<key column=“codigo_cliente”> <many-to-many class=“Categoria” column=“codigo_categoria”/></set>...
</class>
<class name=“Categoria” table=“tab_catergoria”>
...<set name=“clientes” inverse=“true” >
<key column=“codigo_categoria”> <many-to-many class=“Cliente” column=“codigo_cliente”/></set>...
</class>
Luiz Carlos d´Oleron – [email protected]
Representando Herança
• Mapear herança é um dos trabalhos mais difíceis em ORM
• Isto por que não existe herança no mundo relacional
• Assim sendo “herança é o descasamento mais visível entre os mundos relacional e orientado a objetos”
Luiz Carlos d´Oleron – [email protected]
Estratégias para Herança• Existem três estratégias para se trabalhar com herança:
– Tabela por classe concreta
– Tabela por hierarquia de classe
– Tabela por Subclasse
• Cada estratégia possui suas próprias vantagens e desvantagens
• Às vezes você já possui uma estrutura de banco de dados legada, e terá que usar a estratégia que melhor se adeqüe a este legado
Luiz Carlos d´Oleron – [email protected]
Tabela por Classe concreta
• Ideal para classes que não fazem parte de uma hierarquia ou que estão na raiz de uma hierarquia (nível mais alto)
– Essas classes não devem ser usadas em polimorfismo
– Uma declaração <class> para cada classe concreta; um atributo table diferente para cada uma (igual a mapeamento simples)
• Desvantagens
– Pouco suporte para associações polimórficas
– Queries polimórficos, executados em superclasses das classes usadas causam múltiplos queries nas tabelas mapeadas às classes concretas
– Dificulta evolução do esquema (mudanças semânticas em propriedades da superclasse afetam colunas de várias tabelas)
Luiz Carlos d´Oleron – [email protected]
Tabela por Classe concreta
•Nessa estratégia, cada mapeamento se comporta como uma classe isolada, não tendo nenhum conhecimento do resto da hierarquia
Luiz Carlos d´Oleron – [email protected]
Tabela por hierarquia de classe
• Mapeia-se a hierarquia toda a uma única tabela– Tabela inclui uma coluna para identificar a classe (tipo); esta
coluna (discriminator) não é mapeada a uma propriedade mas usada internamente pelo Hibernate
– Há colunas para todas as propriedades de todas as classes da hierarquia
– A classe raiz é mapeada da forma convencional <class>– Subclasses são mapeadas dentro de <class> como
<subclass>
Luiz Carlos d´Oleron – [email protected]
Tabela por hierarquia de classe
<hibernate-mapping> <class name=“Cliente" table=“tab_clientes" discriminator-value="BD">
<id name=“codigo"> <generator class="native"/> </id>
<discriminator column="tipo_cliente" type="string"/>
<property name=“nome"/> ...
<subclass name="ClientePessoaFisica" discriminator-value=“cfisica">
<property name=“cpf"/> ... </subclass><subclass name="ClientePessoaJuridica"
discriminator-value=“cjuridica"> <property name=“cnpj"/> ... </subclass>
... </class></hibernate-mapping>
Vantagens• Forma mais eficiente de
implementar polimorfismo• É simples de implementar,
entender e evoluir
Desvantagens• Colunas de propriedades
declaradas em subclasses precisam aceitar valores nulos (não pode ser declarada not-null)
• Adeus normalização de base de dados!
Luiz Carlos d´Oleron – [email protected]
Tabela por Subclasse
• Representa herança como relacionamentos de chave estrangeira
– Cada subclasse que declara propriedades persistentes (inclusive interfaces e classes abstratas) tem sua própria tabela
– Cada tabela possui colunas apenas para propriedades não-herdadas, e uma chave primária que é chave estrangeira da superclasse
– Criação de uma instância cria registros nas tabelas da superclasse e subclasse
– A recuperação dos dados é realizada através de um join das tabelas
– <joined-subclass> (que pode conter outros elementos <joined-subclass>) pode ser usada no lugar de ou dentro de <class>
Luiz Carlos d´Oleron – [email protected]
Tabela por Subclasse
Luiz Carlos d´Oleron – [email protected]
Tabela por Subclasse<hibernate-mapping> <class name=“Cliente" table=“tab_clientes">
<id name=“codigo"> <generator class="native"/> </id>
<property name=“nome"/> ...
<joined-subclass name="ClientePessoaFisica" table=“tab_cliente_ p_fisica”>
<key column=“codigo”/>
<property name=“cpf"/> <property name=“aniversario"/>
</ joined-subclass >
...
</class></hibernate-mapping>
Luiz Carlos d´Oleron – [email protected]
Tabela por Subclasse
• Vantagens– Modelo relacional normalizado– Evolução e restrições de integridade simples– Novas classes/tabelas criadas sem afetar
classes/tabelas existentes
• Desvantagens– Performance baixa em hierarquias complexas– Mais difícil de codificar a mão (complicado de integrar
com JDBC legado)
Luiz Carlos d´Oleron – [email protected]
Obtendo Objetos
• O modo mais simples de obter um objeto é através do método get da interface Session:
Long id = new Long(10);
Cliente cliente = (Cliente)session.get(Cliente.class, id);
Luiz Carlos d´Oleron – [email protected]
HQL e QBC• Na maioria das vezes, precisamos obter não só uma
única instância, mas necessitamos de grafos completos de Objetos
• por exemplo, podemos querer resgatar coleções de objetos que compartilham propriedades comuns
• Ou às vezes não conhecemos a chave primária de um objeto que desejamos, mas conhecemos outros valores os quais podem identificá-lo
• Nestes casos, podemos usar consultas com HQL (Hibernate Query Language) ou QBC (Query by Criteria)
Luiz Carlos d´Oleron – [email protected]
Hibernate Query Language
• HQL é um dialeto orientado a objetos
• Baseado em SQL
• Só é usado para obtenção de objetos
• Não serve para alterar, excluir ou criar objetos
Luiz Carlos d´Oleron – [email protected]
Exemplo HQL
Query q = session.createQuery(“FROM Cliente cliente WHERE cliente.name =:fname”);
q.setString(“fname”,”Luiz”);
List result = q.list();
Luiz Carlos d´Oleron – [email protected]
Exemplo HQL
Podemos usar outros recursos:
Query q = session.createQuery(“FROM Cliente cliente WHERE cliente.name LIKE :fname ORDER BY cliente.cpf DESC”);
q.setString(“fname”,”Luiz”);List result = q.list();
Luiz Carlos d´Oleron – [email protected]
Consultas e hierarquia de classe
• Polimorfismo é um mecanismo muito importante para o paradigma orientado a objetos
• Hibernate encapsula a maioria dos detalhes da transformação relacional-objeto
• Dessa forma, fazer uma consulta para tipos polimórficos é tão simples quanto para fazê-lo quando não há hierarquia de classes envolvida
• A consulta
Query q = session.createQuery("FROM Cliente c");
List<Cliente> lista = q.list();
• Retornará todas as instâncias de Cliente, indiferente de qual subclasse específica será a instância
Luiz Carlos d´Oleron – [email protected]
QBC – Query By Criteria
• Construção de consultas a partir de objetos de critério
• Permite que se especifique dinamicamente (em tempo de execução) as restrições da consulta
• Sem manipulação (perigosa) de Strings Diretamente
• Um pouco menos legível que HQL
Luiz Carlos d´Oleron – [email protected]
Exemplo QBC
Criteria criteria = session.createCriteria(Cliente.class);
Criteria.add(Expression.like(“nome”,Luiz”));
List result = criteria.list();
Luiz Carlos d´Oleron – [email protected]
Exemplo QBC
Cliente exemplo = new Cliente();
Exemplo.setNome(“Luiz”);
Criteria criteria = session.createCriteria(Cliente.class);
Criteria.add(Example.create(exemplo));
List result = criteria.list();
Luiz Carlos d´Oleron – [email protected]
Transações• Conjunto de ações que devem:
– executarem todas com sucesso;– falhar todas coletivamente;
• Uma transação deve se comportar como uma unidade atômica
• Exemplo: transação bancaria transferir
• Transações podem existir em um aplicação de apenas um usuário
• Mas é mais comum usar-se transações em ambientes concorrentes
• Para indicar que uma transação é bem sucedida, chamamos commit
• Para indicar que uma transação deve ser desfeita (provavelmente pela falha de uma das ações da transação), chamamos rollback
Luiz Carlos d´Oleron – [email protected]
Propriedades ACID
Transações devem possuir as propriedades seguintes, que são conhecidas pelo acrônimo ACID:
• A – Atomicidade• C – Consistência• I – Isolamento• D - Durabilidade
//Pseudo-código
try{
beginTransaction();
executeActions();
commit();
}catch(Exception e){
rollback();
}
Luiz Carlos d´Oleron – [email protected]
Exercício
• Refatorar os DAO´s para as entidades Cliente e Telefone, escritos anteriormente utilizando Hand-coding JDBC, desta vez utilizando a tecnologia Hibernate
• Não altere as interfaces dos DAO´s
• Mantenham as mesmas funcionalidades
Luiz Carlos d´Oleron – [email protected]
Bibliografia
• HIbernate in Action, Bauer & King, Ed. Manning
• On-line hibernate documentation, http://www.hibernate.org/5.html
• Diversos artigos em http://www.theserverside.com
• Apresentações PEC-Hibernate, Jobson Ronan