210
@regismelo Hibernate 1 Persistência com Hibernate Régis Melo @regismelo

Hibernate

Embed Size (px)

DESCRIPTION

Material do Curso de Hibernate 2008

Citation preview

Page 1: Hibernate

@regismelo

Hibernate

1

Persistência com Hibernate

Régis Melo@regismelo

Page 2: Hibernate

@regismelo

Hibernate

2

Missão

Apresentar, motivar e exercitar mecanismos de persistência em Java, com enfoque no framework Hibernate.

Page 3: Hibernate

@regismelo

Hibernate

3

Metodologias

• Exposição e discussão teóricas;

• Exercícios práticos de projeto e modelagem em laboratório.

Page 4: Hibernate

@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.

Page 5: Hibernate

@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.

Page 6: Hibernate

@regismelo

Hibernate

6

Livros sugeridos

Page 7: Hibernate

@regismelo

Hibernate

7

Prepara os teus trabalhos de fora, apronta bem o teu campo; e depois edifica a tua casa.

Provérbios 24:27

Page 8: Hibernate

@regismelo

Hibernate

8

Módulo I

E no princípio, era o JDBC…

Page 9: Hibernate

@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…

Page 10: Hibernate

@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?

Page 11: Hibernate

@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?

Page 12: Hibernate

@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

Page 13: Hibernate

@regismelo

Hibernate

13

API JDBC

Page 14: Hibernate

@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

Page 15: Hibernate

@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.

Page 16: Hibernate

@regismelo

Hibernate

16

Tipo 1 - Ponte

• JDBC-ODBC BRIDGE + ODBC DRIVER

AplicaçãoJAVA

JDBC-ODBCBridge

DriverODBC

Dados

APIODBC

APIJDBC

Page 17: Hibernate

@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.

Page 18: Hibernate

@regismelo

Hibernate

18

Tipo 2 – Java Nativo

• Java / Nativo

AplicaçãoJAVA

DriverJDBC

Dados

APINativaSGBD

APIJDBC

Page 19: Hibernate

@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.

Page 20: Hibernate

@regismelo

Hibernate

20

Tipo 3 – Gateway

• Servidor de acesso intermediário

AplicaçãoJAVA

Driver JDBCDriverNativo

Dados

JDBCDriverServer

APIJDBC

Page 21: Hibernate

@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.

Page 22: Hibernate

@regismelo

Hibernate

22

Tipo 4 – All Java Driver

• All Java Driver

AplicaçãoJAVA

Driver JDBC DadosAPI

JDBC

Page 23: Hibernate

@regismelo

Hibernate

23

Page 24: Hibernate

@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

Page 25: Hibernate

@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");

Page 26: Hibernate

@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");

Page 27: Hibernate

@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” );

Page 28: Hibernate

@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” );

}

Page 29: Hibernate

@regismelo

Hibernate

29

Executando uma consulta• E ao final de tudo, devemos fechar o statement

e a conexão.

...stmt.close();

conn.close();

Page 30: Hibernate

@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

Page 31: Hibernate

@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;

Page 32: Hibernate

@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

Page 33: Hibernate

@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.

Page 34: Hibernate

@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

Page 35: Hibernate

@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, ... );

Page 36: Hibernate

@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) );}

Page 37: Hibernate

@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, ... ).

Page 38: Hibernate

@regismelo

Hibernate

38

ResultSet e os métodos get

Page 39: Hibernate

@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

Page 40: Hibernate

@regismelo

Hibernate

40

Para saber mais

• http://java.sun.com/docs/books/tutorial/jdbc/index.html

Page 41: Hibernate

@regismelo

Hibernate

41

Módulo II

Pool de conexões

Page 42: Hibernate

@regismelo

Hibernate

42

Entendendo o problema...

• Em aplicações cliente/servidor, tipicamente temos, para cada cliente uma conexão com o banco de dados...

Page 43: Hibernate

@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...

Page 44: Hibernate

@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.

Page 45: Hibernate

@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

Page 46: Hibernate

@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.

Page 47: Hibernate

@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

Page 48: Hibernate

@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.

Page 49: Hibernate

