Você está na página 1de 51

Hibernate

Java avanado PCC Jobson Ronan {jrjs@cin.ufpe.br} Guilherme Kelly {gkmo@cin.ufpe.br}

O que ?
Z

Hibernate uma moderna soluo de mapeamento objeto-realcional(ORM)


Persistncia tranparente (POJO/Java Beans) X Lazy Fetching X Uso de uma Cache X Trs estratgias para o mapeamento de heranas
X

O que ?

Pra que transparncia?


Z

Persistncia sem impacto no cdigo dos objetos de negcio Qualquer classe pode ser uma classe persistente sem ser necessrio implementar nenhuma classe ou interface Classes persistentes podem ser usadas fora do contexto de persistncia (ex Testes) Total portabilidade sem dependncias

Problemas dos BDRs


Z

Modelagem
No h polimorfismo X No h herana
X

Lgica de negcio
X

Stored procedures -> perca de portabilidade

Vantagens dos RDBs


Z

Trabalhar com grandes quantidades de dados Trabalhar com conjuntos de dados Compartilhamento
X X X X

Busca, ordenao

Z Z

Junes e agregaes

Integridade
X X

Concorrncia (Transaes) Muitas aplicaes Restries (Constraints) Isolao de transaes

Obviamente, ainda precisamos dos RDBs

Objetivo
Z

Aproveitar-se das vantagens oferecidas pelos RDBs Isso sem perder a orientao a objetos

Objetivo Real
Ter menos trabalho Z Ter um DBA feliz
Z

Em prtica
Z

Locadora em partes...

Em prtica
Z

Classe Persistente
X X

package br.org.citi.pec.locadora; public class Filme { private int codigo; private String nome; public int getCodigo() { return codigo; } private void setCodigo(int codigo) { this.codigo = codigo; } public String getNome() { return nome; } private void setNome(int nome) { this.nome = nome; } }

Construtor default Pares de Get s e Set s Uma propriedade identificadora

Em prtica
Z

Mapeamento XML
Metadado legvel X Mapeamento de tabelas e colunas
X
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="br.org.citi.pec.locadora.Filme" table="filmes"> <id name="codigo" column="filme_id"> <generator class="native" /> </id> <property name="nome" column="nome"/> </class> </hibernate-mapping>

Em prtica
Z

Salvando um objeto
Session session = sessionFactory.openSession(); Transaction tx = s.beginTransaction(); Filme filme = new Filme(); filme.setNome(novoNome); session.save(filme); tx.commit(); session.close();

Tambm pode ser usado saveOrUpdate

Em prtica
Z

