Hibernate

Preview:

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