Upload
regis-melo
View
24
Download
0
Tags:
Embed Size (px)
DESCRIPTION
Material do Curso de Hibernate 2008
Citation preview
@regismelo
Hibernate
1
Persistência com Hibernate
Régis Melo@regismelo
@regismelo
Hibernate
2
Missão
Apresentar, motivar e exercitar mecanismos de persistência em Java, com enfoque no framework Hibernate.
@regismelo
Hibernate
3
Metodologias
• Exposição e discussão teóricas;
• Exercícios práticos de projeto e modelagem em laboratório.
@regismelo
Hibernate
4
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
Hibernate
5
Antes de iniciar…
Vamos nos apresentar
• Nome;
• Empresa;
• Experiência com programação;
• Razões de estar fazendo esse treinamento;
• Expectativas desse curso.
@regismelo
Hibernate
6
Livros sugeridos
@regismelo
Hibernate
7
Prepara os teus trabalhos de fora, apronta bem o teu campo; e depois edifica a tua casa.
Provérbios 24:27
@regismelo
Hibernate
8
Módulo I
E no princípio, era o JDBC…
@regismelo
Hibernate
9
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
Hibernate
10
• É 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).
O que é JDBC?
@regismelo
Hibernate
11
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.
O que JDBC faz?
@regismelo
Hibernate
12
• 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.
API JDBC
@regismelo
Hibernate
13
API JDBC
@regismelo
Hibernate
14
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
Hibernate
15
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
Hibernate
16
Tipo 1 - Ponte
• JDBC-ODBC BRIDGE + ODBC DRIVER
AplicaçãoJAVA
JDBC-ODBCBridge
DriverODBC
Dados
APIODBC
APIJDBC
@regismelo
Hibernate
17
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
Hibernate
18
Tipo 2 – Java Nativo
• Java / Nativo
AplicaçãoJAVA
DriverJDBC
Dados
APINativaSGBD
APIJDBC
@regismelo
Hibernate
19
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
Hibernate
20
Tipo 3 – Gateway
• Servidor de acesso intermediário
AplicaçãoJAVA
Driver JDBCDriverNativo
Dados
JDBCDriverServer
APIJDBC
@regismelo
Hibernate
21
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
Hibernate
22
Tipo 4 – All Java Driver
• All Java Driver
AplicaçãoJAVA
Driver JDBC DadosAPI
JDBC
@regismelo
Hibernate
23
@regismelo
Hibernate
24
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
Hibernate
25
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
Hibernate
26
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
Hibernate
27
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
Hibernate
28
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
Hibernate
29
Executando uma consulta• E ao final de tudo, devemos fechar o statement
e a conexão.
...stmt.close();
conn.close();
@regismelo
Hibernate
30
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 }
Executando uma consulta
@regismelo
Hibernate
31
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
Hibernate
32
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
Hibernate
33
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
Hibernate
34
API JDBC• Exemplo de um executeUpdate
String sql = “update conta set saldo = 1000“;
Statement stmt = conn.createStatement( sql );
stmt.executeUpdate();
throws SQLException
@regismelo
Hibernate
35
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
Hibernate
36
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
Hibernate
37
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
Hibernate
38
ResultSet e os métodos get
@regismelo
Hibernate
39
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
Hibernate
40
Para saber mais
• http://java.sun.com/docs/books/tutorial/jdbc/index.html
@regismelo
Hibernate
41
Módulo II
Pool de conexões
@regismelo
Hibernate
42
Entendendo o problema...
• Em aplicações cliente/servidor, tipicamente temos, para cada cliente uma conexão com o banco de dados...
@regismelo
Hibernate
43
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
Hibernate
44
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
Hibernate
45
Container
Pool de Conexões
<<servlet>>
Cliente
Pool de Conexões
<<Conexão 1>> << Conexão 2 >> <<Conexão 3>> << Conexão 4 >>
<<servlet>>
X
<<servlet>>
Y
<<servlet>>
Z
@regismelo
Hibernate
46
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
Hibernate
47
Container
Solicita uma conexão
Pool de Conexões
<<servlet>>
Cliente
Connection Pool
Existe conexões
disponíveis no pool?
Devolve conexão
com o Banco de dados
Obtém uma nova
conexão
Não
Sim
@regismelo
Hibernate
48
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
Hibernate
49
Pool de Conexões no TomCat
@regismelo
Hibernate
50
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
Hibernate
51
Pool de Conexões no TomCat
Nome da conexão JNDI
String DataSourceEspecí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 exceção ser disparada
Query de validação – usada para verificar se a conexão ainda é válida
@regismelo
Hibernate
52
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;DatabaseName=<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
Hibernate
53
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
Hibernate
54
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
Hibernate
55
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
Hibernate
56
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
Hibernate
57
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) {out.println(e);e.printStackTrace();
}
InitialContext é configurado no momento em que é feito
o deploy da aplicação e se torna
disponível (para leitura).
Todas as entradas configuradas ficam disponíveis
em “java:comp/env” no namespace JNDI.
@regismelo
Hibernate
58
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
Hibernate
59
Para saber mais
• http://jakarta.apache.org/tomcat/tomcat-5.0-doc/jndi-resources-howto.html
@regismelo
Hibernate
60
Módulo III
Data Access Objects
@regismelo
Hibernate
61
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
Hibernate
62
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
Hibernate
63
Estrutura de um DAO
@regismelo
Hibernate
64
Estrutura de um DAO
@regismelo
Hibernate
65
DAO e Abstract Factory
• No caso da implementação do DAO é útil usar um Abstract Factory para instanciar as classes.
@regismelo
Hibernate
66
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
Hibernate
67
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
Hibernate
68
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
Hibernate
69
DAO e Abstract Factory
public class Teste {public static void main( String args[] ) {
AutorDAO autorDAO = DAOFactory.getInstance( conn, AutorDAO.class );
autorDAO.getAutores();
...
}
}____________________________________________________________________________
@regismelo
Hibernate
70
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
Hibernate
71
Para saber mais
• http://java.sun.com/j2ee/patterns/DataAccessObject.html
• http://www.fluffycat.com/java/JavaNotes-GoFAbstractFactory.html
@regismelo
Hibernate
72
Módulo IV
Frameworks de Persistência
@regismelo
Hibernate
73
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
Hibernate
74
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
Hibernate
75
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
Hibernate
76
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
Hibernate
77
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
Hibernate
78
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
Hibernate
79
Entity Beans e Complexidade1. Ditch CMP or make it simpler like Hibernate or JDO2. Use a POJO programming model3. Add support for Interceptors/filters/AOP.4. Eliminate/Consolidate the component interfaces (remote, local and endpoint).5. Make deployment descriptors more like XDoclet6. Instance-level authentication/entitlement.7. Replace the JNDI ENC with Dependency Injection (a.k.a. IoC).8. Add a Mutable Application Level Context9. 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
Hibernate
80
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 ReviewAn 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
Hibernate
81
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
Hibernate
82
Módulo V
Hibernating…
@regismelo
Hibernate
83
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
Hibernate
84
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
Hibernate
85
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
Hibernate
86
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
Hibernate
87
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
Hibernate
88
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
Hibernate
89
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
Hibernate
90
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
Hibernate
91
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sf.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="hello.Message" table="MESSAGE">
<id name="id" column="MESSAGE_ID">
<generator class="native"/>
</id>
<property name="text" column="MESSAGE_TEXT"/>
<many-to-one name="nextMessage" cascade="all“ column="NEXT_MESSAGE_ID"/>
</class>
</hibernate-mapping>
Arquivo Message.hbm.xml
@regismelo
Hibernate
92
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
Hibernate
93
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 geradaMessage 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
Hibernate
94
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
Hibernate
95
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
Hibernate
96
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration
PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.datasource">java:comp/env/jdbc/quickstart</property>
<property name="show_sql">true</property>
<property name="dialect">net.sf.hibernate.dialect.SQLServerDialect</property>
<!– Mapping files -->
<mapping resource=“Message.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Arquivo hibernate.cfg.xml
@regismelo
Hibernate
97
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
Hibernate
98
Módulo V
Ant
@regismelo
Hibernate
99
• 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
Ant: O que é?
@regismelo
Hibernate
100
Integração contínua com Ant
@regismelo
Hibernate
101
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
Hibernate
102
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
Hibernate
103
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
Hibernate
104
• 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
Ant: Para que serve?
@regismelo
Hibernate
105
• 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
Ant: Como funciona?
@regismelo
Hibernate
106
Ant: Como funciona?
@regismelo
Hibernate
107
• 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üênciaDeve 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>, ...
Ant: Buildfile
@regismelo
Hibernate
108
Targets
<?xml version="1.0" encoding="iso-8859-1" ?>
<!-- Compila diversos arquivos .java -->
<project default="compile" basedir=".">
<property name="src.dir" value="${basedir}/src" />
<property name="build.dir" value="build" />
<target name="init">
<echo> Criando diretório </echo>
<mkdir dir="${build.dir}" />
</target>
<target name="compile" depends="init“ description="Compila os arquivos-fonte">
<javac srcdir="${src.dir}" destdir="${build.dir}">
<classpath>
<pathelement location="${build.dir}" />
</classpath>
</javac>
</target>
</project>
…Ant: Buildfile Propriedades
Tasks
@regismelo
Hibernate
109
Ant: O que se pode fazer?• Compilar
<javac>, <csc>• Gerar documentação
<javadoc>, <junitreport>,
<style>, <stylebook>• Executar programas
<java>, <apply>, <exec>
<ant>, <sql>• Testar unidades de código
<junit>• Empacotar e comprimir
<jar>, <zip>, <tar>,
<war>, <ear>, <cab>
• Expandir, copiar, instalar
<copy>, <delete>, <mkdir>,
<unjar>, <unwar>, <untar>,
<unzip>• Acesso remoto
<ftp>, <telnet>, <cvs>,
<mail>, <mimemail>• Montar componentes
<ejbc>, <ejb-jar>, <rmic>• Criar novas tarefas
<taskdef>• Executar roteiros e sons
<script>, <sound>
@regismelo
Hibernate
110
• <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>
Ant: Algumas tarefas
@regismelo
Hibernate
111
• <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" />
…Ant: Algumas tarefas
@regismelo
Hibernate
112
• <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>\
…Ant: Algumas tarefas
@regismelo
Hibernate
113
• 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>
Ant: Filtros
@regismelo
Hibernate
114
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
Hibernate
115
Para saber mais
• http://ant.apache.org/
• Exemplos de build filesdos projetos Jakarta
@regismelo
Hibernate
116
Módulo VII
Hibernate – Entendendo a Arquitetura
@regismelo
Hibernate
117
Arquitetura
@regismelo
Hibernate
118
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
Hibernate
119
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
Hibernate
120
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
Hibernate
121
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
Hibernate
122
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
Hibernate
123
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
Hibernate
124
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
Hibernate
125
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
Hibernate
126
Configurações
@regismelo
Hibernate
127
Configurações
@regismelo
Hibernate
128
Configurações
@regismelo
Hibernate
129
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
Hibernate
130
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
Hibernate
131
Classe Helper Hibernatepublic 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
Hibernate
132
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
Hibernate
133
public class HibernateUtil {// … Código do exemplo anterior suprimido por questões de espaçoprivate static final ThreadLocal session = new ThreadLocal();
public static Session currentSession() throws HibernateException {Session s = (Session) session.get();// Abre uma nova sessão se necessárioif ( (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
Hibernate
134
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
Hibernate
135
Para saber mais
• Hibernate in Action, chapter 3;
•
@regismelo
Hibernate
136
Módulo VIII
Trabalhando com Persistent Objects
@regismelo
Hibernate
137
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
Hibernate
138
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
Hibernate
139
Persistence Lifecycle
@regismelo
Hibernate
140
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
Hibernate
141
Session session = HibernateUtil.currentSession();
Transaction trans = session.beginTransaction();
Message message = new Message();message.setText("Hello World of Hibernate!");
session.save(message);
trans.commit();session.close();
Objeto transiente
Objeto persistente
@regismelo
Hibernate
142
Session session = HibernateUtil.currentSession();Transaction trans = session.beginTransaction();
// Instanciar uma nova classe messageMessage newMessage = new Message();newMessage.setText("Hibernate é fácil!");
// 1 é o código da primeira mensagem geradaMessage messageOriginal = (Message) session.load( Message.class, new Long(1) );messageOriginal.setText("Hello World, de novo!");messageOriginal.setNextMessage( newMessage );
trans.commit();session.close();
Objeto transiente
Objeto persistente
pois foi associado a outro objeto persistente
@regismelo
Hibernate
143
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
Hibernate
144
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>" );
}
trans.commit();session.close();
Objetos persistentes
@regismelo
Hibernate
145
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
Hibernate
146
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
Hibernate
147
Persistence Manager
• Alterando objetos:
user.setPassword("secret");Session sessionTwo = sessions.openSession();
Transaction tx = sessionTwo.beginTransaction();
sessionTwo.update(user);user.setUsername("jonny");
tx.commit();sessionTwo.close();
Somente necessário se for um objeto desconectado
@regismelo
Hibernate
148
Persistence Manager
• Alterando objetos:
user.setPassword("secret");Session sessionTwo = sessions.openSession();
Transaction tx = sessionTwo.beginTransaction();
sessionTwo.saveOrUpdate(user);user.setUsername("jonny");
tx.commit();sessionTwo.close();
Cria ou altera objeto
@regismelo
Hibernate
149
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
Hibernate
150
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:
• Você pode informar também qual o mecanismo de geração de chaves:
<id name="codigo" column="CD_LIVRO“/>
<id name="codigo" column="CD_LIVRO"><generator class="hilo">
<param name="table">NrLivro</param><param name="column">next_value</param>
</generator></id>
@regismelo
Hibernate
151
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
Hibernate
152
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
Hibernate
153
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
Hibernate
154
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
Hibernate
155
Geração de Chaves - Exemplos
• hilo
<id name="codigo" column="CD_LIVRO"><generator class="hilo">
<param name="table">NrLivro</param><param name="column">next_value</param>
</generator></id>
<id name="id" type="long" column="cat_id"><generator class="seqhilo">
<param name="sequence">hi_value</param><param name="max_lo">100</param>
</generator></id>
@regismelo
Hibernate
156
Geração de Chaves - Exemplos
• Identity columns and Sequences
• 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.
<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>
@regismelo
Hibernate
157
Recuperando dados
• Existem diversas formas de recuperar dados usando o Hibernate;
• Usando o método load:
• Usando o método get:
• 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.
Livro livro = (Livro)session.load( Cat.class, new Long(1234) );
Livro livro = (Livro)session.get( Cat.class, new Long(1234) );
@regismelo
Hibernate
158
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
Hibernate
159
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
Hibernate
160
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
Hibernate
161
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
Hibernate
162
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
Hibernate
163
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
Hibernate
164
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
Hibernate
165
Query Interface
• Executar uma query através do Hibernate pode ser feito de duas formas – através da própria session:
• Ou através da criação explícita de uma Query:
• 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.
List autores = session.find("from Autor as autor “ );
Query qry = session.createQuery("from Autor as autor“ );List autores = qry.list();
@regismelo
Hibernate
166
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
Hibernate
167
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
Hibernate
168
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
Hibernate
169
Métodos interessantes de Query
• Passagem de parâmetros – nunca use:
•
• Um usuário malicioso pode passar um parâmetro de forma que a consulta se comporte de outra forma:
• Use a passagem de parâmetros do Hibernate ao invés disso...
String queryString ="from Item i where i.description like '" + searchString + "'";List result = session.createQuery(queryString).list();
foo' and callSomeStoredProcedure() and 'bar' = 'bar
@regismelo
Hibernate
170
Métodos interessantes de Query
• Passagem de parâmetros:
• Métodos comuns para a passagem de parâmetro:
– setString, setBoolean, setInteger, setFloat, ...
– setParameter( String name, Object val )
String queryString = "from Item item where item.description like :searchString";
List result = session.createQuery(queryString).setString("searchString", searchString).list();
@regismelo
Hibernate
171
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
Hibernate
172
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
Hibernate
173
Módulo IX
XDocLet
@regismelo
Hibernate
174
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
Hibernate
175
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
Hibernate
176
Tarefa no ANT<target name="ejbdoclet" depends="init">
<taskdef name="ejbdoclet" classname="xdoclet.modules.ejb.EjbDocletTask" classpathref="xdoclet.path"> <classpath> <fileset dir="${xdoclet.lib.dir}" includes="*.jar"/> </classpath></taskdef>
<ejbdoclet destdir="${xdoclet.gen}" ejbspec="2.0" > <fileset dir="${src.dir}"> <include name="**/*Bean.java" /> </fileset> <remoteinterface/> <homeinterface/> <localhomeinterface/> <homeinterface/> <deploymentdescriptor destdir="${xdoclet.gen}" /> <jboss/> </ejbdoclet> </target>
Configura tarefa
define nova tarefa
<ejbdoclet/>
subtarefas
Gera arquivo do container
@regismelo
Hibernate
177
Algumas Tags EJB• @ejb.interface-method
– Declara um método como método de negócios
• @ejb.create-method– Declara método como método ejbCreate
• @ejb.home-method– Método Home
• @ejb.finder– define método find para interface home e local home
• @ejb.select– Método do tipo ejbSelect
• @ejb.pk-field– Cria método findByPrimaryKey na interface home
@regismelo
Hibernate
178
Tags de container
• O xdoclet pode gerar os arquivos XML específicos de cada servidor– <jboss/>
– <websphere/>
– <jonas/>
– <weblogic/>
– <jrun/>
– <resin-ejb-xml/> (resin-ejb.xml)
– <orion/> (orion-ejb-jar.xml)
– <hpas/>
@regismelo
Hibernate
179
Tarefas Xdoclet
• O Xdoclet possui diversas tarefas definidas para o ant.– <webdoclet/>
• web.xml
• Jakarta Struts
• WebWork
– <hibernatedoclet/>
– <jdodoclet/>
– <jmxdoclet/>
– <mockdoclet/>
@regismelo
Hibernate
180
Struts: struts-config.xml/** * @struts.action * path="/struts/foo" * * @struts.action-forward * name="success" * path="/struts/getAll.do" * redirect="false“
*/public final class StrutsAction extends Action { …
<action path="/struts/foo" type="test.web.StrutsAction" unknown="false" validate="true"> <forward name="success" path="/struts/getAll.do" redirect="false" />/>
struts-config.xml
@regismelo
Hibernate
181
Métodos find e ejbSelect()/*** @ejb.bean type="CMP"* name="ItemBean"* jndi-name="ejb/ItemBean"* view-type="both"** @ejb.finder signature="java.util.Collection findAll()"*/public abstract class ItemBean implements EntityBean {
public abstract class ItemBean implements EntityBean{ //various bean methods… //ejbSelect methods /** * @ejb.select query="SELECT OBJECT( i ) FROM Item AS i" */ public abstract java.util.Collection ejbSelectAll();}
@regismelo
Hibernate
182
Relacionamentos<relationships> <ejb-relation> <ejb-relation-name>OwnerToData</ejb-relation-name>
<ejb-relationship-role > <multiplicity>One</multiplicity> <relationship-role-source > <ejb-name>ch2.Owner</ejb-name>
</relationship-role-source> <cmr-field> <cmr-field-name>data</cmr-field-name> </cmr-field>
</ejb-relationship-role> <ejb-relationship-role > <multiplicity>One</multiplicity>
<relationship-role-source > <ejb-name>ch2.DataBean</ejb-name> </relationship-role-source> </ejb-relationship-role>
</ejb-relation></relationships>
/*** @ejb.interface-method* @ejb.relation
name="OwnerToData"relation-role="Owner"target-ejb= “examples.DataBean"
*/public abstract Data getData();
@regismelo
Hibernate
183
Novidades Java 1.5 (Tiger)• JSR – 175
– A Metadata Facility for the Java Programming Language
• “... would allow classes, interfaces, fields, and methods to be marked as having particular attributes.”
• JSR – 181– Web Services Metadata for the JavaTM Platform
• JSR – 227 – A Standard Data Binding & Data Access Facility for
J2EE • “An API and associated metadata format for declaratively
binding and accessing data in J2EE applications”
@regismelo
Hibernate
184
JSR - 175// Annotation type declaration with defaults on some memberspublic @interface RequestForEnhancement { int id(); // No default - must be specified in each annotation String synopsis(); // No default - must be specified in each annotation String engineer() default "[unassigned]"; String date() default "[unimplemented]";
}
@RequestForEnhancement( id = 2868724, synopsis = "Provide time-travel functionality", engineer = "Mr. Peabody", date = "4/1/2004")public static void travelThroughTime(Date destination) { ... }
@regismelo
Hibernate
185
WebServices MetaDatapublic interface CoffeeOrderIF extends java.rmi.Remote { public Coffee [] getPriceList() throws java.rmi.RemoteException; public String orderCoffee(String name, int quantity) throws java.rmi.RemoteException; }
public class CoffeeOrderImpl implements CoffeeOrderIF { public Coffee [] getPriceList() {...} public String orderCoffee(String name, int quantity) { ... }}
import javax.xml.rpc.*;
public class CoffeeOrder { @Remote public Coffee [] getPriceList() { ... } @Remote public String orderCoffee(String name, int quantity) { ... }}
Método é um web service
@regismelo
Hibernate
186
XDoclet e Hibernate
• XDoclet possui tasks que podem gerar os arquivos do Hibernate;
• A diretiva é muito interessante, pois evita a criação manual de vários arquivos XML;
• Vamos ver as principais diretivas do XDoclet e ao final, criar um build no ant para a geração dos devidos arquivos de configuração.
@regismelo
Hibernate
187
Class Level Tags
• A primeira tag é a ser vista é a que define a classe do hibernate
<hibernate-mapping><class name="bean.Autor" table="AUTOR" >
...</class>
</hibernate-mapping>
/*** @hibernate.class* table=“AUTOR"*/public class Autor { ...
@regismelo
Hibernate
188
Class Level Tags
• Definição de consultas
<query name="findItemsByDescription"><![CDATA[from Item item where item.description like :description]]></query>
/**@hibernate.query
name=“findItemsByDescription”query=“from Item item where item.description like :description”
*/public class Produto {
...}
@regismelo
Hibernate
189
Method Level Tags
• Mapeamento da coluna que identifica (chave primária)
– As entradas XDoclet sempre são feitos no método get
<id name="id" column="MESSAGE_ID"><generator class="native"/>
</id>
/*** @hibernate.id* column=“message_id"* generator-class="native"*/public Long getCodigo() {
return id;}
@regismelo
Hibernate
190
Method Level Tags
• Gerando chave a partir de um hilo
/*** @hibernate.id * column = "nr_seq_venda"* generator-class = "hilo" * * @hibernate.generator-param * name="table" * value= "nrVenda"* * @hibernate.generator-param * name="column"* value= "next_value"* */
@regismelo
Hibernate
191
Method Level Tags
• Mapeamento de uma coluna
/*** @hibernate.property* column="USERNAME"* length="16"* not-null="true"* unique="true"* update="false"*/public String getUsername() {
return username;}
@regismelo
Hibernate
192
Construindo o Build.xml
• Para fazer o XDoclet rodar executando os scripts do Hibernate precisamos escrever o build.xml;
• Uma boa idéia é separar o build do hibernate do build normal do seu sistema;
<!-- Task de geracao de codigo --><target name="generate">
<ant antfile="build-hibernate.xml" target="generate-hibernate"/> </target>
@regismelo
Hibernate
193
build-hibernate.xml
<?xml version="1.0" encoding="UTF-8"?><project name="oreilly" default="generate-hibernate" basedir=".">
<path id="xdoclet.lib.path"><fileset dir="${lib.dir}" includes="*.jar"/><fileset dir="${xdoclet.lib.dir}" includes="*.jar"/>
</path>
<target name="generate-hibernate"><taskdef name="hibernatedoclet"
classname="xdoclet.modules.hibernate.HibernateDocletTask" classpathref="xdoclet.lib.path"/>
<hibernatedoclet destdir="${hibernate.dir}"
mergeDir="${merge.dir}">
<fileset dir="${src.dir}"><include name="**/*.java" />
</fileset>
<hibernate version="2.0" />
</hibernatedoclet></target>
</project>
@regismelo
Hibernate
194
Exercício
• Altere os exercícios anteriores para suportar XDoclet e geração dos arquivos “hbm”
Consulte a resolução desse exercício em hibernate.ex.xdoclet
@regismelo
Hibernate
195
Para saber mais
@regismelo
Hibernate
196
Módulo X
Relacionamentos com Hibernate
@regismelo
Hibernate
197
Relacionamento com Hibernate
• O Hibernate permite o mapeamento de relacionamentos entre tabelas;
• Permite também o uso de coleções;
• Talvez esse seja um dos recursos mais poderosos e mais difíceis de implementar se estivéssemos fazendo um framework proprietário;
• Vamos ver primeiro o mapeamento de coleções...
• Para em seguida ver relacionamentos...
@regismelo
Hibernate
198
Coleções - Set
• Vamos imaginar o cadastro de itens de um produto;
• Cada item poderá ter uma imagem associada;
• Vejamos esse relacionamento:
• Esse tipo de mapeamento poderia ser representado por um Set em uma classe Java.
@regismelo
Hibernate
199
Coleções - Set
• Vejamos a classe:
private Set images = new HashSet();...public Set getImages() {
return this.images;}
public void setImages(Set images) {this.images = images;
}
@regismelo
Hibernate
200
Coleções - Set
• E o mapeamento:
<set name="images" lazy="true" table="ITEM_IMAGE">
<key column="ITEM_ID"/>
<element type="string" column="FILENAME" not-null="true"/>
</set>
Tabela relacionada
Chave primária em ITEM_IMAGE
Coluna que vai ser carregada
no Set
@regismelo
Hibernate
201
Coleções - List
• Vamos alterar ligeiramente nossa modelagem:
• Temos duas informações – a imagem e a posição (ordem) em que ela deverá aparecer.
@regismelo
Hibernate
202
Coleções - List
• Representaremos esse mapeamento da seguinte forma:
<list name="images" lazy="true" table="ITEM_IMAGE"><key column="ITEM_ID"/><index column="POSITION"/><element type="string" column="FILENAME"
not-null="true"/></list>
Tabela relacionada
Chave primária em ITEM_IMAGE
Coluna que vai ser carregada
no Set
Coluna de índice da lista
(define a posição)
@regismelo
Hibernate
203
Coleções - List
• A classe java representando um List...
• Você pode usar arrays puros também para fazer esse mapeamento, mas é desaconselhável pois o Hibernate não poderá realizar Lazy Loading se você fizer isso.
private List images = new ArrayList();...public List getImages() {
return this.images;}
public void setImages(List images) {this.images = images;
}
@regismelo
Hibernate
204
Mapeando um Set (1 para Muitos)
• Relembrando o relacionamento entre autor e livros...
LivroAutor
cd_autor: int NOT NULL (FK)cd_livro: int NOT NULL (FK)
nr_ordem: tinyint NULL
Loja
cd_loja: char(4) NOT NULL
nm_loja: varchar(40) NULLds_endereco: varchar(40) NULLds_cidade: varchar(20) NULLds_estado: char(2) NULLnr_cep: char(5) NULL
Vendas
nr_seq_venda: varchar(20) NOT NULL
cd_loja: char(4) NOT NULL (FK)cd_livro: int NOT NULL (FK)dt_venda: datetime NOT NULLqt_livros: smallint NOT NULL
Cargo
cd_cargo: smallint IDENTITY(1,1)
ds_cargo: varchar(50) NOT NULL
EditoraLogo
cd_editora: char(4) NOT NULL (FK)
logo: image NULL
Funcionario
cd_funcionario: int NOT NULL
nm_funcionario: varchar(50) NOT NULLcd_cargo: smallint NOT NULL (FK)cd_editora: char(4) NOT NULL (FK)dt_contratacao: datetime NOT NULL
Autor
cd_autor: int NOT NULL
nm_autor: varchar(40) NOT NULLds_fone: char(12) NOT NULLds_endereco: varchar(40) NULLds_cidade: varchar(20) NULLds_estado: char(2) NULLnr_cep: char(5) NULLid_contratado: bit NOT NULL
Editora
cd_editora: char(4) NOT NULL
nm_editora: varchar(40) NULLnm_cidade: varchar(20) NULLnm_estado: char(2) NULLnm_pais: varchar(30) NULL
Livro
cd_livro: int NOT NULL
nm_livro: varchar(80) NOT NULLcd_editora: char(4) NULL (FK)vr_preco: money NULLds_notas: varchar(200) NULLdt_publicacao: datetime NOT NULLcd_tipo: char(10) NULL (FK)
TipoLivro
cd_tipo: char(10) NOT NULL
ds_tipo: char(40) NOT NULL
@regismelo
Hibernate
205
Mapeando um Set (Relacionamento N para N)
• Vamos realizar o mapeamento dessa classe usando o Hibernate e XDoclet;
• Precisamos informar:
– A tabela de relacionamento;
– A coluna chave a partir da classe autor;
– A classe de relacionamento;
– E a coluna que origina esse relacionamento.
• Vejamos…
@regismelo
Hibernate
206
Relacionamento entre Autor e Livro
/** * @hibernate.set * table = "LivroAutor" * lazy = "true" * cascade = "save-update" * * @hibernate.collection-key * column = "cd_autor" * * @hibernate.collection-many-to-many * class = "bean.Livro" * column = "cd_livro" * */public Set getLivros() {
return Livros;}
@regismelo
Hibernate
207
Mapeando um Set (Relacionamento N para N)
• Recuperar agora os livros publicados pelo Autor X é fácil:
Autor autor = (Autor)session.get(Autor.class, new Integer(1));
Set livros = autor.getLivros();
for (Iterator iter = livros.iterator(); iter.hasNext();) {Livro livro = (Livro) iter.next();
out.println( "Livro --> " + livro.getNome() + ", Valor: " + livro.getPreco() );
TipoLivro tipoLivro = livro.getTipoLivro();
if ( tipoLivro != null ) { out.println("Tipo do Livro --> " + tipoLivro.getTipo() );}out.println( "<br>" );
}
@regismelo
Hibernate
208
Exercício
• Represente o relacionamento entre Autor e Livro;
• Recupere todos os autores e todos os livros publicados por eles.
Consulte a resolução desse exercício em hibernate.ex.xdoclet - AutorServlet
@regismelo
Hibernate
209
@regismelo
Hibernate
210
LivroAutor
cd_autor: int NOT NULL (FK)cd_livro: int NOT NULL (FK)
nr_ordem: tinyint NULL
Loja
cd_loja: char(4) NOT NULL
nm_loja: varchar(40) NULLds_endereco: varchar(40) NULLds_cidade: varchar(20) NULLds_estado: char(2) NULLnr_cep: char(5) NULL
Vendas
nr_seq_venda: varchar(20) NOT NULL
cd_loja: char(4) NOT NULL (FK)cd_livro: int NOT NULL (FK)dt_venda: datetime NOT NULLqt_livros: smallint NOT NULL
Cargo
cd_cargo: smallint IDENTITY(1,1)
ds_cargo: varchar(50) NOT NULL
EditoraLogo
cd_editora: char(4) NOT NULL (FK)
logo: image NULL
Funcionario
cd_funcionario: int NOT NULL
nm_funcionario: varchar(50) NOT NULLcd_cargo: smallint NOT NULL (FK)cd_editora: char(4) NOT NULL (FK)dt_contratacao: datetime NOT NULL
Autor
cd_autor: int NOT NULL
nm_autor: varchar(40) NOT NULLds_fone: char(12) NOT NULLds_endereco: varchar(40) NULLds_cidade: varchar(20) NULLds_estado: char(2) NULLnr_cep: char(5) NULLid_contratado: bit NOT NULL
Editora
cd_editora: char(4) NOT NULL
nm_editora: varchar(40) NULLnm_cidade: varchar(20) NULLnm_estado: char(2) NULLnm_pais: varchar(30) NULL
Livro
cd_livro: int NOT NULL
nm_livro: varchar(80) NOT NULLcd_editora: char(4) NULL (FK)vr_preco: money NULLds_notas: varchar(200) NULLdt_publicacao: datetime NOT NULLcd_tipo: char(10) NULL (FK)
TipoLivro
cd_tipo: char(10) NOT NULL
ds_tipo: char(40) NOT NULL