Carregando um objeto
Session session = sessionFactory.openSession(); (Filme) session.load(Filme.class, new Integer(filmeId); session.close(); Filme filme =

No use load para determinar se um objeto existe (uma exceo lanada neste caso) Use get. Este retorna null caso o objeto no exista

Em prtica
Z

Removendo um objeto
Session session = sessionFactory.openSession(); Transaction tx = s.beginTransaction(); Filme filme = (Filme) session.get(Filme.class, new Integer(filmeId);

session.delete(filme); tx.commit(); session.close();

Em prtica
Z

Atualizando um objeto (Dirty Checking)


X

Obetendo um filme e alterando seu nome


Session session = sessionFactory.openSession(); Transaction tx = s.beginTransaction(); Filme filme = (Filme) session.get(Filme.class, new Integer(filmeId); filme.setNome(novoNome); tx.commit(); session.close();

No necessrio uma chamada explicita do update

Estado dos Objetos


Z

Alguns conceitos sobre objetos


X

Transiente.
Nunca persistido. No associado a nenhuma sesso (Session)

Persistente
Associado a uma nica sesso

Desacoplado (Detached)
J persistido, mas no associado a nenhuma sesso

Estado dos Objetos


Z

Dirty Checking s funciona em objetos persistentes


X

Use update para objetos desacoplados

Mais prtica
Z

Melhorando nosso modelo...

Mais prtica
Z

Classes persistentes
package br.org.citi.pec.locadora; public class Cliente { private String login; private String CPF; private String nome; private Set locacoes = new Hashset(); //... Gets e Sets }

Mais prtica
Z

Classes persistentes
package br.org.citi.pec.locadora; public class Locacao { private int id; private Filme filme; private Cliente cliente; private Date dataLocacao; private Date datadevolucao; //... Gets e Sets }

Mais prtica
Z

XML...
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="br.org.citi.pec.locadora.Cliente" table="Clientes"> <id name="login"/> <property name="nome" /> <property name="cpf" /> <set name="locacoes"> <key column="cliente_login" /> <one-to-many class="br.org.citi.pec.locadora.Locacao"/> </set> </class> </hibernate-mapping>

Mais prtica
Z

XML...
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="br.org.citi.pec.locadora.Locacao" table="Locacoes"> <id name="id"> <generator class="native" /> </id> <property name="dataLocacao" /> <property name="dataDevolucao" /> <many-to-one name="cliente" class="br.org.citi.pec.locadora.Cliente" column="cliente_login"/> <many-to-one name="filme" class="br.org.citi.pec.locadora.Filme" column="filme_id"/> </class> </hibernate-mapping>

Mais prtica
Z

Persistncia transitiva
Locacao locacao = new Locacao(); Locacao.setDataLocacao(new Date()); Session session = sessionFactory.openSession(); Transaction tx = s.beginTransaction(); Filme filme = (Filme) session.get(Filme.class, new Integer(filmeId); Cliente cliente = (Cliente) session.get(Cliente.class, login); locacao.setCliente(cliente); locacao.setFilme(filme); cliente.getLocacoes().add(locacao); tx.commit(); session.close();

Otimizando
Z

Como as colees so carregadas


Lazy fetching (Default) X Eager (Outer Join) fetching
X

Indicado nos XML, ou na prpria consulta

Lazy fetching
Z

SQL escondido:
Cliente cliente = (Cliente) session.get(Cliente.class, login); SELECT FROM CLIENTES C WHERE C.LOGIN = ? Iterator cliente = cliente.getLocacoes().iterate(); SELECT FROM LOCACOES L WHERE L.LOGIN_CLIENTE = ? Filme filme = locacao.getFilme(); SELECT FROM FILMES F WHERE F.FILME_ID = ?

Outer join fetching


Z

SQL escondido:
Cliente cliente = (Cliente) session.get(Cliente.class, login); SELECT FROM CLIENTES C
LEFT OUTER JOIN LOCACOES L ON L.LOGIN_CLIENTE = C.LOGIN LEFT OUTER JOIN FILME F ON L.FILME_ID = F.FILME_ID

WHERE C.LOGIN = ?

Herana
Z

Estratgias para o mapeamento de herana


Uma tabela por hierarquia de classes X Uma tabela por subclasse X Uma tabela por classe concreta
X

Herana
Z

Uma tabela por subclasse


<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="br.org.citi.pec.locadora.Cliente" table="Clientes"> <id name="login" column="LOGIN" /> ... <joined-subclass name="br.org.citi.pec.locadora.ClienteEspecial" table="ClientesEspeciais"> <key column="LOGIN" /> <property ... /> ... </joined-subclass> </class> </hibernate-mapping>

Otimizando
Z

Como otimizar?
Minimizando a leitura de linhas das tabelas X Minimizando a quantidade de comandos SQLs enviados
X

Otimizando
Z

Minimizando a leitura de linhas das tabelas


X

Usar lazy fecthing

Minimizando a quantidade de comandos SQLs enviados


X

Usar outer join fetching

Otimizando
Z

Problemas
X

Usar lazy fecthing


Problema dos n+1 selects (muitos selects!)

Usar outer join fetching


Problema do produto cartesiano (grandes conjuntos de dados)

Otimizando
Z

Solucionando problemas de otimizao


Stratgia de Fecthing definida em tempo de execuo X Batch Fecthing X Utilizar um cache de segundo nvel
X

Consultas
Z

HIbernate Query Lanuage


X

Permite que se expresse quase tudo o que se precisa expressar em SQL, porm mais orientado a objetos

Trs maneiras de se fazer consultas no Hibernate


HQL X Criteria X SQL nativo
X

HQL
Z

Tornar SQL orientado a objetos


X X X

Classes e propriedades ao invs de Tabelas e colunas Polimorfismo Associaes Joins Projees Funes agregadas e agrupamento Ordenao SubQueries Chamadas a funes SQL

Total suporte a operaes relacionais


X X X X X X

HQL
Z

A consulta mais simples possivel HQL


from Filme
X

Devolva todos os filmes

List filmes = session.createQuery(from Filme).list();


Z

As consultas podem ser paginadas

Query query = session.createQuery(from Filme); query.setFirstResult(20); query.setMaxResults(30); List filmes = query.list();

HQL
Z

Uma consulta com ordenao


from Locacao l order by l.dataLocacao desc

Caso esteja interessado em um nico resultado

Query query = session.createQuery( from Locacao l order by l.dataLocacao desc); Locacao locacao = query.uniqueResult();

HQL
Z

Uma consulta com joins


select c from Cliente c left join [fetch] c.locacaoes l where l.dataLocacao > 3/5/2005
X

Todos os clientes com suas locaes efetuadas aps o dia 3

Definio da estratgia de fetching


X X

Com o fetch: Colees j inicializadas Sem o fetch: lazy collections

HQL
Z Z

HQL suporta os mesmos operadores que SQL Operadores do HQL:


X

Comparao: =, <>, <, >, >=, <=, between, not between, in, not in Nulidade: is null, is not null Aritmticos: +, -, /, *, %, parnteses

X X

O operador like funciona da mesma forma que SQL Pode usar funes SQL se o banco suportar

HQL
Z

Projees + funes agregadas (Report Queries)


select c.nome, count(l) from Cliente c, c.locacoes l where l.dataLocacao between(:inicio, :fim) group by c.nome order by count(l)

HQL
Z Z

Os dados da consulta anterior sero retornados em List de Object[] Consulta comum para a realizao de relatrios Podemos tornar o processo mais elegante
List list = session.createQuery( select new ClienteReportRow(c.nome, count(l)) + from Cliente c, c.locacoes l + where l.dataLocacao between(:inicio, :fim) + group by c.nome + order by count(l)). setDate(inicion, inicio). setDate(fim, fim).list();

HQL
Dessa evitasse o uso de vetores de objetos Z necessrio que exista uma classe e um construtor previamente definido
Z

HQL
Z

Consultas no precisam aparecer no cdigo


X X

Na verdade, muitas vezes melhor que no apaream Podem ficar nos metadados e serem chamadas pelo nome

Usa-se o mtodo getNamedQuery()


List clientes = session.getNamedQuery(findClienteByName) .setString(nome, nome),list()

Mas antes, ela precisa ser declarada em algum arquivo de mapeamento


<query name=findClienteByName><![CDATA[ from Cliente c where c.nome like :nome]] </query>

Modelagem OO
Z

Mais classes que tabelas


X

Classse Endereco
Propriedade: rua, numero, bairro...

Rua, numero, bairro,... Colunas da tabela cliente

<class name="br.org.citi.pec.locadora.Cliente" table="Clientes"> <component name=endereco class=br.org.citi.pec.locadora.Endereco> <property name=rua column=rua/> <property name=numero column=numero/> </component> </class>

O que mais?
Z

Hibernate tambm d suporte a tipos de dados definidos pelo usurio Z Interceptadores e EventListeners Z Filtros Z Definies explicitas dos SQLs de insert e update e load (hibernate 3) ...e mais um pouco!

Sobre configurao
Z

Como obter um SessionFactory?


Programaticamente X Por arquivo XML
X

Configurao programtica
Configuration cfg = new Configuration() .setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect"). .setProperty("hibernate.connection.driver_class", "org.hsqldb.jdbcDriver") .setProperty("hibernate.connection.url", "jdbc:hsqldb:file:hsqldb/data") .setProperty("hibernate.connection.username", "sa") .setProperty("hibernate.connection.password", "") .addClass(Filme.class) .addClass(Cliente.class) .addClass(Locacao.class); SessionFactory sessionFactory = cfg.buildSessionFactory();

Configurao XML
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.dialect"> org.hibernate.dialect.MySQLDialect</property> <property name="hibernate.connection.driver_class"> org.gjt.mm.mysql.Driver</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">ftBBvEdiC</property> <property name="hibernate.connection.url"> jdbc:mysql://localhost/lockar</property> <mapping class="br.org.citi.pec.locadora.Filme"/> <mapping class="br.org.citi.pec.locadora.Locacao"/> <mapping class="br.org.citi.pec.locadora.Cliente"/> </session-factory> </hibernate-configuration>

Configuration cfg = new Configuration().configure(); SessionFactory sessionFactory = cfg.buildSessionFactory();

Extras
Z

Hbm2ddl (tool)
Gera o schema do BD a partir das XML de mapeamentos X Usado por linha de comando ou pelo ant
X

<target name="schemaexport"> <taskdef name="schemaexport" classname="org.hibernate.tool.hbm2ddl.SchemaExportTask" classpathref="project.lib.classpath" /> <schemaexport properties="hibernate.properties" quiet="yes" text="yes" drop="no" delimiter=";" output="${basedir}/sql/schema-export.sql"> <fileset dir="src"> <include name="**/*.hbm.xml" /> </fileset> </schemaexport> </target>

Exerccios
Z

Ampliar nosso modelo

Exerccios
Z Z Z

Crie as classes (JavaBeans/POJO) Crie os XML de mapeamentos Implemente as consultas e mtodos para retornar
X X

Todos os filmes locados durante um determinado ms Listagem contendo nome do filme, mdia das avaliaes, e total de comentrios para todos os filmes Listagem contendo nome do filme mais o nmero de cpias de VHS e de DVD desse filme Listagem contendo nome do filme mais o nmero de cpias de VHS e de DVD desse filme locadas em um determinado ms Todos os clientes que locaram mais de 5 VHS no ultimo ms (Com as devidas locaes carregadas)

Você também pode gostar