Este documento apresenta três pontos principais:
1. A missão do curso é apresentar, motivar e exercitar mecanismos de persistência em Java com foco no framework Hibernate.
2. As metodologias incluem exposição teórica, discussão e exercícios práticos de projeto e modelagem em laboratório.
3. O curso não cobre conceitos gerais de Java e J2EE, e também não é para iniciantes em acesso a banco de dados ou em programação Java.
Persistência com Hibernate - Curso sobre o framework Hibernate
1. Hibernate
Persistência com Hibernate
Régis Melo
@regismelo
@regismelo 1
2. Hibernate
Missão
Apresentar, motivar e exercitar mecanismos
de persistência em Java, com enfoque no
framework Hibernate.
@regismelo 2
3. Hibernate
Metodologias
• Exposição e discussão teóricas;
• Exercícios práticos de projeto e modelagem em
laboratório.
@regismelo 3
4. Hibernate
O que esse curso não cobre ou não é?
Não Cobre:
• Conceitos gerais de Java e da plataforma J2SE;
• Conceitos gerais da plataforma J2EE – Servlets e JSP;
Não é:
• O primeiro curso para aprender como acessar bancos de
dados relacionais a partir de Java;
• Esse curso não é para você se você não sabe aonde
colocar aquele arquivo “.class” que acabou de compilar.
@regismelo 4
5. Hibernate
Antes de iniciar…
Vamos nos apresentar
• Nome;
• Empresa;
• Experiência com programação;
• Razões de estar fazendo esse treinamento;
• Expectativas desse curso.
@regismelo 5
7. Hibernate
Prepara os teus trabalhos de fora, apronta bem o
teu campo; e depois edifica a tua casa.
Provérbios 24:27
@regismelo 7
8. Hibernate
Módulo I
E no princípio, era o JDBC…
@regismelo 8
9. Hibernate
E no princípio, era o JDBC…
• Existem diversas tecnologias de acesso a banco de
dados utilizando Java;
• A mais simples dela, com certeza é o JDBC;
• Relembrando JDBC…
@regismelo 9
10. Hibernate
O que é JDBC?
• É uma API Java para acesso a banco de dados
utilizando SQL;
• Permite a independência de banco de dados;
• A forma de acesso a um banco de dados é exatamente
igual a outro banco de dados.
• A independência entre bancos de dados pode ser
prejudicada pela forma como você utiliza SQL
(comandos SQL proprietários).
@regismelo 10
11. Hibernate
O que JDBC faz?
De maneira simplificada JDBC faz seis coisas:
1 – Estabelece conexão com o banco de dados.
2 – Executa consultas.
3 – Recebe o conjunto de resultados das consultas.
4 – Executa stored procedures.
5 – Obtém informações sobre o banco de dados, tabelas,
índices, visões, e stored procedures.
6 – Gerencia transações.
@regismelo 11
12. Hibernate
API JDBC
• A API JDBC está definida no pacote java.sql – a maior
parte da API são interfaces;
• O J2SE – Java 2 Standard Edition disponibiliza uma única
implementação JDBC chamada JDBC-ODBC Bridge (que
faz a ponte entre JDBC e ODBC);
• Para acessar o seu banco de dados utilizando JDBC você
deverá obter um driver do fornecedor do SGBD (o caso
mais comum), comprar de uma empresa fornecedora de
drivers ou usar produtos de código aberto.
@regismelo 12
14. Hibernate
Tipos de driver JDBC
• Existem 4 tipos de drivers JDBC:
– Tipo 1 JDBC-ODBC Bridge;
– Tipo 2 Java Nativo
– Tipo 3 Gateway
– Tipo 4 All Java Driver
@regismelo 14
15. Hibernate
Tipo 1 - Ponte
• Convertem chamadas JDBC em chamadas ODBC e as
envia ao driver ODBC;
• Possibilitam o uso indireto de drivers ODBC;
• Necessidade de configurar o ODBC;
• Mais apropriado para uma rede corporativa ou para
aplicações usando arquitetura em três camadas;
Ex: sun jdbc-odbc bridge.
@regismelo 15
16. Hibernate
Tipo 1 - Ponte
• JDBC-ODBC BRIDGE + ODBC DRIVER
Aplicação
JAVA Dados
API JDBC-ODBC API Driver
JDBC Bridge ODBC ODBC
@regismelo 16
17. Hibernate
Tipo 2 – Java Nativo
• Convertem chamadas JDBC em chamadas nativas do
banco e comunicam-se diretamente com o SGBD;
• Apresentam ganhos de performance;
• O cliente do banco de dados é necessário;
• Menor portabilidade.
Ex: IBM DB2.
@regismelo 17
18. Hibernate
Tipo 2 – Java Nativo
• Java / Nativo
Aplicação
JAVA Dados
API
API Driver
Nativa
JDBC JDBC
SGBD
@regismelo 18
19. Hibernate
Tipo 3 – Gateway
• Convertem chamadas JDBC em um protocolo de rede
independente do SGBD e comunicam-se com um
gateway que traduz estas requisições para o protocolo
específico do SGBD;
Ex: borland datagateway.
@regismelo 19
20. Hibernate
Tipo 3 – Gateway
• Servidor de acesso intermediário
Aplicação
JAVA Dados
JDBC
API Driver
Driver JDBC Driver
JDBC Nativo
Server
@regismelo 20
21. Hibernate
Tipo 4 – All Java Driver
• Convertem chamadas JDBC para um protocolo de rede
usado diretamente pelo SGBD;
• São geralmente específicos para determinada base de
dados;
Ex: Sybase, SQL Server, Oracle.
@regismelo 21
22. Hibernate
Tipo 4 – All Java Driver
• All Java Driver
Aplicação API
Driver JDBC Dados
JAVA JDBC
@regismelo 22
24. Hibernate
Abrindo uma conexão com o BD
• Para abrir uma conexão com o banco de dados,
precisamos primeiro de um driver JDBC;
• Utilizaremos o driver do Microsoft SQL Server nos
próximos exemplos;
• O driver JDBC do MSSQL pode ser baixado no site
www.microsoft.com/sql;
• É free e é um driver tipo 4;
• Três arquivos são necessários:
– msbase.jar
– mssqlserver.jar
– msutil.jar
@regismelo 24
25. Hibernate
Abrindo uma conexão com o BD
• O nosso primeiro passo é registrar o driver JDBC;
• O driver do SQL Server está disponível em
“mssqlserver.jar”, “msbase.jar” e “msutil.jar”;
• Você deverá consultar a documentação do seu
fornecedor para saber qual é a classe e pacote do driver
JDBC.
Class.forName(
"com.microsoft.jdbc.sqlserver.SQLServerDriver");
@regismelo 25
26. Hibernate
Abrindo uma conexão com o BD
• O segundo passo é abrir a conexão com o
banco de dados;
• Utilize a classe DriverManager para fazer isso;
• Os parâmetros passados para o método
getConnection variam de driver para driver –
consulte a documentação do seu driver.
...
java.sql.Connection conn;
conn = DriverManager.getConnection(
"jdbc:microsoft:sqlserver://localhost:1433
;DatabaseName=<<nome do seu database>>;
SelectMethod=cursor");
@regismelo 26
27. Hibernate
Executando uma consulta
• Com a conexão com o banco de dados obtida,
podemos executar consultas SQL:
...
java.sql.Connection conn;
conn = DriverManager.getConnection(
"jdbc:microsoft:sqlserver://localhost:1433
;DatabaseName=dbExemplo;SelectMethod=cursor");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery( “Select * from
authors” );
@regismelo 27
28. Hibernate
Executando uma consulta
• O objeto ResultSet guarda os dados retornados
pela consulta:
...
Resultset rs = stmt.executeQuery( “Select * from contas”
);
while ( rs.next() ) {
String cdConta = rs.getString( “codigo” );
double sdConta = rs.getDouble( “saldo” );
}
@regismelo 28
29. Hibernate
Executando uma consulta
• E ao final de tudo, devemos fechar o statement
e a conexão.
...
stmt.close();
conn.close();
@regismelo 29
30. Hibernate
Executando uma consulta
Statement stmt; ResultSet rs;
try {
Class.forName( "com.mysql.jdbc.Driver");
java.sql.Connection conn;
conn = DriverManager.getConnection(
"jdbc:mysql://localhost/test?user=root&password=");
stmt = conn.createStatement();
rs = stmt.executeQuery( “Select * from contas” );
while ( rs.next() ) {
String cdConta = rs.getString( “codigo” );
double sdConta = rs.getDouble( “saldo” );
}
}
catch (ClassNotFoundException e){System.out.println(e);// Trate o
erro! }
catch (SQLException e ) {System.out.println(e); // Trate o erro! }
finally { // Feche o statment e a conexão com o BD }
@regismelo 30
31. Hibernate
API JDBC
• DriverManager Utilizada para obter a
conexão com o banco de dados
• Principais métodos:
– Connection getConnection( String url )
• Obtém uma conexão com o banco de dados;
– Connection getConnection ( String url, String
user, String pass )
• Obtém uma conexão com o BD passando usuário e
senha;
@regismelo 31
32. Hibernate
API JDBC
• Connection Representa uma conexão com o BD
• Principais métodos:
– Statement createStatement()
• Cria um statement, que representa um comando SQL a ser
enviado;
– PreparedStatement prepareStatement()
• Cria um statement pré-compilado (veja definições adiante)
– setAutoCommit( boolean )
• Indica se deverá se trabalhar no modo AutoCommit;
– commit
• Confirma as alteração no banco de dados
– rollback
• Desfaz transações no BD
– close
• Fecha a conexão com o banco de dados
@regismelo 32
33. Hibernate
API JDBC
• Statement Representa um comando SQL;
• Principais métodos:
– ResultSet executeQuery( String )
• Executa um comando SQL e obtém o resultado;
– executeUpdate( String )
• Executa um comando SQL que não retorna resultado (um update,
delete ou insert);
– addBatch( String )
• Adiciona um comando SQL em um bloco;
– executeBatch()
• Executa comandos adicionados com addBatch
– getConnection
• Retorna a conexão associada ao statement
– setMaxRows( int )
• Especifica a quantidade de linhas máxima retornada.
@regismelo 33
34. Hibernate
API JDBC
• Exemplo de um executeUpdate
String sql = “update conta set saldo = 1000“;
Statement stmt = conn.createStatement( sql );
stmt.executeUpdate();
throws SQLException
@regismelo 34
35. Hibernate
API JDBC
• PreparedStatement Representa um comando
SQL pré-compilado;
• Principais métodos:
– ResultSet executeQuery( String )
• Executa um comando SQL e obtém o resultado;
– executeUpdate( String )
• Executa um comando SQL que não retorna resultado (um
update, delete ou insert);
– setXXXX( indice, valor )
• Passa um parâmetro para o result set, onde XXXX é o tipo
do parâmetro (setInt, setDate, setLong, setString, ... );
@regismelo 35
36. Hibernate
API JDBC
• PreparedStatement é útil quando você irá submeter o mesmo
comando diversas vezes pois o banco só faz o parse da
query uma vez.
String sql = "select * from conta where codigo = ? "
PreparedStatement stmt =
conn.prepareStatement( sql );
stmt.setInt( 1, 50 );
ResultSet rs = stmt.executeQuery();
while ( rs.next() )
{
System.out.println( rs.getString(1) );
}
@regismelo 36
37. Hibernate
API JDBC
• ResultSet Representa o resultado de uma consulta;
• Principais métodos:
– close
• Fecha o resultset
– ResultSetMetaData getMetaData()
• Retorna informações sobre as colunas do result set.
– getXXXX( String ) / getXXXX( int )
• Retorna a informação de uma coluna, onde XXXX representa o tipo
da coluna (getInt, getDate, getLong, getString, ... ).
@regismelo 37
38. Hibernate
ResultSet e os métodos get
@regismelo 38
39. Hibernate
Exercício
• No banco de dados disponibilizado existe uma
tabela chamada Autores (ver modelo de dados no
final do material);
• Faça uma classe Java que inclui novos autores
nessa tabela usando Statement e
PreparedStatement – qual a diferença entre o
código gerado para os dois?
(Dica: Use o profiler do SQL Server para ver os
comandos gerados pelo JDBC)
30 minutos
@regismelo 39
40. Hibernate
Para saber mais
• http://java.sun.com/docs/books/tutorial/jdbc/index
.html
@regismelo 40
41. Hibernate
Módulo II
Pool de conexões
@regismelo 41
42. Hibernate
Entendendo o problema...
• Em aplicações cliente/servidor, tipicamente temos,
para cada cliente uma conexão com o banco de
dados...
@regismelo 42
43. Hibernate
Entendendo o problema...
• Manter uma conexão para cada cliente pode gerar
carga desnecessário do servidor de banco de
dados;
• Boa parte do tempo a conexão não é necessária
no cliente;
• Cada conexão consome recursos no banco de
dados...
@regismelo 43
44. Hibernate
Pool de Conexões
• O ideal é que os clientes “compartilhassem” as
conexões com o banco de dados;
• Poderíamos abrir um determinado número de
conexões e deixá-las em um “pool”;
• Cada vez que uma conexão for necessária, ela
será obtida desse pool.
@regismelo 44
45. Hibernate
Pool de Conexões
<<servlet>> <<servlet>> <<servlet>> <<servlet>>
Cliente X Y Z
Container
Pool de Conexões
<<Conexão 1>> << Conexão 2 >> <<Conexão 3>> << Conexão 4 >>
@regismelo 45
46. Hibernate
Pool de Conexões
• Cada cliente (Servlet, JSP ou qualquer outro tipo),
quando precisa de uma conexão, solicita ao
container;
• O container:
– Verifica se existem conexões no pool;
– Disponibiliza uma conexão para o cliente
• O cliente:
– Usa a conexão;
– E ao final, devolve-a para o pool.
@regismelo 46
47. Hibernate
Pool de Conexões
Container
<<servlet>> Connection Pool
Solicita uma conexão
Cliente Existe conexões
disponíveis no pool?
Não
Sim Obtém uma nova
conexão
Devolve conexão
com o Banco de dados
@regismelo 47
48. Hibernate
Pool de Conexões
• É ainda função do pool de conexões saber
quando o pool deve crescer ou diminuir;
• Usualmente isso é configurável pelo administrador
do sistema;
• Algo como
– Número máximo de conexões;
– Número mínimo de conexões.
@regismelo 48
49. Hibernate
Pool de Conexões no TomCat
@regismelo 49
50. Hibernate
Pool de Conexões no TomCat
• O pool de conexões no TomCat é implementado
por um projeto chamado Jakarta DBCP;
• DBCP = Database Connection Pooling;
• Vamos configurar o pool de conexões para
nossa aplicação chamada HTeste...
Demo Configurando Pool de Conexões...
http://www.softsite.com.br/cursos/hibernate/demo/Configurando_Pool_de_Conexoes_TomCat5_viewlet_swf.html
@regismelo 50
51. Hibernate
Pool de Conexões no TomCat
Nome da conexão JNDI
String DataSource
Específico do Driver JDBC
Nome da Classe JDBC
Quantidade máxima de
conexões abertas pelo
pool
Quantidade máxima de
conexões não
utilizadas (idle)
Tempo máximo que o
cliente irá esperar por
uma conexão até uma Query de validação – usada para
exceção ser disparada verificar se a conexão ainda
é válida
@regismelo 51
52. Hibernate
Pool de Conexões no TomCat
• Configurações para o SQL Server, usando o driver
JDBC tipo 4 da Microsoft:
– JNDI name:
O padrão especifica iniciar com “jdbc/”
– Data Source URL:
jdbc:microsoft:sqlserver://<serverName>:1433;DatabaseN
ame=<dbName>;SelectMethod=cursor
– JDBC Driver Class:
com.microsoft.jdbc.sqlserver.SQLServerDriver
– User Name:
Nome do usuário que você irá se conectar no banco de
dados (“sa”, no SQL Server = System Administrator).
@regismelo 52
53. Hibernate
Pool de Conexões no TomCat
• Configurações para o SQL Server, usando o driver
JDBC tipo 4 da Microsoft:
– Password:
Senha. Na instalação default, vazio
– Max. Active Connections:
Número máximo de conexões com o banco de dados que
o pool irá gerenciar. Em desenvolvimento, deixe esse
valor bem pequeno.
– Max. Idle Connections:
Número de conexões que sempre deverá estar aberta. Em
desenvolvimento, deixe esse valor bem pequeno.
@regismelo 53
54. Hibernate
Pool de Conexões no TomCat
• Configurações para o SQL Server, usando o driver
JDBC tipo 4 da Microsoft:
– Max. Wait for Connection:
Tempo máximo em milisegundos que o container irá
esperar para uma conexão ser disponibilizada (quando
não existir nenhuma conexão livre). Passado esse tempo
é disparada uma exceção.
– Validation Query:
Uma query válida que pode ser usada pelo pool para
validar conexões antes delas serem retornadas para a
aplicação. Se especificado, deverá retornar pelo menos
uma linha (usualmente uma query simples e rápida).
@regismelo 54
55. Hibernate
Pool de Conexões no TomCat
• Após criado o pool de conexões no TomCat,
copie os arquivos “jar” para
<tomcat>/common/lib;
• No caso do SQL Server:
– msbase.jar
– mssqlserver.jar
– msutil.jar
@regismelo 55
56. Hibernate
Obtendo uma conexão do pool...
• O pool de conexões que acabamos de configurar fica
disponível no TomCat através de JNDI;
• JNDI = Java Naming and Directory Interface;
• Uma API para serviços de diretório;
“The JNDI is part of the Java platform, providing
applications based on Java technology with a unified
interface to multiple naming and directory services. You
can build powerful and portable directory-enabled
applications using this industry standard.”
http://java.sun.com/products/jndi/
@regismelo 56
57. Hibernate
Obtendo uma conexão do pool...
InitialContext iniContext;
try {
iniContext = new InitialContext();
DataSource ds =
(DataSource)iniContext.lookup("java:comp/env/jdbc/quickstart");
Connection conn = ds.getConnection();
out.println("Sucesso!");
} catch (NamingException e) {
out.println(e);
e.printStackTrace();
} catch (SQLException e) { InitialContext é configurado no momento em que é feito
out.println(e); o deploy da aplicação e se torna
e.printStackTrace(); disponível (para leitura).
} Todas as entradas configuradas ficam disponíveis
em “java:comp/env” no namespace JNDI.
@regismelo 57
58. Hibernate
Exercício
• Altere o exercicío anterior, implementando um
servlet, de forma que o acesso ao banco de
dados seja feito usando uma conexão no pool de
conexões.
30 minutos
@regismelo 58
59. Hibernate
Para saber mais
• http://jakarta.apache.org/tomcat/tomcat-5.0-doc/jndi-r
@regismelo 59
60. Hibernate
Módulo III
Data Access Objects
@regismelo 60
61. Hibernate
Data Acess Object
• DAO é um dos padrões do livro “Core J2EE
Design Patterns”;
• É usado para “isolar” o acesso a persistência, pois
a persistência pode variar enormemente (JDBC,
Hibernate, SGBD relacionais, SGBD O.O., etc);
• Use DAO para não expor o seu cliente a forma
como seus dados são acessados!
@regismelo 61
62. Hibernate
Quando usar DAO?
• Componentes como BMP entity beans, session beans ou
servlets/JSP precisam recuperar e armazenar informações de
locais persistentes e outras fontes (bancos legados, LDAP,
etc);
• A API da camada de persistência pode variar dependendo do
fornecedor (JDBC, Hibernate, JDO);
• A portabilidade dos componentes (usualmente componentes
de negócio) é diretamente afetada quando um acesso de
forma específica a uma API é incluída nesses componentes;
• Componentes precisam ser transparentes a forma como a
persistência armazena os dados – isso facilita a migração
para fornecedores diferentes, tipos de armazenamentos
diferentes e tipos de fontes de dados diferentes.
http://java.sun.com/j2ee/patterns/DataAccessObject.html
@regismelo 62
65. Hibernate
DAO e Abstract Factory
• No caso da implementação do DAO é útil usar um Abstract
Factory para instanciar as classes.
@regismelo 65
66. Hibernate
DAO e Abstract Factory
public interface DAO { }
____________________________________________________________________________
public interface AutorDAO implements DAO {
public List getAutores();
public void addAutor( int cdAutor , String nmAutor, String dsFone, boolean
idContratado );
}
____________________________________________________________________________
public class AutorDAOJDBC implements AutorDAO
{ ... }
@regismelo 66
67. Hibernate
DAO e Abstract Factory
public class DAOFactory {
public DAO getInstance( Object connection, Class c) throws DAOException
{
try {
Class cc = c.getClassLoader().loadClass(c.getName() + "JDBC" );
Constructor ctor = cc. getConstructor(new Class[] { Object.class });
return (DAO)ctor.newInstance( new Object[] { connection } );
}
catch ( Exception e ) {
throw new DAOException( e );
}
}
Todas as classes concretas,
}
deverão se chamar *JDBC
@regismelo 67
68. Hibernate
DAO e Abstract Factory
public class DAOException extends Exception {
public DAOException() {
super();
}
public DAOException(String message) {
super(message);
}
public DAOException(String message, Throwable cause) {
super(message, cause);
}
public DAOException(Throwable cause) {
super(cause);
}
}
@regismelo 68
69. Hibernate
DAO e Abstract Factory
public class Teste {
public static void main( String args[] ) {
AutorDAO autorDAO = DAOFactory.getInstance( conn, AutorDAO.class );
autorDAO.getAutores();
...
}
}
____________________________________________________________________________
@regismelo 69
70. Hibernate
Exercício
• Implemente o exercício anterior utilizando DAO;
• A classe AutorDAO deverá ter os dois métodos
implementados – getAutores e addAutor.
• Os dois métodos deverão trabalhar com o objeto Autor que
representará os dados da tabela
(JavaBean com gets e sets).
45 minutos
@regismelo 70
71. Hibernate
Para saber mais
• http://java.sun.com/j2ee/patterns/DataAccessObject.html
• http://www.fluffycat.com/java/JavaNotes-GoFAbstractFactory.h
@regismelo 71
72. Hibernate
Módulo IV
Frameworks de Persistência
@regismelo 72
73. Hibernate
Frameworks e Java
• JDBC é uma API de muito baixo nível;
• Surge a necessidade de frameworks de persistência;
• Construir o próprio framework?
– Maior integração com seu sistema;
– Muito esforço de manutenção
• Usar um framework próprio?
– Diversos frameworks open-source;
– Muitas opções – difícil escolha!
• Vamos conhecer os principais mecanismos de persistência
disponíveis com Java.
@regismelo 73
74. Hibernate
JDO
• JDO = Java Data Objects;
• JCP (Java Community Process) desenvolveu o JDO como
uma especificação de alto nível;
• A idéia é realizar um mapeamento objeto-relacional;
• Grande vantagem por ser um padrão;
• Porém, a SUN não disponibilizou uma implementação free do
JDO (apenas uma implementação de referência);
• A implementação de referência armazena os dados em
arquivos e não em um banco relacional.
@regismelo 74
75. Hibernate
Implementações de JDO de Fornecedores
Produto Fornecedor
JDO Genie Hemisphere Technologies
LiDO LIBeLIS
JDO Toolkit MVCSoft
FrontierSuite Object Frontier
JRelay Object Industries
OpenFusion JDO Prism Technologies
Fast Objects Poet Software
IntelliBO Signsoft
Kodo JDO SolarMetric
@regismelo 75
76. Hibernate
Implementações JDO Open Source
• Existem também opções livres;
• A mais famosa delas talvez seja o Castor;
• Porém o Castor não é completamente aderente a
especificação JDO;
• Apesar de ser open source, o Castor não “explodiu” como
solução para a comunidade...
@regismelo 76
77. Hibernate
Entity Beans
• Enterprise Java Beans provêm dois tipos de mecanismo
de persistência:
– Bean Managed Persistence
– Container Managed Persistence
• BMP Você controla como o dado vai ser gravado;
• CMP O container faz o trabalho para você;
• Grandes vantagens por proporcionar um mecanismo
transparente de persistência objeto-relacional;
• Linguagem própria para consulta – OQL (Object Query
Language) muito limitada.
@regismelo 77
78. Hibernate
Entity Beans e Complexidade
• Recentemente, Richard Monson-Haefel, um dos
desenvolvedores que está especificando a especificação
3.0 de EJB (JSR 220), postou uma mensagem em seu
WebLog – “You Can make EJB better”;
• Diversas pessoas postaram mensagens sobre melhorias
na especificação;
• Ele organizou e elencou as TOP 13 funcionalidades
solicitadas pela comunidade...
• http://weblogs.java.net/pub/wlg/997
@regismelo 78
79. Hibernate
Entity Beans e Complexidade
1. Ditch CMP or make it simpler like Hibernate or JDO
2. Use a POJO programming model
3. Add support for Interceptors/filters/AOP.
4. Eliminate/Consolidate the component interfaces (remote, local
and endpoint).
5. Make deployment descriptors more like XDoclet
6. Instance-level authentication/entitlement.
7. Replace the JNDI ENC with Dependency Injection (a.k.a. IoC).
8. Add a Mutable Application Level Context
9. Support development and testing outside the container
system.
10. Define cluster-wide singletons for EJB.
11. Clearly specify and standardize class loading requirements.
12. Standardize the deployment directory structure for EJBs.
13. Support Inheritance.
@regismelo 79
80. Hibernate
Entity Beans e Complexidade
• Kiss!
• Diversos pontos levantados já são suportados por
frameworks como Hibernate;
• Do site do Hibernate:
30.06.2004 - EJB 3.0 Early Draft Review
An early draft of the EJB 3.0 specification was made public today.
The next generation of EJB is focused on simplification of the
programming model and many concepts from Hibernate have
been used to shape the new EJB entity bean part of the spec.
@regismelo 80
81. Hibernate
Hibernate
• Hibernate tem se mostrado um framework bastante
maduro;
• Não é padrão de direito, mas é um padrão de fato;
• O JBoss incorporou o projeto Hibernate como
mecanismo oficial de persistência;
• Diferente de JDO, Hibernate se propõem a persistir
dados somente em bancos relacionais;
• Open Source e com suporte aos principais SGBDs do
mercado.
@regismelo 81
83. Hibernate
Iniciando no Hibernate
• Para iniciar, iremos implementar uma classe simples de
mensagens...
• Essa classe, será responsável por armazenar
mensagens em um banco de dados relacional;
• Basicamente, teremos:
– Um número único para a mensagem;
– O texto da mensagem;
– Um ponteiro para a próxima mensagem.
@regismelo 83
84. Hibernate
package hello;
public class Message {
private Long id; // Identificador da mensagem
private String text; // Texto da mensagem
private Message nextMessage; // Próxima mensagem
private Message() { }
public Message(String text) {
this.text = text;
}
public Long getId() {
return id;
}
// ... Todos os outros gets/sets das propriedades...
}
@regismelo 84
85. Hibernate
A classe Message
• Alguns pontos importantes sobre a classe Message:
– Todos os atributos de message obedecem o padrão de
JavaBeans (get, set, is);
– A classe tem um construtor default;
– Essa classe poderá ser facilmente persistida pelo Hibernate;
– E também poderá ser utilizada livremente fora do “escopo”
hibernate;
– Isso é uma diferença importante entre Hibernate e Entity
Beans!
Message message = new Message("Hello World");
System.out.println( message.getText() );
@regismelo 85
86. Hibernate
Persistindo a classe Message
• Precisamos agora de alguma maneira de persistir a
classe message;
• Fazer isso em Hibernate seria algo do tipo:
Session session = HibernateUtil.currentSession();
Transaction trans = session.beginTransaction();
Message message = new Message("Hello World");
session.save(message);
trans.commit();
session.close();
@regismelo 86
87. Hibernate
Persistindo a classe Message
• Esse código, resultaria em um insert no banco de
dados...
insert into Messages
(Message_ID, Message_Text, Next_Message_ID )
Values ( 1, ‘Hello World’, null )
Chave cega (increment)
@regismelo 87
88. Hibernate
Persistindo a classe Message
• Para recuperar as mensagens do banco de dados:
Session newSession = getSessionFactory().openSession();
Transaction newTrans = newSession.beginTransaction();
List messages = newSession.find(
"from Message as message order by message.text asc");
System.out.println( messages.size() + " message(s) found:" );
for ( Iterator iter = messages.iterator(); iter.hasNext(); ) {
Message message = (Message) iter.next();
System.out.println( message.getText() );
}
newTrans.commit();
newSession.close();
@regismelo 88
89. Hibernate
Persistindo a classe Message
• A literal “from Message as message order by
message.text asc” na verdade é uma query Hibernate;
• No Hibernate você escreve consultas com sua
linguagem, chamada HQL (Hibernate Query Language);
• HQL é muito parecido com SQL;
• Essa consulta, provavelmente seria traduzida para algo
como:
select message.MESSAGE_ID, message.MESSAGE_TEXT,
message.NEXT_MESSAGE_ID
from MESSAGES message
order by message.MESSAGE_TEXT asc
@regismelo 89
90. Hibernate
Persistindo a classe Message
• Para “colar” as peças, é necessário ainda um arquivo de
mapeamento entre a tabela no banco de dados e o
objeto;
• É o que chamamos de “mapping metadata”;
• Basicamente, esse arquivo define os campos da tabela
em relação ao bean e seus relacionamentos;
• Vejamos um exemplo...
@regismelo 90
92. Hibernate
Persistindo a classe Message
• Podemos perceber que o arquivo XML é fácil de
entender e de manter...
• Para cada obejeto a ser persistido, teremos um arquivo
XML de configuração;
• Mais a frente, veremos maneiras de gerá-lo
automaticamente;
@regismelo 92
93. Hibernate
Persistindo a classe Message
• E para fazer alterações na tabela? Como deveríamos
proceder?
Session session = getSessionFactory().openSession();
Transaction trans = session.beginTransaction();
// 1 é o código da primeira mensagem gerada
Message message=(Message)session.load( Message.class, new Long(1) );
message.setText(“Hello World, again!");
message.setNextMessage( new Message(“It’s so funny!" ) );
trans.commit();
session.close();
@regismelo 93
94. Hibernate
Persistindo a classe Message
• Esse código iria gerar algumas queries como essas:
select message.MESSAGE_ID, message.MESSAGE_TEXT,
message.NEXT_MESSAGE_ID
from MESSAGES message
where message.MESSAGE_ID = 1
insert into MESSAGES (MESSAGE_ID, MESSAGE_TEXT,
NEXT_MESSAGE_ID)
values (2, 'Take me to your leader (please)', null)
update MESSAGES
set MESSAGE_TEXT = 'Greetings Earthling',
NEXT_MESSAGE_ID = 2
where MESSAGE_ID = 1
@regismelo 94
95. Hibernate
Persistindo a classe Message
• Para que o código do exemplo anterior funcione ainda é
necessário configurar o Hibernate;
• Fazemos isso, criando o arquivo hibernate.cfg.xml;
• Ele conterá os mapeamentos para os arquivos de
configuração de cada classe;
• Vejamos um exemplo desse arquivo...
@regismelo 95
97. Hibernate
Exercício
• Implemente a classe Message;
• Crie um servlet que persista os dados de Message e que
recupere a lista de mensagens como mostrado no
exemplo.
Consulte a resolução desse
exercício em hibernate.ex01
@regismelo 97
99. Hibernate
Ant: O que é?
• Ferramenta para construção de aplicações
– Implementada em Java
– Baseada em roteiros XML
– Extensível (via scripts ou classes)
– 'padrão' do mercado
– Open Source (Grupo Apache, Projeto Jakarta)
• Semelhante a make, porém
– Mais simples e estruturada (XML)
– Mais adequada a tarefas comuns em projetos Java
– Independente de plataforma
@regismelo 99
100. Hibernate
Integração contínua com Ant
@regismelo 100
101. Hibernate
Por que integrar continuamente?
• "Reduz o tempo passado no inferno da integração"
– Quanto mais tempo durarem os bugs de integração, mais
difíceis são de eliminar
• Integração contínua expõe o estado atual do
desenvolvimento permanentemente
– Permite avaliar e reavaliar prazos
– Permite encontrar problemas de design rapidamente
– Permite executar testes funcionais e de aceitação a
qualquer momento
– Estimula pequenos lançamentos e design simples
• Quando integrar?
– Pelo menos uma vez por dia (sistemas grandes) ou +
@regismelo 101
102. Hibernate
Tipos de integração
• Integração local
– Projetos pequenos ou subprojetos independentes
– Única cópia de trabalho do código-fonte
– Ligação com bibliotecas, montagem de componentes,
implementação, testes
– Pode ser implementada com função "build" do IDE usado
• Integração distribuída
– Projetos desenvolvidos por várias pessoas ao mesmo
tempo
– Múltiplas cópias de trabalho do código-fonte
– Atualizações a qualquer momento
– Uma atualização pode fazer testes não rodarem mais
– Mais complicada de implementar: desenvolvedores
geograficamente distribuídos, plataformas diferentes, etc.
@regismelo 102
103. Hibernate
Como implementar?
• Ferramentas de código aberto disponíveis:
– CVS, Ant e JUnit
– Extensões para essas ferramentas
• Cumprem os requisitos necessários para viabilizar a
integração contínua
– 1. Único lugar para obter as fontes mais recentes:
• Repositório CVS, ou similar
– 2. Único comando para montar a aplicação a partir das
fontes do repositório:
• Ant
– 3. Único comando para rodar todos os testes:
• JUnit
@regismelo 103
104. Hibernate
Ant: Para que serve?
• Para montar praticamente qualquer aplicação Java que consista
de mais que meia dúzia de classes;
• Aplicações:
– distribuídas em pacotes
– que requerem a definição de classpaths locais, e precisam
vincular código a bibliotecas (JARs)
– cuja criação/instalação depende de mais que uma simples
– chamada ao javac. Ex: RMI, CORBA, EJB, servlets, JSP,...
• Para automatizar processos freqüentes
– Javadoc, XSLT, implantação de serviços Web e J2EE
(deployment), CVS, criação de JARs, testes, FTP, email
@regismelo 104
105. Hibernate
Ant: Como funciona?
• Ant executa roteiros escritos em XML: 'buildfiles’;
• Cada projeto do Ant possui um buildfile
– subprojetos podem ter, opcionalmente, buildfiles adicionais
chamados durante a execução do primeiro;
• Cada projeto possui uma coleção de targets;
• Cada target consiste de uma seqüência de tasks;
• Exemplos de execução
– ant
procura build.xml no diretório atual e roda alvo default
– ant -buildfile outro.xml
executa alvo default de arquivo outro.xml
– ant compilar
roda alvo 'compilar' e possíveis dependências em build.xml
@regismelo 105
107. Hibernate
Ant: Buildfile
• O buildfile é um arquivo XML: build.xml (default)
• Principais elementos
<project default=“target_default">
Elemento raiz (obrigatório): define o projeto.
<target name=“targete_name">
Coleção de tarefas a serem executadas em seqüência
Deve haver pelo menos um <target>
<property name="nome" value="valor">
• pares nome/valor usados em atributos dos elementos do
• build.xml da forma ${nome}
• propriedades também podem ser definidas em linha de
comando (-Dprop=valor) ou lidas de arquivos externos (atributo
file)
tarefas (mais de 130) - dentro dos targets.
<javac>, <jar>, <java>, <copy>, <mkdir>, ...
@regismelo 107
109. Hibernate
Ant: O que se pode fazer?
• Compilar • Expandir, copiar, instalar
<javac>, <csc> <copy>, <delete>, <mkdir>,
• Gerar documentação <unjar>, <unwar>, <untar>,
<javadoc>, <junitreport>, <unzip>
<style>, <stylebook> • Acesso remoto
• Executar programas <ftp>, <telnet>, <cvs>,
<java>, <apply>, <exec> <mail>, <mimemail>
<ant>, <sql> • Montar componentes
• Testar unidades de código <ejbc>, <ejb-jar>, <rmic>
<junit> • Criar novas tarefas
• Empacotar e comprimir <taskdef>
<jar>, <zip>, <tar>, • Executar roteiros e sons
<war>, <ear>, <cab> <script>, <sound>
@regismelo 109
110. Hibernate
Ant: Algumas tarefas
• <javac>: Chama o compilador Java
<javac srcdir="dirfontes" destdir="dirbuild" >
<fileset includes="**/*.java" />
<classpath>
<pathelement path="arquivo.jar" />
<pathelement path="/arquivos" />
</classpath>
<classpath idref="extra" />
</javac>
• <jar>: Monta um JAR
<jar destfile="bin/programa.jar“ manifest="manifest.txt">
<fileset dir="${build.dir}"/>
</jar>
@regismelo 110
111. Hibernate
…Ant: Algumas tarefas
• <tstamp>: Grava um instante
– A hora e data podem ser recuperados como propriedades
• ${TSTAMP} hhmm 1345
• ${DSTAMP} aaaammdd 20020525
• ${TODAY} dia mes ano 25 May 2002
• Novas propriedades podem ser definidas, locale, etc.
• Uso típico: <tstamp/>
• <javadoc>: Gera documentação do código-fonte.
<javadoc destdir="docs/api“
packagenames=“br.com.softsite.sfc.*"
sourcepath="tmp" />
@regismelo 111
112. Hibernate
…Ant: Algumas tarefas
• <ftp>: Realiza a comunicação com um servidor FTP remoto para envio
ou download de arquivos
– Tarefa opcional que requer NetComponents.jar (
http://www.savarese.org)
<target name="ftp-deploy" depends="dist">
<ftp server="${ftp.host}" port="${ftp.port}“
remotedir="/tomcat/deploy“ userid="tomcat" password="catalina“
depends="yes" binary="yes">
<fileset dir="${basedir}">
<include name="*.war"/>
</fileset>
</ftp>
</target>
@regismelo 112
113. Hibernate
Ant: Filtros
• Permite a substituição de padrões delimitados por um caractere em arquivos
durante a execução de uma tarefa
– Caractere default: @
• Exemplo: a tarefa abaixo irá substituir todas as ocorrências de @javahome@
por c:j2sdk1.4.0 nos arquivos copiados
<copy todir="${dest.dir}">
<fileset dir="${src.dir}"/>
<filterset>
<filter token="javahome" value="c:j2sdk1.4.0"/>
</filterset>
</copy>
• Pares token=valor podem ser carregados de arquivo:
<filterset>
<filtersfile file="build.properties" />
</filterset>
@regismelo 113
114. Hibernate
Exercício
• Empacotar em um arquivo WAR o exemplo hibernate
anterior;
• Fazer o deploy desse arquivo WAR no TomCat.
Consulte a resolução desse exercício em hibernate.ex02
Antes de executar, configure o arquivo build.properties de acordo com seu ambiente
@regismelo 114
115. Hibernate
Para saber mais
• http://ant.apache.org/
• Exemplos de build files
dos projetos Jakarta
@regismelo 115
116. Hibernate
Módulo VII
Hibernate –
Entendendo a Arquitetura
@regismelo 116
118. Hibernate
Arquitetura
• Session Interface
– É a principal interface utilizada por aplicações Hibernate;
– Não é thread-safe;
– Falando em banco de dados, pense em uma sessão como algo entre uma
conexão e uma transação;
– Falando em Java, pense em uma sessão como um cache ou uma coleção
de objetos relativos a uma “unit of work”;
– Ela é a interface responsável por persistir os dados no banco de dados.
– Dica: Faça com que seu programa compartilhe em uma mesma requisição
a mesma instância de session (ver implementação HibernateUtil).
@regismelo 118
119. Hibernate
Arquitetura
• SessionFactory Interface
– Mantém cache dos SQL gerados e outros mapeamentos que o Hibernate
usa em tempo de execução;
– Mantém também cache de dados que são lidos em uma sessão;
• Configuration Interface
– Usado para configurar o Hibernate;
– Configuration é utilizado para indicar o local dos arquivos XML e para obter
SessionFactory
@regismelo 119
120. Hibernate
Arquitetura
• Transaction Interface
– Gerencia transações com o banco de dados;
– É uma API opcional, pois a aplicação poderá optar por gerenciar a
transação sozinha;
– Abstrai o mecanismo utilizado para gerenciar uma transação (que
pode ser uma transação JDBC, JTA ou CORBA);
– É interessante pois permite que aplicações Hibernate sejam
portáveis entre diferentes tipos de container e ambientes.
@regismelo 120
121. Hibernate
Arquitetura
• Query and Criteria Interface
– Permite criar queries no banco de dados;
– As consultas são escritas em HQL (Hibernate Query Language) ou
em SQL nativo;
– Criteria é uma interface muito similar que permite você criar e
executar consultas baseadas em critérios (veremos mais a frente
esse tópico);
@regismelo 121
122. Hibernate
Arquitetura
• Callbacks interfaces
– Permite que a aplicação receba notificações quando algo
“interessante” acontece com os objetos;
– Notifica quando o objeto é lido, excluído ou armazenado no
banco de dados;
– Inteface Lifecycle
• onSave: Chamado antes do objeto ser salvo
• onUpdate: Chamado antes do objeto ser atualizado
(Session.update())
• onDelete: Antes do objeto ser deletado
• onLoad: Depois do objeto ser lido.
@regismelo 122
123. Hibernate
Arquitetura
• ...Callbacks interfaces
– Interface Validatable
• validate: Validar o objeto antes dele ser persistido.
– A interface Interceptor também é utilizada para “interceptar”
ações do Hibernate;
– Vantagem em usar pois não força que as classes
implementem uma interface Hibernate.
@regismelo 123
124. Hibernate
Arquitetura
• Types
– Um tipo no Hibernate mapeia um tipo Java para um tipo no
banco de dados;
– Um tipo no Hibernate pode inclusive se transformar em mais
de uma coluna no banco de dados (endereço de cobrança,
por exemplo);
• Extension Interfaces
– Possibilidade de extender funcionalidades do Hibernate;
– Exemplos – Geração de primary key, dialetos SQL,
estratégias de cache, etc.
@regismelo 124
125. Hibernate
Configurações
• Hibernate pode ser utilizado tanto em “ambientes não
gerenciados” (tipicamente um servlet container) quanto em
“ambientes gerenciados” (EJB);
• O desenho dos POJOs, mapeamentos e configurações do
Hibernate são os mesmos;
• Vantagem em relação a BMP/CMP pois:
– É portável entre tipos diferentes de arquitetura;
– É fácil de testar (JUnit);
– É mais natural de implementar. Você vai desenhar
apenas JavaBeans.
@regismelo 125
129. Hibernate
Dicas importantes
• Um Session Factory, usando como Factory de sessões é
uma classe dispendiosa para ser criada;
• Ela é a responsável por fazer o parser dos arquivos XML
de definição do Hibernate;
• Portanto, procure criar essa classe apenas uma vez!
• Você pode criar uma classe “Helper” para fazer isso...
• Vejamos o exemplo...
@regismelo 129
130. Hibernate
Dicas importantes
• Um Session Factory, usando como Factory de sessões é
uma classe dispendiosa para ser criada;
• Ela é a responsável por fazer o parser dos arquivos XML
de definição do Hibernate;
• Portanto, procure criar essa classe apenas uma vez!
• Você pode criar uma classe “Helper” para fazer isso...
• Vejamos o exemplo...
@regismelo 130
131. Hibernate
Classe Helper Hibernate
public class HibernateUtil {
private static final SessionFactory sessionFactory;
static {
try {
// Create the SessionFactory
sessionFactory = new
Configuration().configure().buildSessionFactory();
} catch (HibernateException ex) {
System.out.println(ex);
throw new RuntimeException(“Problemas na configuracao: " +
ex.getMessage(), ex);
}
}
}
@regismelo 131
132. Hibernate
Dicas importantes
• Você pode usar essa mesma classe Helper para garantir
que a mesma Session seja retornada entre várias
chamadas;
• Isso é bom pois evitará problemas de concorrência e
fará como que dados (cache de objetos) seja
compartilhado entre chamadas;
• Importante: Session não é Thread Safe!
• Você pode utilizar a mesma classe Helper para fazer
isso, usando um pequeno truque com ThreadLocal;
• Vejamos o exemplo…
@regismelo 132
133. Hibernate
public class HibernateUtil {
// … Código do exemplo anterior suprimido por questões de
espaço
private static final ThreadLocal session = new ThreadLocal();
public static Session currentSession() throws HibernateException {
Session s = (Session) session.get();
// Abre uma nova sessão se necessário
if ( (s == null) || ( ! s.isConnected() ) ){
s = sessionFactory.openSession();
session.set(s);
}
return s;
}
public static void closeSession() throws HibernateException {
Session s = (Session) session.get();
session.set(null);
if (s != null)
s.close();
}
}
@regismelo 133
134. Hibernate
Dicas importantes
• Você pode usar essa mesma classe Helper para garantir
que a messa Session seja retornada entre várias
chamadas;
• Isso é bom pois evitará problemas de concorrência e
fará como que dados (cache de objetos) seja
compartilhado entre chamadas;
• Importante: Session não é Thread Safe!
• Você pode utilizar a mesma classe Helper para fazer
isso, usando um pequeno truque com ThreadLocal;
• Vejamos o exemplo…
@regismelo 134
135. Hibernate
Para saber mais
• Hibernate in Action, chapter 3;
•
@regismelo 135
136. Hibernate
Módulo VIII
Trabalhando com Persistent Objects
@regismelo 136
137. Hibernate
Persistence Lifecycle
• Hibernate é um mecanismo de persistência
transparente;
• Isso significa que classes não precisam se preocupar
com a sua própria capacidade de persistência;
• Ótimo! Nossos objetos não precisam de um tratamento
especial, não precisam herdar de uma classes
específica, não precisam trabalhar de forma diferente
para serem persistidos;
• Isso facilita o trabalho e principalmente nos permite
fazer escolhas diferentes de mecanismos de
persistência.
@regismelo 137
138. Hibernate
Persistence Lifecycle
• Porém, a sua aplicação precisa interagir de alguma
forma com a camada de persistência indicando que os
dados precisam ser gravados no banco ou recuperados
dele;
• Para fazer isso, é necessário o uso da API do Hibernate
(persistence manager e query interfaces);
• O ciclo de vida dos objetos persistidos é definido em 3
estados – Transient, Persistent e Detached;
• Vejamos o gráfico…
@regismelo 138
140. Hibernate
Persistence Lifecycle - Transient
• O primeiro estado é o transiente;
• Ele acontece quando você instancia um objeto qualquer
Cliente a = new Cliente();
• O estado é chamado de transient o que quer dizer que ele não está
associado a nenhuma linha no banco de dados;
• O seu estado será perdido assim que ele não for mais referenciado
(garbage collector);
• Para um objeto transient passar a ser persistent é requerida uma
chamada a save() a partir de persistence manager ou a criação de
uma referência a partir de um persistência já instanciada.
@regismelo 140
141. Hibernate
Session session = HibernateUtil.currentSession();
Transaction trans = session.beginTransaction();
Objeto
Message message = new Message();
transiente
message.setText("Hello World of Hibernate!");
Objeto
session.save(message);
persistente
trans.commit();
session.close();
@regismelo 141
142. Hibernate
Session session = HibernateUtil.currentSession();
Transaction trans = session.beginTransaction();
// Instanciar uma nova classe message
Message newMessage = new Message(); Objeto
newMessage.setText("Hibernate é fácil!"); transiente
// 1 é o código da primeira mensagem gerada
Message messageOriginal = (Message) session.load( Message.class, new
Long(1) );
messageOriginal.setText("Hello World, de novo!");
messageOriginal.setNextMessage( newMessage );
trans.commit();
session.close(); Objeto
persistente pois
foi associado a
outro objeto
persistente
@regismelo 142
143. Hibernate
Persistence Lifecycle - Persistent
• É qualquer instância com “database identity”;
• Pode ser desde um objeto que foi instanciado pela
aplicação e salvo pela chamada do método save();
• Ou um objeto que já foi recuperado do banco de dados
(através de uma query, por exemplo);
• Vejamos o exemplo…
@regismelo 143
144. Hibernate
Session session = HibernateUtil.currentSession();
Transaction trans = session.beginTransaction();
List messages = session.find(
"from Message as message order by message.text asc");
for ( Iterator iter = messages.iterator(); iter.hasNext(); ) {
Message message = (Message) iter.next();
out.println( message.getText() + "<BR>" );
} Objetos
persistentes
trans.commit();
session.close();
@regismelo 144
145. Hibernate
Persistence Lifecycle - Detached
• Objetos “desconectados” são objetos que não tem mais
ligação com o banco de dados;
• Causa - A transação acabou;
• Muito útil pois pode evitar a necessidade de DTOs
(típicos de aplicações EJB);
• Problemático pois pode gerar LazyInitializationException
@regismelo 145
146. Hibernate
Persistence Manager
• Criando objetos novos:
User user = new User();
user.setFirstname("John");
user.setLastname("Doe");
Session session = sessions.openSession();
Transaction tx = session.beginTransaction();
session.save(user);
tx.commit();
session.close();
@regismelo 146
147. Hibernate
Persistence Manager
• Alterando objetos:
user.setPassword("secret");
Session sessionTwo = sessions.openSession();
Transaction tx = sessionTwo.beginTransaction();
sessionTwo.update(user);
user.setUsername("jonny");
Somente
tx.commit(); necessário se
sessionTwo.close(); for um objeto
desconectado
@regismelo 147
149. Hibernate
Persistence Manager
• Tornando objetos transientes:
Session session = sessions.openSession();
Transaction tx = session.beginTransaction();
int userID = 1234;
User user = new User();
user.setId( 1234 );
session.delete(user);
tx.commit();
session.close();
@regismelo 149
150. Hibernate
Primary Keys no Hibernate
• Toda tabela deve indicar qual sua chave primária;
• Use a tag “id” para indicar qual a chave primária da
tabela:
<id name="codigo" column="CD_LIVRO“/>
• Você pode informar também qual o mecanismo de
geração de chaves:
<id name="codigo" column="CD_LIVRO">
<generator class="hilo">
<param name="table">NrLivro</param>
<param name="column">next_value</param>
</generator>
</id>
@regismelo 150
151. Hibernate
Primary Keys no Hibernate
• A geração de chaves é determinada pela tag
<generator>;
• Existem diversas classes disponibilizadas para a
geração de chaves;
• São classes simples que implementam a interface
net.sf.hibernate.id.IdentifierGenerator
• Você pode implementar o seu próprio mecanismo...
• Ou usar um dos diversos mecanismos já
disponibilizados no Hibernate.
@regismelo 151
152. Hibernate
Geração de Chaves
• increment
– generates identifiers of type long, short or int that are unique
only when no other process is inserting data into the same table.
Do not use in a cluster.
• identity
– supports identity columns in DB2, MySQL, MS SQL Server,
Sybase and HypersonicSQL. The returned identifier is of type
long, short or int.
• sequence
– uses a sequence in DB2, PostgreSQL, Oracle, SAP DB, McKoi
or a generator in Interbase. The returned identifier is of type
long, short or int
@regismelo 152
153. Hibernate
Geração de Chaves
• hilo
– uses a hi/lo algorithm to efficiently generate identifiers of type
long, short or int, given a table and column (by default
hibernate_unique_key and next respectively) as a source of hi
values. The hi/lo algorithm generates identifiers that are unique
only for a particular database.
• seqhilo
– uses a hi/lo algorithm to efficiently generate identifiers of type
long, short or int, given a named database sequence (Oracle,
por exemplo).
• uuid.hex
– uses a 128-bit UUID algorithm to generate identifiers of type
string, unique within a network (the IP address is used). The
UUID is encoded as a string of hexadecimal digits of length 32.
@regismelo 153
154. Hibernate
Geração de Chaves
• uuid.string
– uses the same UUID algorithm. The UUID is encoded a string of
length 16 consisting of (any) ASCII characters. Do not use with
PostgreSQL.
• native
– picks identity, sequence or hilo depending upon the capabilities
of the underlying database.
• assigned
– lets the application to assign an identifier to the object before
save() is called.
• foreign
– uses the identifier of another associated object. Usually used in
conjunction with a <one-to-one> primary key association.
@regismelo 154
156. Hibernate
Geração de Chaves - Exemplos
• Identity columns and Sequences
<id name="id" type="long" column="uid">
<generator class="sequence">
<param name="sequence">uid_sequence</param>
</generator>
</id>
<id name="id" type="long" column="uid" unsaved-value="0">
<generator class="identity"/>
</id>
• Dica Para compatibilidade entre bancos, use native. O Hibernate
se encarregará de usar identity, sequence ou hilo de acordo com o
banco de dados selecionado.
@regismelo 156
157. Hibernate
Recuperando dados
• Existem diversas formas de recuperar dados usando o Hibernate;
• Usando o método load:
Livro livro = (Livro)session.load( Cat.class,
new Long(1234) );
• Usando o método get:
Livro livro = (Livro)session.get( Cat.class,
new Long(1234) );
• O load dispara uma exceção ObjectNotFoundException caso não
seja encontrada a linha no banco de dados;
• get tenta carregar a linha imediatamente e retorna null caso nada
seja encontrado.
@regismelo 157
158. Hibernate
Recuperando dados
• É possível também dar um refresh nos dados;
• Pode ser útil quando um trigger altera algum dado da linha lida.
Livro livro = (Livro)session.load( Cat.class,
new Long(1234) );
livro.setPreco( 1000 );
session.update(livro);
session.refresh( livro );
@regismelo 158
159. Hibernate
Recuperando dados
• É possível ainda executar consultas com Hibernate;
• Hibernate usa uma linguagem muito parecida com SQL chamada
HQL (Hibernate Query Language);
• HQL não é uma linguagem de manipulação como SQL – é usada
somente para recuperar dados (não possui funcionalidade de
alteração/deleção);
• HQL parece com ODMG OQL e EJB QL (A versão 3.0 do EJB QL é
bem parecida com HQL).
• Vejamos alguns exemplos...
@regismelo 159
160. Hibernate
List cats = sess.find("from Cat as cat where cat.birthdate = ?",
date, Hibernate.DATE );
List mates = sess.find(
"select mate from Cat as cat join cat.mate as mate where " +
"cat.name = ?", name, Hibernate.STRING );
List cats = sess.find( "from Cat as cat where cat.mate.bithdate is
null" );
List moreCats = sess.find("from Cat as cat where " +
"cat.name = 'Fritz' or cat.id = ? or cat.id = ?",
new Object[] { id1, id2 },
new Type[] { Hibernate.LONG, Hibernate.LONG }
);
List problems = sess.find("from GoldFish as fish " +
"where fish.birthday > fish.deceased or fish.birthday is null");
Query q = session.createQuery("from User u where u.firstname =
:fname");
q.setString("fname", "Max");
List result = q.list();
@regismelo 160
161. Hibernate
Query by Criteria
• Hibernate possui ainda um mecanismo chamado QBC – Query by
Criteria;
• Alguns desenvolvedores usam QBC pois o vêem como um
mecanismo mais O.O. para realizar consultas;
• Do outro lado, consultas feitas com QBC são menos legíveis que
consultas expressas com HQL
Criteria criteria = session.createCriteria(User.class);
criteria.add( Expression.like("firstname", "Max") );
List result = criteria.list();
@regismelo 161
162. Hibernate
Query by Example
• Complementar a Query by Criteria existe um mecanismo chamado
Query by Example;
• Útil quando você quer listar dados a partir de vários filtros que
podem ser representados em um objeto
(usuário pode preencher qualquer dado da tela de clientes para
pesquisar um cliente)
User exampleUser = new User();
exampleUser.setFirstname("Max");
Criteria criteria = session.createCriteria(User.class);
criteria.add( Example.create(exampleUser) );
List result = criteria.list();
@regismelo 162
163. Hibernate
Query Nativa
• Se você realmente precisar de algo dependente do banco de dados
você poderá usar o mecanismo de consultas nativas do Hibernate;
• Nele, você pode realizar as consultas e fazer mapeamentos das
mesmas com o banco de dados;
• Veja o exemplo:
session.createSQLQuery(
"select {c.*} from CATEGORY {c} where NAME like 'Laptop
%'",
"c",
Category.class);
@regismelo 163
164. Hibernate
O que você consegue fazer com HQL
• The ability to apply restrictions to properties of associated objects related by
reference or held in collections (to navigate the object graph using query language).
• The ability to retrieve only properties of an entity or entities, without the overhead of
loading the entity itself in a transactional scope. This is sometimes called a report
query; it’s more correctly called projection.
• The ability to order the results of the query.
• The ability to paginate the results.
• Aggregation with group by, having, and aggregate functions like sum, min, and max.
• Outer joins when retrieving multiple objects per row.
• The ability to call user-defined SQL functions.
• Subqueries (nested queries).
Fonte: Hibernate in Action
@regismelo 164
165. Hibernate
Query Interface
• Executar uma query através do Hibernate pode ser feito de duas
formas – através da própria session:
List autores = session.find("from Autor as autor “ );
• Ou através da criação explícita de uma Query:
Query qry = session.createQuery("from Autor as autor“ );
List autores = qry.list();
• A primeira forma pode ser considerada como um “atalho” em
relação a segunda;
• Porém a segunda tem mais vantagens, pois oferece todas as
funcionalidades da interface Query.
@regismelo 165
166. Hibernate
Métodos interessantes de Query
• list()
– Retorna os resultados da query no formato de um list. Se a
query contém múltiplos resultados em uma linha (mais de um
objeto está sendo retornado), o resultado é retornado como uma
instância de Object[].
Query qry = session.createQuery("from Autor as autor“ );
List autores = qry.list();
Iterator foosAndBars = session.list(
"select foo, bar from Foo foo, Bar bar where bar.date = foo.date"
);
while ( foosAndBars.hasNext() ) {
Object[] tuple = (Object[]) foosAndBars.next();
Foo foo = tuple[0]; Bar bar = tuple[1];
....
}
@regismelo 166
167. Hibernate
Métodos interessantes de Query
• iterate()
– O mesmo que list. Porém, só as chaves primárias são
retornadas com a chamada de iterate. Os objetos são
populados sob demanda no momento em que são requisitados;
– Pode ser mais eficiente que list() caso você não pretenda
navegar em todo o result set ou se grande parte dos objetos já
estiver carregado na memória;
– Pode ser mais lento pois requer a execução de n+1 consultas.
Query qry = session.createQuery("from Autor as autor“ );
Iterator autores = qry.iterate();
@regismelo 167
168. Hibernate
Métodos interessantes de Query
• Métodos de paginação – setFirstResult() e setMaxResults()
– Usado para páginação;
– O Hibernate decidirá como fará a paginação no seu banco de
dados;
Query query =
session.createQuery("from User u order by u.name asc");
query.setFirstResult(0);
query.setMaxResults(10);
List results = session.createQuery("from User u order by u.name asc")
.setFirstResult(0)
.setMaxResults(10)
.list();
@regismelo 168
169. Hibernate
Métodos interessantes de Query
• Passagem de parâmetros – nunca use:
String queryString =
"from Item i where i.description like '" + searchString + "'";
List result = session.createQuery(queryString).list();
•
• Um usuário malicioso pode passar um parâmetro de forma que a
consulta se comporte de outra forma:
foo' and callSomeStoredProcedure() and 'bar' = 'bar
• Use a passagem de parâmetros do Hibernate ao invés disso...
@regismelo 169
170. Hibernate
Métodos interessantes de Query
• Passagem de parâmetros:
String queryString =
"from Item item where item.description like :searchString";
List result = session.createQuery(queryString)
.setString("searchString", searchString)
.list();
• Métodos comuns para a passagem de parâmetro:
– setString, setBoolean, setInteger, setFloat, ...
– setParameter( String name, Object val )
@regismelo 170
171. Hibernate
Named Queries
• Como você já deve ter percebido, usar queries dentro do código
pode torná-lo pouco legível;
• Para isso, o Hibernate possui um recurso chamado Named
Queries;
• Você pode armazernar as consultas em um arquivo XML e
simplesmente chamá-lo do seu programa Java;
• O interessante é que as consultas podem ser escritas em HQL ou
SQL – o código Java não vai precisar tomar conhecimento disso;
<query name="findItemsByDescription"><![CDATA[
from Item item where item.description like :description
]]>
</query>
@regismelo 171
172. Hibernate
Exercício
• Dado o modelo de dados (ver referência no final desse
material)...
• Faça a manutenção da tabela Autor (Inserir, Alterar,
Consultar e Deletar).
Consulte a resolução desse exercício
em hibernate.ex??
TODO: Finalizar o exercício
@regismelo 172
174. Hibernate
Xdoclet
• Xdoclet é uma ferramenta de geração de código
– Open Source
– Estende a Javadoc doclet API, permitindo a criação de
novos arquivo baseado nas tags @ do javadoc
– Baseado no ANT
– Extensível através de templates.
• Site:http://xdoclet.sourceforge.net
• Fornece suporte para geração de Arquivos EJB
– ejb-jar.xml, interfaces home, remote etc.
@regismelo 174
175. Hibernate
Exemplo: CountBean.java
/**
* @ejb.bean type="Stateful"
* view-type="both"
* jndi-name="CountHome"
*/
public class CountBean implements SessionBean {
public int val;
/**
* Counts up
* @ejb.interface-method
*/
public int count() {
System.out.println("count()");
return ++val;
}
/*
* @ejb.create-method
*/
public void ejbCreate(int val) throws CreateException {
this.val = val;
System.out.println("ejbCreate()");
}
. . .
@regismelo 175
Notes de l'éditeur
1o. Gráfico refere-se a uma app sem Hibernate 2o. Gráfico – um app sem EJB usando Hibernate
Uma app EJB com hibernate
LazyInitializationException pode acontecer quando Lazy Loading estiver ligado, a sessão tiver sido fechada e um objeto ainda não carregado seja solicitado.
\\
\\
\\
Fale sobre a interface Query.
Example é uma classe do Hibernate usada para montar a query de acordo com o exemplo de classe passado.
Como não é possível fazer um proxy de um array puro, o lazy loading não funciona.
Como não é possível fazer um proxy de um array puro, o lazy loading não funciona.