Escolar Documentos
Profissional Documentos
Cultura Documentos
conceitos e consultas
Objetivos
Aprender sobre os conceitos de persistncia relacionados ao Hibernate Aprender como recuperar os dados e efetuar consultas de maneira eficientemente no Hibernate
2012
DAW
Como Hibernate oferece um sistema transparente de persistncia, as classes no sabem de sua capacidade de persistncia Por outro lado, a aplicao que usa os objetos, os utiliza em estados diferentes
Transientes, antes de serem gravados em meio persistente Persistentes, quando esto armazenados Desligados, quando suas instncias so manipuladas sem afetar a base de dados
DAW 3
2012
Diagrama de estados
2012
DAW
Objetos transientes
Seu estado transiente (ainda no foram armazenados no banco e deixaro de existir assim que perderem sua referncia) Session.delete() sobre um objeto persistente torna-o transiente
Rollback no recupera seu estado anterior
Objetos referenciados por instncias transientes so (por default) tambm transientes Para mudar para o estado persistente preciso
Passar o objeto como argumento de um Session.save(), ou Criar a referncia a partir de uma instncia persistente
2012
DAW
Objetos persistentes
Uma instncia persistente uma instncia com uma identidade no banco de dados
Podem ser
Objeto criado com new e armazenado com Session.save() Objeto criado a partir da referncia de uma instncia persistente Objeto obtido a partir de um query no banco
Seu estado sincronizado com o banco ao fim da transao Automatic dirty checking (transparente ao usurio) usado como estratgia de atualizao eficiente de dados
DAW 6
2012
Quando a sesso fechada (Session.close()) todas as instncias ainda mantm seu estado, mas no esto mais sincronizadas com o banco
Podem ficar obsoletas se houver mudana no banco Podem mudar de estado, que no ser refletido no banco Mas, a qualquer momento, a sesso pode ser reativada, tornando o objeto persistente e sincronizando seu estado
Objetos desligados so teis para transportar o estado de objetos persistentes para outras camadas
Camada de apresentao, em substituio aos DTOs (Data Transfer Objects, tambm chamados de Value Objects)
DAW 7
2012
4) Grave o objeto
session.save(user);
5) Cometa a transao
tx.commit();
6) Feche a sesso
session.close();
DAW 8
2012
Qualquer alterao no seu estado no afeta o banco Para relig-lo pode-se usar update()
user.setPassword("secret"); // objeto desligado Session sessionTwo = sessions.openSession(); Transaction tx = sessionTwo.beginTransaction(); sessionTwo.update(user); user.setUsername("jonny"); // objeto persistente tx.commit(); sessionTwo.close();
2012
DAW
A forma mais simples de recuperar um objeto pelo identificador, usando o comando get():
Session session = sessions.openSession(); Transaction tx = session.beginTransaction(); int userID = 1234; User user = (User) session.get(User.class, new Long(userID)); tx.commit(); session.close();
2012
Uma vez que a sesso foi fechada, o objeto uma instncia desligada, e pode ser repassada para outras camadas (apresentao, por exemplo) Se o objeto no existir, a chamada get() retorna null
DAW
10
Quaisquer modificaes no seu estado sero sincronizadas com o banco de dados Hibernate automaticamente verifica e grava as mudanas ocorridas dentro de uma sesso (automatic dirty checking) As mudanas tornam-se permanentes ao cometer a transao O objeto torna-se desligado quando a sesso fecha
Session session = sessions.openSession(); Transaction tx = session.beginTransaction(); int userID = 1234; User user = (User) session.get(User.class, new Long(userID)); user.setPassword("secret"); tx.commit(); session.close();
2012 DAW 11
Para isto preciso usar o gerente de persistncia e chamar o mtodo delete() Quando a sesso terminar o objeto ser considerado um mero objeto Java transiente (cujo estado ser perdido assim que o coletor de lixo atuar)
Session session = sessions.openSession(); Transaction tx = session.beginTransaction(); int userID = 1234; User user = (User) session.get(User.class, new Long(userID)); session.delete(user); tx.commit(); session.close();
2012 DAW 12
Para tornar um objeto desligado transiente, no preciso lig-lo ou fazer update() Basta chamar delete() sobre sua instncia
Session session = sessions.openSession(); Transaction tx = session.beginTransaction(); session.delete(user); tx.commit(); session.close();
2012
DAW
13
beginTransaction()
Demarca o incio de uma transao. Retorna um objeto Transaction que deve chamar commit() ou rollback() no final da transao. Fecha e desconecta a sesso Desconecta a sesso da conexo JDBC atual sem fech-la. Obtm uma nova conexo JDBC para a sesso ou tenta conectar a uma conexo JDBC, se passada como argumento Sincroniza a camada de objetos com a camada de dados. Este mtodo chamado automaticamente quando a transao cometida.
DAW 14
close()
disconnect()
reconnect()
flush()
2012
save(Object)
saveOrUpdate(Object)
update(Object)
delete(Object instancia)
load(classe, identificador)
refresh(Object)
evict(Object)
2012
DAW
15
Recuperao de dados
Pelo identificador Navegando na rvore de objetos [ ex: usuario.getEndereco().getCidade() ] Usando HQL Usando a API Criteria Usando SQL nativo
2012
DAW
16
2012
Devolve o objeto ou um proxy para o objeto se existirem, ou causa exceo se nenhum for encontrado no banco ou no cache O proxy pode apontar para objeto que ainda ou no mais existe
DAW 17
HQL
Assemelha-se a ODMG OQL e EJB-QL mas adaptado para uso em bancos de dados SQL No uma linguagem de manipulao de dados (como SQL); no serve para inserir, remover, atualizar usada apenas para recuperao de objetos
Exemplo
Query q = session.createQuery("from User u where u.firstname = :fname"); q.setString("fname", "Max"); List result = q.list();
2012 DAW 18
HQL
2012
Pesquisas com navegao do grafo de objetos Recuperao seletiva de propriedades dos objetos selecionados (sem ter que carregar objeto inteiro) Ordenao de resultados Paginao de resultados Agregao com group by, having, e funes sobre agregados como sum, count, min e max Outer joins ao recuperar mltiplos objetos por registro Chamadas a funes SQL definidas pelo usurio Subqueries
DAW 19
QBC = Query By Criteria Queries podem ser expressos usando uma API em vez de usar HQL
Evita uso de strings Validao feita em tempo de compilao Enfoque mais orientado a objetos Mais difcil de ler ( Java e no HQL) Em HQL: from User u where u.firstname = :fname Em QBC:
Exemplo
Talvez o problema mais difcil de solucionar em ORM: acesso eficiente a dados relacionais Aplicao prefere tratar os dados como um grafo de objetos interligados por associaes
mais fcil fazer vrios pequenos queries (performance baixa) Alternativa: escrever queries para cada associao (muito complexo e pouco flexvel)
Hibernate permite especificar uma estratgia de recuperao default (no mapeamento) que pode ser sobreposta em tempo de execuo
DAW 21
2012
Estratgias de recuperao
Fetching strategies Estratgias para qualquer associao (nos metadados e em tempo de execuo)
Lazy fetching objeto associado s recuperado quando chamado Eager fetching objeto associado recuperado atravs de SQL outer join Batch fetching acessa uma coleo de objetos prdeterminada
2012
DAW
22
Lazy fetching
O restante do grafo pode ser carregado medida em que for necessrio Vai requer mais chamadas ao banco posteriormente, mas pode ser que elas no sejam necessrias Pode ser otimizada com Batch Fetching
A estratgia pode depois ser sobreposta em tempo de execuo por estratgias mais vidas
DAW 23
2012
LazyInitializationException
A forma mais simples de evit-lo, realizar tudo dentro da sesso (o commit() sincroniza os dados e evita a inconsistncia) Sabendo-se do estado do objeto, os dados podem ser recuperados em outra sesso (quando voltar a ser persistente)
s = sessions.openSession(); User u = (User) s.createQuery("from User u where u.name=?).setString(userName).list().get(0); Map permissions = u.getPermissions(); s.connection().commit(); s.close(); Integer accessLevel = (Integer) permissions.get("accounts"); // Error!
2012
DAW
24
uma soluo rpida para otimizar lazy fetching um lazy menos lazy: usurio define quantos nveis de associaes devem ser carregadas
Hibernate procura as outras instncias associadas coleo e tenta carreg-las ao mesmo tempo Pode ser melhor que lazy simples
2012
DAW
25
Eager fetching
uma soluo que ajuda a reduzir a carga sobre o banco de dados de forma mais inteligente que Batch Fetching
Permite que se especifique explicitamente quais objetos associados devem ser carregados juntos com o objeto que os referencia Os objetos associados podem ento ser retornados em nica requisio
Otimizao de performance em Hibernate freqentemente usa esse tipo de estratgia em tempo de execuo para um query em particular
DAW 26
2012
A seleo de uma estratgia de recuperao de dados default feita atravs de atributos no XML do arquivo de mapeamento. Mapeamentos de coleo diferem dependendo do tipo de associaes.
Colees e associaes de muitos para muitos comportam-se diferentemente de associaes singulares -to-one.
2012
DAW
27
Usado do lado oposto da associao O outro lado escolhe lazy fetching (ou immediate fetching por omisso) outer-join=auto (default). O comportamento lazy, se o outro lado (singular) da associao especificar, ou eager, se no especificado. outer-join=true Comportamento sempre eager para esta associao (logo diferentes associaes para mesmo objeto podem ter estratgias diferentes) outer-join=false Se o objeto tiver sido mapeado como lazy, ocorre lazy fetching, caso contrrio, immediate fetching (SQL select)
Opes
Exemplo:
<many-to-one name="item" class="Item" outer-join="true">
DAW 28
2012
Em colees
Lazy
Batched Lazy
Eager
2012
DAW
29
Consultas HQL
Os resultados de um query podem ser lidos em pginas O query abaixo l 10 pginas, a partir da primeira pgina
Query query = session.createQuery("from User u order by u.name asc"); query.setFirstResult(0); query.setMaxResults(10); List results = query.list();
Listagem de resultados
List result = session.createQuery("from User").list();
2012
DAW
30
Passagem de parmetros
Risco de segurana: basta esquecer de fechar a aspa Longos queries ficam ilegveis
O ideal passar parmetros que sero ligados ao query Parmetros podem ser passados duas formas
2012
DAW
31
Passagem de parmetros
.setString(0, searchString)
.setDate(1, minDate) .list();
2012
DAW
32
Na verdade, muitas vezes melhor que no apaream Podem ficar nos metadados e serem chamados pelo nome
Mas antes, preciso que ele seja declarado em algum arquivo de mapeamento (ex: Item.hbm.xml):
<query name="findItemsByDescription"><![CDATA[ from Item item where item.description like :description ]]></query>
2012
DAW
33
Aliases
Aliases (apelidos) so usados para que se possa ter uma referncia para acessar propriedades das instncias recuperadas
from Livro
Mas o as opcional
from Livro livro
2012
DAW
34
Queries polimrficos
BillingDetails
pois os resultados so classes concretas CreditCard BankAccount BankAccount e CreditCard Queries polimrficos podem ser feitos em qualquer classe, no apenas em classes mapeadas O query abaixo retorna todas as instncias mapeadas
from java.lang.Object
2012
DAW
35
Como em SQL, HQL define restries de um query atravs da clusula where, que suporta vrias expresses. Por exemplo, a expresso de equivalncia:
from User u where u.email = 'foo@hibernate.org
lgica ternria
HQL suporta os mesmos operadores que SQL Queries Criteria: expresses na classe Expression
No h suporte para expresses aritmticas via API (s via HQL) Comparao: =, <>, <, >, >=, <=, between, not between, in, not in Nulidade: is null, is not null Aritmticos: +, -, /, *, %, parnteses
DAW 36
Operadores do HQL:
2012
Exemplos
Bid bid where bid.amount between 1 and 10 Bid bid where bid.amount > 100 User u where u.email in ( "foo@abc.org", "bar@abc.org" ) User u where u.email is null Bid bid where ( bid.amount / 0.71 ) - 100.0 > 0.0
2012
DAW
37
O smbolo _ representa um caractere O smbolo % representa vrios caracteres HQL: from User u where u.firstname like "G%" Criteria: session.createCriteria(User.class)
Exemplos
.add(Expression.like("firstname","G%"))
2012
DAW
38
Mais HQL
Operadores lgicos: and, or, parnteses, etc. servem para argupar expresses
from User user where ( user.firstname like "G%" and user.lastname like "K%" ) or user.email in ( "foo@abc.org", "bar@abc.org" )
2012
DAW
39
2012
DAW
40
Joins
Joins (junes) so usados para combinar dados de duas ou mais tabelas relacionadas H quatro tipos de joins possveis
Inner join Left outer join Right outer join Full join ANSI: juno de tabelas atravs de propriedade comum com condio de join na clusula on Theta: produto cartesiano de tabelas com condio de join na clusula where
2012
DAW
41
Left outer join (ou left join) - Inclui tambm Itens que no tm Bids
2012
Right outer join (right join) - permite valores nulos na tabela esquerda (inclui Bids sem Itens mas no itens sem Bids) no faz sentido neste caso (lance sem item) Full join - permite valores nulos nas duas tabelas (inclui Bids que no tm Itens e itens que no tm Bids) tambm no faz sentido neste caso
DAW
42
Joins em HQL
Elas podem ser deduzidas das associaes entre objetos automaticamente Queries ficam mais simples e legveis Fetch join (outer, agressivo) na clusula from Join comum (inner, lazy) na clusula from Join theta-style (produto cartesiano) na clusula where Join por associao explcita
DAW 43
2012
Fetch join
2012
DAW
44
Freqentemente necessrio aplicar restries a tabelas combinadas com join. Isto pode ser feito atribundo um alias ao join:
from Item item join item.bids bid where item.description like '%gc% and bid.amount > 100
Em vez de uma lista de Item, retorna uma lista de Object[] Retorna uma lista de arrays {item, bid} (Se fosse um fetch join, retornaria uma lista de Item com coleo de bids inicializada) Um Item pode aparecer mltiplas vezes (uma vez para cada Bid associado)
2012
DAW
45
no tm Bid
2012
DAW
46
Clusula select
Select opcional em HQL (mas no em SQL) A ausncia do select equivale ao SQL select *
Para que o inner join do exemplo anterior devolva apenas os itens (e no uma lista de Object[] com par item-bid) pode-se usar select:
select item from Item item join item.bids bid
Exemplo
Query q = session.createQuery("select i from Item i join i.bids b"); Iterator items = q.list().iterator(); while ( items.hasNext() ) { Item item = (Item) items.next(); }
2012
Agora temos uma lista de Items contendo DAW apenas os Items que tm Bids (inner join)
47
Joins implcitos
Ocorrem em associaes *-para-um (caminho convergente) e nunca em caminhos *-para-muitos O HQL a seguir causa trs joins em SQL
from Bid bid where bid.item.category.name like 'Laptop%' and bid.item.successfulBid.amount > 100
Ou ainda
from Bid as bid join bid.item as item join item.category as cat join item.successfulBid as winningBid where cat.name like 'Laptop% and winningBid.amount > 100
2012
DAW
48
Permite recuperar todas as combinaes possveis de instncias de duas ou mais classes til em classes no associadas
Condio de join deve estar na clusula where Apenas inner-join pode ser usado neste caso
Produto cartesiano
Exemplo
Query query = session.createQuery("from User user, LogRecord log " + "where user.username = log.username") Iterator i = query.list().iterator(); while ( i.hasNext() ) { Object[] pair = (Object[]) i.next(); Condio de join User user = (User) pair[0]; LogRecord log = (LogRecord) pair[1]; }
2012
Comparao de identificadores
2012
from Item i, User u where i.seller.id = u.id and u.username = 'steve' from Item i, Bid b where i.seller.id = b.bidder.id Esta ltima sintaxe permite que se passe parmetros (tipo, o id) para comparao. DAW 50
Queries de relatrios
Instncias no so importantes, mas valores selecionados, agrupados e organizados de certas instncias Dependem de recursos de seleo e agrupamento Usa-se clusulas select e group by / having.
2012
DAW
51
Quais os dados desejados no resultado? O query abaixo seleciona trs propriedades de dois objetos
Os dados sero retornados em um vetor de Object[] de tamanho 3. Os resultados no so entidades (so valores) e no so transacionais (sero usados para leitura, apenas)
Query query = session.createQuery("select item.id, item.description, bid.amount " + "from Item item join item.bids bid where bid.amount > 100"); Iterator i = query.list().iterator(); while ( i.hasNext() ) { Object[] row = (Object[]) i.next(); Long id = (Long) row[0]; String description = (String) row[1]; BigDecimal amount = (BigDecimal) row[2]; ItemRow itemRow = new ItemRow(id, description, amount); }
2012 DAW 52
Instanciamento dinmico
Hibernate permite o instanciamento dinmico de objetos que so povoados pelos resultados do query
Evita o uso de vetores de objetos necessrio que exista uma classe e construtor previamente construda
class ItemRow { public ItemRow(Long id, String description, BigDecimal amount) {...} ... }
Query query = session.createQuery( "select new ItemRow(item.id, item.description, bid.amount)" + "from Item item join item.bids bid where bid.amount > 100"); Iterator i = query.list().iterator(); while ( i.hasNext() ) { ItemRow row = (ItemRow) i.next(); // ... fazer alguma coisa }
2012 DAW 53
Distinct
Com o uso da clusula select, os resultados de um query no mais tem garantia de serem distintos A seguinte query pode retornar Items repetidos
select item.description from Item item
2012
DAW
54
Funes agregadas
Integer count = (Integer) session.createQuery("select count(*) from Item").uniqueResult(); BigDecimal sum = (BigDecimal) session.createQuery("select sum(item.successfulBid.amount) " +"from Item item").uniqueResult(); BigDecimal[] minmax = (BigDecimal[]) session.createQuery("select min(bid.amount), max(bid.amount) +"from Bid bid where bid.item.id = 1") .uniqueResult(); BigDecimal min = minmax[0]; BigDecimal max = minmax[1];
2012
DAW
55
Agrupamento
Se houver funes agregadas no select, no pode haver seleo de outros elementos, a menos que haja uma clusula group by
select bid.item.id, count(bid), avg(bid.amount) from Bid bid where bid.item.successfulBid is null group by bid.item.id select bidItem.id, count(bid), avg(bid.amount) from Bid bid join bid.item bidItem where bidItem.successfulBid is null group by bidItem.id select item.id, count(bid), avg(bid.amount) from Item item fetch join item.bids bid where item.successfulBid is null group by item.id
2012 DAW
Um fetch (outer) join; o agrupamento teve que ser feito usando item.id
56
Grupos requerem o uso de pelo menos dois aliases no select (a funo e a propriedade de agrupamento) Sempre que a clusula select tem mltiplos aliases, o Hibernate devolve o resultado como (tuplas)vetores de Object
Chato de manipular; inseguro quanto ao tipo Ideal usar select new e instanciar objetos dinamicamente
2012
DAW
57
UFA
...agora acabou!
2012
DAW
58