@regismelo

Hibernate

49

Pool de Conexões no TomCat

Page 50: Hibernate

@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

Page 51: Hibernate

@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

Page 52: Hibernate

@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).

Page 53: Hibernate

@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.

Page 54: Hibernate

@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).

Page 55: Hibernate

@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

Page 56: Hibernate

@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/

Page 57: Hibernate

@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.

Page 58: Hibernate

@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

Page 59: Hibernate

@regismelo

Hibernate

59

Para saber mais

• http://jakarta.apache.org/tomcat/tomcat-5.0-doc/jndi-resources-howto.html

Page 60: Hibernate

@regismelo

Hibernate

60

Módulo III

Data Access Objects

Page 61: Hibernate

@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!

Page 62: Hibernate

@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

Page 63: Hibernate

@regismelo

Hibernate

63

Estrutura de um DAO

Page 64: Hibernate

@regismelo

Hibernate

64

Estrutura de um DAO

Page 65: Hibernate

@regismelo

Hibernate

65

DAO e Abstract Factory

• No caso da implementação do DAO é útil usar um Abstract Factory para instanciar as classes.

Page 66: Hibernate

@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

{ ... }

Page 67: Hibernate

@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

Page 68: Hibernate

@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);

} }

Page 69: Hibernate

@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();

...

}

}____________________________________________________________________________

Page 70: Hibernate

@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

Page 71: Hibernate

@regismelo

Hibernate

71

Para saber mais

• http://java.sun.com/j2ee/patterns/DataAccessObject.html

• http://www.fluffycat.com/java/JavaNotes-GoFAbstractFactory.html

Page 72: Hibernate

@regismelo

Hibernate

72

Módulo IV

Frameworks de Persistência

Page 73: Hibernate

@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.

Page 74: Hibernate

@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.

Page 75: Hibernate

@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

Page 76: Hibernate

@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...

Page 77: Hibernate

@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.

Page 78: Hibernate

@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

Page 79: Hibernate

@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.

Page 80: Hibernate

@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.

Page 81: Hibernate

@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.

Page 82: Hibernate

@regismelo

Hibernate

82

Módulo V

Hibernating…

Page 83: Hibernate

@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.

Page 84: Hibernate

@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...

}

Page 85: Hibernate

@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() );

Page 86: Hibernate

@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();

Page 87: Hibernate

@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)

Page 88: Hibernate

@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();

Page 89: Hibernate

@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

Page 90: Hibernate

@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...

Page 91: Hibernate

@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

Page 92: Hibernate

@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;

Page 93: Hibernate

@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();

Page 94: Hibernate

@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

Page 95: Hibernate

@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...

Page 96: Hibernate

@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

Page 97: Hibernate

@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

Page 98: Hibernate

@regismelo

Hibernate

98

Módulo V

Ant

Page 99: Hibernate

@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 é?

Page 100: Hibernate

@regismelo

Hibernate

100

Integração contínua com Ant

Page 101: Hibernate

@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 +

Page 102: Hibernate

@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.

Page 103: Hibernate

@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

Page 104: Hibernate

@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?

Page 105: Hibernate

@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?

Page 106: Hibernate

@regismelo

Hibernate

106

Ant: Como funciona?

Page 107: Hibernate

@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

Page 108: Hibernate

@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

Page 109: Hibernate

@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>

Page 110: Hibernate

@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

Page 111: Hibernate

@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

Page 112: Hibernate

@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

Page 113: Hibernate

@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

Page 114: Hibernate

@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

Page 115: Hibernate

@regismelo

Hibernate

115

Para saber mais

• http://ant.apache.org/

• Exemplos de build filesdos projetos Jakarta

Page 116: Hibernate

@regismelo

Hibernate

116

Módulo VII

Hibernate – Entendendo a Arquitetura

Page 117: Hibernate

@regismelo

Hibernate

117

Arquitetura

Page 118: Hibernate

@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).

Page 119: Hibernate

@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

Page 120: Hibernate

@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.

Page 121: Hibernate

@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);

Page 122: Hibernate

@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.

Page 123: Hibernate

@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.

Page 124: 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.

Page 125: Hibernate

@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.

Page 126: Hibernate

@regismelo

Hibernate

126

Configurações

Page 127: Hibernate

@regismelo

Hibernate

127

Configurações

Page 128: Hibernate

@regismelo

Hibernate

128

Configurações

Page 129: Hibernate

@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...

Page 130: Hibernate

@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...

Page 131: Hibernate

@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);}

}}

Page 132: Hibernate

@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…

Page 133: Hibernate

@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();

}}

Page 134: Hibernate

@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…

Page 135: Hibernate

@regismelo

Hibernate

135

Para saber mais

• Hibernate in Action, chapter 3;

Page 136: Hibernate

@regismelo

Hibernate

136

Módulo VIII

Trabalhando com Persistent Objects

Page 137: Hibernate

@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.

Page 138: Hibernate

@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…

Page 139: Hibernate

@regismelo

Hibernate

139

Persistence Lifecycle

Page 140: Hibernate

@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.

Page 141: Hibernate

@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

Page 142: Hibernate

@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

Page 143: Hibernate

@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…

Page 144: Hibernate

@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

Page 145: Hibernate

@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

Page 146: Hibernate

@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();

Page 147: Hibernate

@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

Page 148: Hibernate

@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

Page 149: Hibernate

@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();

Page 150: Hibernate

@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>

Page 151: Hibernate

@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.

Page 152: 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

Page 153: Hibernate

@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.

Page 154: Hibernate

@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.

Page 155: Hibernate

@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>

Page 156: Hibernate

@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>

Page 157: Hibernate

@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) );

Page 158: Hibernate

@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 );

Page 159: Hibernate

@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...

Page 160: Hibernate

@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();

Page 161: Hibernate

@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();

Page 162: Hibernate

@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();

Page 163: Hibernate

@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);

Page 164: Hibernate

@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

Page 165: Hibernate

@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();

Page 166: Hibernate

@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];....

}

Page 167: Hibernate

@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();

Page 168: Hibernate

@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();

Page 169: Hibernate

@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

Page 170: Hibernate

@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();

Page 171: Hibernate

@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>

Page 172: Hibernate

@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

Page 173: Hibernate

@regismelo

Hibernate

173

Módulo IX

XDocLet

Page 174: Hibernate

@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.

Page 175: Hibernate

@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()");

} . . .

Page 176: Hibernate

@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

Page 177: Hibernate

@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

Page 178: Hibernate

@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/>

Page 179: Hibernate

@regismelo

Hibernate

179

Tarefas Xdoclet

• O Xdoclet possui diversas tarefas definidas para o ant.– <webdoclet/>

• web.xml

• Jakarta Struts

• WebWork

– <hibernatedoclet/>

– <jdodoclet/>

– <jmxdoclet/>

– <mockdoclet/>

Page 180: Hibernate

@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

Page 181: Hibernate

@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();}

Page 182: Hibernate

@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();

Page 183: Hibernate

@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”

Page 184: Hibernate

@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) { ... }

Page 185: Hibernate

@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

Page 186: Hibernate

@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.

Page 187: Hibernate

@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 { ...

Page 188: Hibernate

@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 {

...}

Page 189: Hibernate

@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;}

Page 190: Hibernate

@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"* */

Page 191: Hibernate

@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;}

Page 192: Hibernate

@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>

Page 193: Hibernate

@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>

Page 194: Hibernate

@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

Page 195: Hibernate

@regismelo

Hibernate

195

Para saber mais

Page 196: Hibernate

@regismelo

Hibernate

196

Módulo X

Relacionamentos com Hibernate

Page 197: 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...

Page 198: Hibernate

@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.

Page 199: Hibernate

@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;

}

Page 200: Hibernate

@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

Page 201: Hibernate

@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.

Page 202: Hibernate

@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)

Page 203: Hibernate

@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;

}

Page 204: Hibernate

@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

Page 205: Hibernate

@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…

Page 206: Hibernate

@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;}

Page 207: Hibernate

@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>" );

}

Page 208: Hibernate

@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

Page 209: Hibernate

@regismelo

Hibernate

209

Page 210: Hibernate

@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