SlideShare uma empresa Scribd logo
1 de 210
Hibernate




             Persistência com Hibernate

                     Régis Melo
                      @regismelo




@regismelo                                    1
Hibernate




                   Missão


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




  @regismelo                                 2
Hibernate




                 Metodologias
• Exposição e discussão teóricas;
• Exercícios práticos de projeto e modelagem em
  laboratório.




  @regismelo                                          3
Hibernate




     O que esse curso não cobre ou não é?

Não Cobre:
• Conceitos gerais de Java e da plataforma J2SE;
• Conceitos gerais da plataforma J2EE – Servlets e JSP;
Não é:
• O primeiro curso para aprender como acessar bancos de
  dados relacionais a partir de Java;
• Esse curso não é para você se você não sabe aonde
  colocar aquele arquivo “.class” que acabou de compilar.


  @regismelo                                                4
Hibernate




                 Antes de iniciar…

Vamos nos apresentar
• Nome;
• Empresa;
• Experiência com programação;
• Razões de estar fazendo esse treinamento;
• Expectativas desse curso.




 @regismelo                                       5
Hibernate




             Livros sugeridos




@regismelo                          6
Hibernate




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


                                Provérbios 24:27




@regismelo                                         7
Hibernate




                      Módulo I



             E no princípio, era o JDBC…




@regismelo                                     8
Hibernate




              E no princípio, era o JDBC…
• Existem diversas tecnologias de acesso a banco de
  dados utilizando Java;
• A mais simples dela, com certeza é o JDBC;
• Relembrando JDBC…




 @regismelo                                               9
Hibernate



                 O que é JDBC?
• É uma API Java para acesso a banco de dados
  utilizando SQL;

• Permite a independência de banco de dados;

• A forma de acesso a um banco de dados é exatamente
  igual a outro banco de dados.

• A independência entre bancos de dados pode ser
  prejudicada pela forma como você utiliza SQL
  (comandos SQL proprietários).

 @regismelo                                            10
Hibernate



                   O que JDBC faz?
De maneira simplificada JDBC faz seis coisas:


   1 – Estabelece conexão com o banco de dados.
   2 – Executa consultas.
   3 – Recebe o conjunto de resultados das consultas.
   4 – Executa stored procedures.
   5 – Obtém informações sobre o banco de dados, tabelas,
     índices, visões, e stored procedures.
   6 – Gerencia transações.




 @regismelo                                                 11
Hibernate



                       API JDBC
• A API JDBC está definida no pacote java.sql – a maior
  parte da API são interfaces;

• O J2SE – Java 2 Standard Edition disponibiliza uma única
  implementação JDBC chamada JDBC-ODBC Bridge (que
  faz a ponte entre JDBC e ODBC);

• Para acessar o seu banco de dados utilizando JDBC você
  deverá obter um driver do fornecedor do SGBD (o caso
  mais comum), comprar de uma empresa fornecedora de
  drivers ou usar produtos de código aberto.



 @regismelo                                                   12
Hibernate
             API JDBC




@regismelo                  13
Hibernate



               Tipos de driver JDBC
• Existem 4 tipos de drivers JDBC:

    –   Tipo 1  JDBC-ODBC Bridge;
    –   Tipo 2  Java Nativo
    –   Tipo 3  Gateway
    –   Tipo 4  All Java Driver




 @regismelo                               14
Hibernate



                     Tipo 1 - Ponte
• Convertem chamadas JDBC em chamadas ODBC e as
  envia ao driver ODBC;
• Possibilitam o uso indireto de drivers ODBC;
• Necessidade de configurar o ODBC;
• Mais apropriado para uma rede corporativa ou para
  aplicações usando arquitetura em três camadas;

Ex: sun jdbc-odbc bridge.




 @regismelo                                           15
Hibernate



                  Tipo 1 - Ponte
• JDBC-ODBC BRIDGE + ODBC DRIVER


 Aplicação
  JAVA                             Dados




    API       JDBC-ODBC    API     Driver
   JDBC         Bridge    ODBC     ODBC




 @regismelo                                     16
Hibernate



               Tipo 2 – Java Nativo
• Convertem chamadas JDBC em chamadas nativas do
  banco e comunicam-se diretamente com o SGBD;
• Apresentam ganhos de performance;
• O cliente do banco de dados é necessário;
• Menor portabilidade.

Ex: IBM DB2.




 @regismelo                                        17
Hibernate



              Tipo 2 – Java Nativo
• Java / Nativo



  Aplicação
   JAVA                              Dados




                            API
      API         Driver
                           Nativa
     JDBC         JDBC
                           SGBD




 @regismelo                                      18
Hibernate




                 Tipo 3 – Gateway
• Convertem chamadas JDBC em um protocolo de rede
  independente do SGBD e comunicam-se com um
  gateway que traduz estas requisições para o protocolo
  específico do SGBD;

Ex: borland datagateway.




 @regismelo                                               19
Hibernate



                Tipo 3 – Gateway
• Servidor de acesso intermediário



  Aplicação
   JAVA                                Dados




                              JDBC
      API                              Driver
               Driver JDBC    Driver
     JDBC                              Nativo
                              Server




 @regismelo                                         20
Hibernate



              Tipo 4 – All Java Driver
• Convertem chamadas JDBC para um protocolo de rede
  usado diretamente pelo SGBD;

• São geralmente específicos para determinada base de
  dados;

Ex: Sybase, SQL Server, Oracle.




 @regismelo                                             21
Hibernate



              Tipo 4 – All Java Driver
• All Java Driver




 Aplicação           API
                           Driver JDBC   Dados
  JAVA              JDBC




 @regismelo                                      22
Hibernate




@regismelo       23
Hibernate



              Abrindo uma conexão com o BD
• Para abrir uma conexão com o banco de dados,
  precisamos primeiro de um driver JDBC;
• Utilizaremos o driver do Microsoft SQL Server nos
  próximos exemplos;
• O driver JDBC do MSSQL pode ser baixado no site
  www.microsoft.com/sql;
• É free e é um driver tipo 4;
• Três arquivos são necessários:
   – msbase.jar
   – mssqlserver.jar
   – msutil.jar


 @regismelo                                               24
Hibernate



         Abrindo uma conexão com o BD
• O nosso primeiro passo é registrar o driver JDBC;
• O driver do SQL Server está disponível em
  “mssqlserver.jar”, “msbase.jar” e “msutil.jar”;
• Você deverá consultar a documentação do seu
  fornecedor para saber qual é a classe e pacote do driver
  JDBC.

Class.forName(
  "com.microsoft.jdbc.sqlserver.SQLServerDriver");




 @regismelo                                              25
Hibernate



          Abrindo uma conexão com o BD
• O segundo passo é abrir a conexão com o
  banco de dados;
• Utilize a classe DriverManager para fazer isso;
• Os parâmetros passados para o método
  getConnection variam de driver para driver –
  consulte a documentação do seu driver.
  ...
  java.sql.Connection conn;
  conn = DriverManager.getConnection(
     "jdbc:microsoft:sqlserver://localhost:1433
     ;DatabaseName=<<nome do seu database>>;
     SelectMethod=cursor");
 @regismelo                                         26
Hibernate




              Executando uma consulta
• Com a conexão com o banco de dados obtida,
  podemos executar consultas SQL:

  ...
  java.sql.Connection conn;
  conn = DriverManager.getConnection(
   "jdbc:microsoft:sqlserver://localhost:1433
  ;DatabaseName=dbExemplo;SelectMethod=cursor");
  Statement stmt = conn.createStatement();
  ResultSet rs = stmt.executeQuery( “Select * from
  authors” );


 @regismelo                                          27
Hibernate




              Executando uma consulta
• O objeto ResultSet guarda os dados retornados
  pela consulta:

  ...
  Resultset rs = stmt.executeQuery( “Select * from contas”
  );
  while ( rs.next() ) {
      String cdConta = rs.getString( “codigo” );
      double sdConta = rs.getDouble( “saldo” );
  }




 @regismelo                                              28
Hibernate




              Executando uma consulta
• E ao final de tudo, devemos fechar o statement
  e a conexão.

  ...
  stmt.close();
  conn.close();




 @regismelo                                        29
Hibernate



                 Executando uma consulta
Statement stmt; ResultSet rs;
try {
   Class.forName( "com.mysql.jdbc.Driver");
   java.sql.Connection conn;
   conn = DriverManager.getConnection(
     "jdbc:mysql://localhost/test?user=root&password=");
   stmt = conn.createStatement();
   rs = stmt.executeQuery( “Select * from contas” );
   while ( rs.next() ) {
         String cdConta = rs.getString( “codigo” );
         double sdConta = rs.getDouble( “saldo” );
   }
}
catch (ClassNotFoundException e){System.out.println(e);// Trate o
   erro! }
catch (SQLException e ) {System.out.println(e); // Trate o erro! }
finally { // Feche o statment e a conexão com o BD }

    @regismelo                                                       30
Hibernate




                         API JDBC
• DriverManager  Utilizada para obter a
  conexão com o banco de dados
• Principais métodos:

    – Connection getConnection( String url )
         • Obtém uma conexão com o banco de dados;
    – Connection getConnection ( String url, String
      user, String pass )
         • Obtém uma conexão com o BD passando usuário e
           senha;

 @regismelo                                                31
Hibernate


                               API JDBC
• Connection  Representa uma conexão com o BD
• Principais métodos:
   – Statement createStatement()
         • Cria um statement, que representa um comando SQL a ser
           enviado;
    – PreparedStatement prepareStatement()
         • Cria um statement pré-compilado (veja definições adiante)
    – setAutoCommit( boolean )
         • Indica se deverá se trabalhar no modo AutoCommit;
    – commit
         • Confirma as alteração no banco de dados
    – rollback
         • Desfaz transações no BD
    – close
         • Fecha a conexão com o banco de dados
 @regismelo                                                                32
Hibernate




                              API JDBC
• Statement  Representa um comando SQL;
• Principais métodos:
   – ResultSet executeQuery( String )
         • Executa um comando SQL e obtém o resultado;
    – executeUpdate( String )
         • Executa um comando SQL que não retorna resultado (um update,
           delete ou insert);
    – addBatch( String )
         • Adiciona um comando SQL em um bloco;
    – executeBatch()
         • Executa comandos adicionados com addBatch
    – getConnection
         • Retorna a conexão associada ao statement
    – setMaxRows( int )
         • Especifica a quantidade de linhas máxima retornada.
 @regismelo                                                               33
Hibernate




                          API JDBC
• Exemplo de um executeUpdate
  String sql = “update conta set saldo = 1000“;
  Statement stmt = conn.createStatement( sql );

  stmt.executeUpdate();




                          throws SQLException




 @regismelo                                           34
Hibernate




                            API JDBC
• PreparedStatement  Representa um comando
  SQL pré-compilado;
• Principais métodos:
    – ResultSet executeQuery( String )
         • Executa um comando SQL e obtém o resultado;
    – executeUpdate( String )
         • Executa um comando SQL que não retorna resultado (um
           update, delete ou insert);
    – setXXXX( indice, valor )
         • Passa um parâmetro para o result set, onde XXXX é o tipo
           do parâmetro (setInt, setDate, setLong, setString, ... );


 @regismelo                                                            35
Hibernate




                       API JDBC
• PreparedStatement é útil quando você irá submeter o mesmo
  comando diversas vezes pois o banco só faz o parse da
  query uma vez.
  String sql = "select * from conta where codigo = ? "
  PreparedStatement stmt =
      conn.prepareStatement( sql );

  stmt.setInt( 1, 50 );
  ResultSet rs = stmt.executeQuery();

  while ( rs.next() )
  {
      System.out.println( rs.getString(1) );
  }




 @regismelo                                                  36
Hibernate




                                   API JDBC
• ResultSet  Representa o resultado de uma consulta;
• Principais métodos:
   – close
         • Fecha o resultset


    – ResultSetMetaData getMetaData()
         • Retorna informações sobre as colunas do result set.


    – getXXXX( String ) / getXXXX( int )
         • Retorna a informação de uma coluna, onde XXXX representa o tipo
           da coluna (getInt, getDate, getLong, getString, ... ).




 @regismelo                                                             37
Hibernate


             ResultSet e os métodos get




@regismelo                                    38
Hibernate




                           Exercício

• No banco de dados disponibilizado existe uma
  tabela chamada Autores (ver modelo de dados no
  final do material);
• Faça uma classe Java que inclui novos autores
  nessa tabela usando Statement e
  PreparedStatement – qual a diferença entre o
  código gerado para os dois?

  (Dica: Use o profiler do SQL Server para ver os
   comandos gerados pelo JDBC)
                                                    30 minutos
 @regismelo                                              39
Hibernate



                 Para saber mais


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




 @regismelo                                         40
Hibernate




                 Módulo II



             Pool de conexões




@regismelo                          41
Hibernate



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




 @regismelo                                        42
Hibernate



              Entendendo o problema...
• Manter uma conexão para cada cliente pode gerar
  carga desnecessário do servidor de banco de
  dados;

• Boa parte do tempo a conexão não é necessária
  no cliente;

• Cada conexão consome recursos no banco de
  dados...


 @regismelo                                       43
Hibernate



               Pool de Conexões
• O ideal é que os clientes “compartilhassem” as
  conexões com o banco de dados;

• Poderíamos abrir um determinado número de
  conexões e deixá-las em um “pool”;

• Cada vez que uma conexão for necessária, ela
  será obtida desse pool.



 @regismelo                                        44
Hibernate



                  Pool de Conexões

<<servlet>>           <<servlet>>      <<servlet>>     <<servlet>>
  Cliente                 X                Y               Z




                           Container




                        Pool de Conexões
<<Conexão 1>>   << Conexão 2 >> <<Conexão 3>>        << Conexão 4 >>




@regismelo                                                             45
Hibernate



                Pool de Conexões
• Cada cliente (Servlet, JSP ou qualquer outro tipo),
  quando precisa de uma conexão, solicita ao
  container;
• O container:
   – Verifica se existem conexões no pool;
   – Disponibiliza uma conexão para o cliente
• O cliente:
   – Usa a conexão;
   – E ao final, devolve-a para o pool.

 @regismelo                                          46
Hibernate



                     Pool de Conexões
                                Container
<<servlet>>                                        Connection Pool
              Solicita uma conexão
  Cliente                                      Existe conexões
                                             disponíveis no pool?

                                                               Não

                                             Sim         Obtém uma nova
                                                             conexão




                                          Devolve conexão
                                        com o Banco de dados



@regismelo                                                                47
Hibernate



               Pool de Conexões
• É ainda função do pool de conexões saber
  quando o pool deve crescer ou diminuir;
• Usualmente isso é configurável pelo administrador
  do sistema;
• Algo como
   – Número máximo de conexões;
   – Número mínimo de conexões.




 @regismelo                                        48
Hibernate



             Pool de Conexões no TomCat




@regismelo                                    49
Hibernate



               Pool de Conexões no TomCat
• O pool de conexões no TomCat é implementado
  por um projeto chamado Jakarta DBCP;

• DBCP = Database Connection Pooling;

• Vamos configurar o pool de conexões para
  nossa aplicação chamada HTeste...


         Demo  Configurando Pool de Conexões...
  http://www.softsite.com.br/cursos/hibernate/demo/Configurando_Pool_de_Conexoes_TomCat5_viewlet_swf.html



 @regismelo                                                                                            50
Hibernate



                   Pool de Conexões no TomCat
Nome da conexão JNDI

String DataSource
    Específico do Driver JDBC
Nome da Classe JDBC




Quantidade máxima de
   conexões abertas pelo
   pool

Quantidade máxima de
   conexões não
   utilizadas (idle)

Tempo máximo que o
   cliente irá esperar por
   uma conexão até uma          Query de validação – usada para
   exceção ser disparada           verificar se a conexão ainda
                                   é válida
    @regismelo                                                        51
Hibernate



              Pool de Conexões no TomCat
• Configurações para o SQL Server, usando o driver
  JDBC tipo 4 da Microsoft:

    – JNDI name:
      O padrão especifica iniciar com “jdbc/”
    – Data Source URL:
      jdbc:microsoft:sqlserver://<serverName>:1433;DatabaseN
      ame=<dbName>;SelectMethod=cursor
    – JDBC Driver Class:
      com.microsoft.jdbc.sqlserver.SQLServerDriver
    – User Name:
      Nome do usuário que você irá se conectar no banco de
      dados (“sa”, no SQL Server = System Administrator).

 @regismelo                                                 52
Hibernate



              Pool de Conexões no TomCat
• Configurações para o SQL Server, usando o driver
  JDBC tipo 4 da Microsoft:

    – Password:
      Senha. Na instalação default, vazio
    – Max. Active Connections:
      Número máximo de conexões com o banco de dados que
      o pool irá gerenciar. Em desenvolvimento, deixe esse
      valor bem pequeno.
    – Max. Idle Connections:
      Número de conexões que sempre deverá estar aberta. Em
      desenvolvimento, deixe esse valor bem pequeno.

 @regismelo                                               53
Hibernate



              Pool de Conexões no TomCat
• Configurações para o SQL Server, usando o driver
  JDBC tipo 4 da Microsoft:

    – Max. Wait for Connection:
      Tempo máximo em milisegundos que o container irá
      esperar para uma conexão ser disponibilizada (quando
      não existir nenhuma conexão livre). Passado esse tempo
      é disparada uma exceção.
    – Validation Query:
      Uma query válida que pode ser usada pelo pool para
      validar conexões antes delas serem retornadas para a
      aplicação. Se especificado, deverá retornar pelo menos
      uma linha (usualmente uma query simples e rápida).


 @regismelo                                                    54
Hibernate



              Pool de Conexões no TomCat
• Após criado o pool de conexões no TomCat,
  copie os arquivos “jar” para
  <tomcat>/common/lib;

• No caso do SQL Server:
    – msbase.jar
    – mssqlserver.jar
    – msutil.jar



 @regismelo                                       55
Hibernate



          Obtendo uma conexão do pool...
• O pool de conexões que acabamos de configurar fica
  disponível no TomCat através de JNDI;
• JNDI = Java Naming and Directory Interface;
• Uma API para serviços de diretório;

       “The JNDI is part of the Java platform, providing
      applications based on Java technology with a unified
    interface to multiple naming and directory services. You
        can build powerful and portable directory-enabled
            applications using this industry standard.”
                                http://java.sun.com/products/jndi/

 @regismelo                                                     56
Hibernate



              Obtendo uma conexão do pool...
InitialContext iniContext;
try {
    iniContext = new InitialContext();
    DataSource ds =
    (DataSource)iniContext.lookup("java:comp/env/jdbc/quickstart");
    Connection conn = ds.getConnection();
    out.println("Sucesso!");
} catch (NamingException e) {
    out.println(e);
    e.printStackTrace();
} catch (SQLException e) {           InitialContext é configurado no momento em que é feito
    out.println(e);                              o deploy da aplicação e se torna
    e.printStackTrace();                              disponível (para leitura).
}                                       Todas as entradas configuradas ficam disponíveis
                                                 em “java:comp/env” no namespace JNDI.


     @regismelo                                                                          57
Hibernate




                    Exercício

• Altere o exercicío anterior, implementando um
  servlet, de forma que o acesso ao banco de
  dados seja feito usando uma conexão no pool de
  conexões.




                                            30 minutos
 @regismelo                                        58
Hibernate



                 Para saber mais


• http://jakarta.apache.org/tomcat/tomcat-5.0-doc/jndi-r




 @regismelo                                         59
Hibernate




                  Módulo III



             Data Access Objects




@regismelo                             60
Hibernate



               Data Acess Object
• DAO é um dos padrões do livro “Core J2EE
  Design Patterns”;

• É usado para “isolar” o acesso a persistência, pois
  a persistência pode variar enormemente (JDBC,
  Hibernate, SGBD relacionais, SGBD O.O., etc);

• Use DAO para não expor o seu cliente a forma
  como seus dados são acessados!


 @regismelo                                         61
Hibernate



                 Quando usar DAO?
• Componentes como BMP entity beans, session beans ou
  servlets/JSP precisam recuperar e armazenar informações de
  locais persistentes e outras fontes (bancos legados, LDAP,
  etc);
• A API da camada de persistência pode variar dependendo do
  fornecedor (JDBC, Hibernate, JDO);
• A portabilidade dos componentes (usualmente componentes
  de negócio) é diretamente afetada quando um acesso de
  forma específica a uma API é incluída nesses componentes;
• Componentes precisam ser transparentes a forma como a
  persistência armazena os dados – isso facilita a migração
  para fornecedores diferentes, tipos de armazenamentos
  diferentes e tipos de fontes de dados diferentes.
                      http://java.sun.com/j2ee/patterns/DataAccessObject.html
 @regismelo                                                               62
Hibernate



             Estrutura de um DAO




@regismelo                             63
Hibernate



             Estrutura de um DAO




@regismelo                             64
Hibernate



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




 @regismelo                                                 65
Hibernate



                     DAO e Abstract Factory
public interface DAO { }
____________________________________________________________________________


public interface AutorDAO implements DAO {
   public List getAutores();
   public void addAutor( int cdAutor , String nmAutor, String dsFone, boolean
                             idContratado );
}
____________________________________________________________________________


public class AutorDAOJDBC implements AutorDAO
{ ... }




    @regismelo                                                                  66
Hibernate



                          DAO e Abstract Factory

public class DAOFactory {
   public DAO getInstance( Object connection, Class c) throws DAOException
   {
           try {
                Class cc = c.getClassLoader().loadClass(c.getName() + "JDBC" );
                Constructor ctor = cc. getConstructor(new Class[] { Object.class });
                return (DAO)ctor.newInstance( new Object[] { connection } );
             }
             catch ( Exception e ) {
               throw new DAOException( e );
             }
    }
                                                               Todas as classes concretas,
}
                                                                deverão se chamar *JDBC




        @regismelo                                                                       67
Hibernate



                      DAO e Abstract Factory
public class DAOException extends Exception {
   public DAOException() {
           super();
   }

    public DAOException(String message) {
           super(message);
    }

    public DAOException(String message, Throwable cause) {
           super(message, cause);
    }

    public DAOException(Throwable cause) {
           super(cause);
    }
}



     @regismelo                                                  68
Hibernate



                       DAO e Abstract Factory

public class Teste {
    public static void main( String args[] ) {
      AutorDAO autorDAO = DAOFactory.getInstance( conn, AutorDAO.class );
      autorDAO.getAutores();
      ...
    }
}
____________________________________________________________________________




     @regismelo                                                             69
Hibernate




                        Exercício

• Implemente o exercício anterior utilizando DAO;

• A classe AutorDAO deverá ter os dois métodos
  implementados – getAutores e addAutor.

• Os dois métodos deverão trabalhar com o objeto Autor que
  representará os dados da tabela
  (JavaBean com gets e sets).


                                                    45 minutos
 @regismelo                                              70
Hibernate



                   Para saber mais


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

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




  @regismelo                                             71
Hibernate




                     Módulo IV



             Frameworks de Persistência




@regismelo                                    72
Hibernate



                    Frameworks e Java
• JDBC é uma API de muito baixo nível;
• Surge a necessidade de frameworks de persistência;
• Construir o próprio framework?
    – Maior integração com seu sistema;
    – Muito esforço de manutenção
• Usar um framework próprio?
    – Diversos frameworks open-source;
    – Muitas opções – difícil escolha!
• Vamos conhecer os principais mecanismos de persistência
  disponíveis com Java.



 @regismelo                                                 73
Hibernate



                             JDO
• JDO = Java Data Objects;
• JCP (Java Community Process) desenvolveu o JDO como
  uma especificação de alto nível;
• A idéia é realizar um mapeamento objeto-relacional;
• Grande vantagem por ser um padrão;
• Porém, a SUN não disponibilizou uma implementação free do
  JDO (apenas uma implementação de referência);
• A implementação de referência armazena os dados em
  arquivos e não em um banco relacional. 



 @regismelo                                                 74
Hibernate




Implementações de JDO de Fornecedores

 Produto          Fornecedor
 JDO Genie        Hemisphere Technologies
 LiDO             LIBeLIS
 JDO Toolkit      MVCSoft
 FrontierSuite    Object Frontier
 JRelay           Object Industries
 OpenFusion JDO   Prism Technologies
 Fast Objects     Poet Software
 IntelliBO        Signsoft
 Kodo JDO         SolarMetric

 @regismelo                                     75
Hibernate



        Implementações JDO Open Source
• Existem também opções livres;
• A mais famosa delas talvez seja o Castor;
• Porém o Castor não é completamente aderente a
  especificação JDO;
• Apesar de ser open source, o Castor não “explodiu” como
  solução para a comunidade...




 @regismelo                                                 76
Hibernate



                    Entity Beans
• Enterprise Java Beans provêm dois tipos de mecanismo
  de persistência:
    – Bean Managed Persistence
    – Container Managed Persistence
• BMP  Você controla como o dado vai ser gravado;
• CMP  O container faz o trabalho para você;
• Grandes vantagens por proporcionar um mecanismo
  transparente de persistência objeto-relacional;
• Linguagem própria para consulta – OQL (Object Query
  Language) muito limitada.
 @regismelo                                             77
Hibernate



              Entity Beans e Complexidade
• Recentemente, Richard Monson-Haefel, um dos
  desenvolvedores que está especificando a especificação
  3.0 de EJB (JSR 220), postou uma mensagem em seu
  WebLog – “You Can make EJB better”;
• Diversas pessoas postaram mensagens sobre melhorias
  na especificação;
• Ele organizou e elencou as TOP 13 funcionalidades
  solicitadas pela comunidade...
• http://weblogs.java.net/pub/wlg/997



 @regismelo                                               78
Hibernate



             Entity Beans e Complexidade
 1. Ditch CMP or make it simpler like Hibernate or JDO
 2. Use a POJO programming model
 3. Add support for Interceptors/filters/AOP.
 4. Eliminate/Consolidate the component interfaces (remote, local
 and endpoint).
 5. Make deployment descriptors more like XDoclet
 6. Instance-level authentication/entitlement.
 7. Replace the JNDI ENC with Dependency Injection (a.k.a. IoC).
 8. Add a Mutable Application Level Context
 9. Support development and testing outside the container
 system.
 10. Define cluster-wide singletons for EJB.
 11. Clearly specify and standardize class loading requirements.
 12. Standardize the deployment directory structure for EJBs.
 13. Support Inheritance.
@regismelo                                                     79
Hibernate



              Entity Beans e Complexidade
• Kiss!
• Diversos pontos levantados já são suportados por
  frameworks como Hibernate;
• Do site do Hibernate:

    30.06.2004 - EJB 3.0 Early Draft Review
    An early draft of the EJB 3.0 specification was made public today.
      The next generation of EJB is focused on simplification of the
      programming model and many concepts from Hibernate have
      been used to shape the new EJB entity bean part of the spec.




 @regismelo                                                              80
Hibernate



                       Hibernate
• Hibernate tem se mostrado um framework bastante
  maduro;
• Não é padrão de direito, mas é um padrão de fato;
• O JBoss incorporou o projeto Hibernate como
  mecanismo oficial de persistência;
• Diferente de JDO, Hibernate se propõem a persistir
  dados somente em bancos relacionais;
• Open Source e com suporte aos principais SGBDs do
  mercado.



 @regismelo                                                81
Hibernate




               Módulo V



             Hibernating…




@regismelo                      82
Hibernate



              Iniciando no Hibernate
• Para iniciar, iremos implementar uma classe simples de
  mensagens...
• Essa classe, será responsável por armazenar
  mensagens em um banco de dados relacional;
• Basicamente, teremos:
    – Um número único para a mensagem;
    – O texto da mensagem;
    – Um ponteiro para a próxima mensagem.




 @regismelo                                             83
Hibernate


package hello;

public class Message {
  private Long id;                        // Identificador da mensagem
  private String text;                    // Texto da mensagem
  private Message nextMessage;            // Próxima mensagem
  private Message() { }
  public Message(String text) {
       this.text = text;
  }
  public Long getId() {
          return id;
  }
  // ... Todos os outros gets/sets das propriedades...
}
 @regismelo                                                           84
Hibernate



                    A classe Message
• Alguns pontos importantes sobre a classe Message:
    – Todos os atributos de message obedecem o padrão de
      JavaBeans (get, set, is);
    – A classe tem um construtor default;
    – Essa classe poderá ser facilmente persistida pelo Hibernate;
    – E também poderá ser utilizada livremente fora do “escopo”
      hibernate;
    – Isso é uma diferença importante entre Hibernate e Entity
      Beans!

    Message message = new Message("Hello World");
    System.out.println( message.getText() );
 @regismelo                                                       85
Hibernate



              Persistindo a classe Message
• Precisamos agora de alguma maneira de persistir a
  classe message;
• Fazer isso em Hibernate seria algo do tipo:

         Session session = HibernateUtil.currentSession();
         Transaction trans = session.beginTransaction();

         Message message = new Message("Hello World");
         session.save(message);

         trans.commit();
         session.close();

 @regismelo                                                      86
Hibernate



              Persistindo a classe Message
• Esse código, resultaria em um insert no banco de
  dados...


         insert into Messages
         (Message_ID, Message_Text, Next_Message_ID )
         Values ( 1, ‘Hello World’, null )




   Chave cega (increment)




 @regismelo                                                 87
Hibernate



              Persistindo a classe Message
• Para recuperar as mensagens do banco de dados:

         Session newSession = getSessionFactory().openSession();
         Transaction newTrans = newSession.beginTransaction();

         List messages = newSession.find(
           "from Message as message order by message.text asc");

         System.out.println( messages.size() + " message(s) found:" );
         for ( Iterator iter = messages.iterator(); iter.hasNext(); ) {
           Message message = (Message) iter.next();
           System.out.println( message.getText() );
         }

         newTrans.commit();
         newSession.close();
 @regismelo                                                               88
Hibernate



              Persistindo a classe Message
• A literal “from Message as message order by
  message.text asc” na verdade é uma query Hibernate;
• No Hibernate você escreve consultas com sua
  linguagem, chamada HQL (Hibernate Query Language);
• HQL é muito parecido com SQL;
• Essa consulta, provavelmente seria traduzida para algo
  como:

         select message.MESSAGE_ID, message.MESSAGE_TEXT,
            message.NEXT_MESSAGE_ID
         from MESSAGES message
         order by message.MESSAGE_TEXT asc
 @regismelo                                                 89
Hibernate



              Persistindo a classe Message
• Para “colar” as peças, é necessário ainda um arquivo de
  mapeamento entre a tabela no banco de dados e o
  objeto;
• É o que chamamos de “mapping metadata”;
• Basicamente, esse arquivo define os campos da tabela
  em relação ao bean e seus relacionamentos;
• Vejamos um exemplo...




 @regismelo                                              90
Hibernate


<?xml version="1.0"?>                                            Arquivo Message.hbm.xml
<!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>

       @regismelo                                                                  91
Hibernate



              Persistindo a classe Message
• Podemos perceber que o arquivo XML é fácil de
  entender e de manter...


• Para cada obejeto a ser persistido, teremos um arquivo
  XML de configuração;


• Mais a frente, veremos maneiras de gerá-lo
  automaticamente;




 @regismelo                                                92
Hibernate



              Persistindo a classe Message
• E para fazer alterações na tabela? Como deveríamos
  proceder?

  Session session = getSessionFactory().openSession();
  Transaction trans = session.beginTransaction();

  // 1 é o código da primeira mensagem gerada
  Message message=(Message)session.load( Message.class, new Long(1) );
  message.setText(“Hello World, again!");
  message.setNextMessage( new Message(“It’s so funny!" ) );
  trans.commit();
  session.close();




 @regismelo                                                         93
Hibernate



               Persistindo a classe Message
• Esse código iria gerar algumas queries como essas:

              select message.MESSAGE_ID, message.MESSAGE_TEXT,
              message.NEXT_MESSAGE_ID
              from MESSAGES message
              where message.MESSAGE_ID = 1

              insert into MESSAGES (MESSAGE_ID, MESSAGE_TEXT,
              NEXT_MESSAGE_ID)
              values (2, 'Take me to your leader (please)', null)

              update MESSAGES
              set MESSAGE_TEXT = 'Greetings Earthling',
                  NEXT_MESSAGE_ID = 2
              where MESSAGE_ID = 1
 @regismelo                                                             94
Hibernate



              Persistindo a classe Message
• Para que o código do exemplo anterior funcione ainda é
  necessário configurar o Hibernate;
• Fazemos isso, criando o arquivo hibernate.cfg.xml;
• Ele conterá os mapeamentos para os arquivos de
  configuração de cada classe;
• Vejamos um exemplo desse arquivo...




 @regismelo                                                95
Hibernate


<?xml version='1.0' encoding='utf-8'?>                                   Arquivo hibernate.cfg.xml
<!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>




       @regismelo                                                                            96
Hibernate




                       Exercício

• Implemente a classe Message;

• Crie um servlet que persista os dados de Message e que
  recupere a lista de mensagens como mostrado no
  exemplo.




                                   Consulte a resolução desse
                                   exercício em hibernate.ex01

 @regismelo                                                          97
Hibernate




             Módulo V


               Ant




@regismelo                  98
Hibernate



                   Ant: O que é?
• Ferramenta para construção de aplicações
   – Implementada em Java
   – Baseada em roteiros XML
   – Extensível (via scripts ou classes)
   – 'padrão' do mercado
   – Open Source (Grupo Apache, Projeto Jakarta)
• Semelhante a make, porém
   – Mais simples e estruturada (XML)
   – Mais adequada a tarefas comuns em projetos Java
   – Independente de plataforma


  @regismelo                                           99
Hibernate


             Integração contínua com Ant




@regismelo                                    100
Hibernate



        Por que integrar continuamente?
•   "Reduz o tempo passado no inferno da integração"
     – Quanto mais tempo durarem os bugs de integração, mais
        difíceis são de eliminar
•   Integração contínua expõe o estado atual do
    desenvolvimento permanentemente
     – Permite avaliar e reavaliar prazos
     – Permite encontrar problemas de design rapidamente
     – Permite executar testes funcionais e de aceitação a
        qualquer momento
     – Estimula pequenos lançamentos e design simples
•   Quando integrar?
     – Pelo menos uma vez por dia (sistemas grandes) ou +


@regismelo                                                     101
Hibernate



                  Tipos de integração
•   Integração local
     – Projetos pequenos ou subprojetos independentes
     – Única cópia de trabalho do código-fonte
     – Ligação com bibliotecas, montagem de componentes,
        implementação, testes
     – Pode ser implementada com função "build" do IDE usado
•   Integração distribuída
     – Projetos desenvolvidos por várias pessoas ao mesmo
        tempo
     – Múltiplas cópias de trabalho do código-fonte
     – Atualizações a qualquer momento
     – Uma atualização pode fazer testes não rodarem mais
     – Mais complicada de implementar: desenvolvedores
        geograficamente distribuídos, plataformas diferentes, etc.
@regismelo                                                           102
Hibernate



                 Como implementar?
•   Ferramentas de código aberto disponíveis:
     – CVS, Ant e JUnit
     – Extensões para essas ferramentas
•   Cumprem os requisitos necessários para viabilizar a
    integração contínua
     – 1. Único lugar para obter as fontes mais recentes:
          • Repositório CVS, ou similar
     – 2. Único comando para montar a aplicação a partir das
        fontes do repositório:
          • Ant
     – 3. Único comando para rodar todos os testes:
          • JUnit


@regismelo                                                        103
Hibernate



                 Ant: Para que serve?
• Para montar praticamente qualquer aplicação Java que consista
  de mais que meia dúzia de classes;
• Aplicações:
   – distribuídas em pacotes
   – que requerem a definição de classpaths locais, e precisam
     vincular código a bibliotecas (JARs)
   – cuja criação/instalação depende de mais que uma simples
   – chamada ao javac. Ex: RMI, CORBA, EJB, servlets, JSP,...

• Para automatizar processos freqüentes
   – Javadoc, XSLT, implantação de serviços Web e J2EE
     (deployment), CVS, criação de JARs, testes, FTP, email

  @regismelo                                                  104
Hibernate


                     Ant: Como funciona?
•   Ant executa roteiros escritos em XML: 'buildfiles’;
•   Cada projeto do Ant possui um buildfile
     – subprojetos podem ter, opcionalmente, buildfiles adicionais
       chamados durante a execução do primeiro;
•   Cada projeto possui uma coleção de targets;
•   Cada target consiste de uma seqüência de tasks;
•   Exemplos de execução
     – ant
         procura build.xml no diretório atual e roda alvo default
     – ant -buildfile outro.xml
         executa alvo default de arquivo outro.xml
     – ant compilar
         roda alvo 'compilar' e possíveis dependências em build.xml

    @regismelo                                                        105
Hibernate



             Ant: Como funciona?




@regismelo                            106
Hibernate



                           Ant: Buildfile
•   O buildfile é um arquivo XML: build.xml (default)
•   Principais elementos
     <project default=“target_default">
     Elemento raiz (obrigatório): define o projeto.
     <target name=“targete_name">
     Coleção de tarefas a serem executadas em seqüência
     Deve haver pelo menos um <target>
     <property name="nome" value="valor">
         • pares nome/valor usados em atributos dos elementos do
         • build.xml da forma ${nome}
         • propriedades também podem ser definidas em linha de
           comando (-Dprop=valor) ou lidas de arquivos externos (atributo
           file)
     tarefas (mais de 130) - dentro dos targets.
         <javac>, <jar>, <java>, <copy>, <mkdir>, ...
    @regismelo                                                       107
Hibernate


                                  …Ant: Buildfile
   <?xml version="1.0" encoding="iso-8859-1" ?>                   Propriedades
   <!-- 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}" />                              Targets
         </target>

        <target name="compile" depends="init“ description="Compila os arquivos-fonte">
              <javac srcdir="${src.dir}" destdir="${build.dir}">
                   <classpath>
Tasks                   <pathelement location="${build.dir}" />
                   </classpath>
              </javac>
        </target>
      </project>
       @regismelo                                                                      108
Hibernate



                 Ant: O que se pode fazer?
•   Compilar                     •   Expandir, copiar, instalar
     <javac>, <csc>                   <copy>, <delete>, <mkdir>,
•   Gerar documentação                <unjar>, <unwar>, <untar>,
     <javadoc>, <junitreport>,        <unzip>
     <style>, <stylebook>        •   Acesso remoto
•   Executar programas                <ftp>, <telnet>, <cvs>,
     <java>, <apply>, <exec>          <mail>, <mimemail>
     <ant>, <sql>                •   Montar componentes
•   Testar unidades de código         <ejbc>, <ejb-jar>, <rmic>
     <junit>                     •   Criar novas tarefas
•   Empacotar e comprimir             <taskdef>
     <jar>, <zip>, <tar>,        •   Executar roteiros e sons
     <war>, <ear>, <cab>              <script>, <sound>

    @regismelo                                               109
Hibernate



                     Ant: Algumas tarefas
•   <javac>: Chama o compilador Java
     <javac srcdir="dirfontes" destdir="dirbuild" >
        <fileset includes="**/*.java" />
        <classpath>
                   <pathelement path="arquivo.jar" />
                   <pathelement path="/arquivos" />
        </classpath>
        <classpath idref="extra" />
     </javac>

•   <jar>: Monta um JAR
     <jar destfile="bin/programa.jar“ manifest="manifest.txt">
        <fileset dir="${build.dir}"/>
     </jar>
    @regismelo                                                      110
Hibernate



                    …Ant: Algumas tarefas
•   <tstamp>: Grava um instante
     – A hora e data podem ser recuperados como propriedades
         • ${TSTAMP} hhmm 1345
         • ${DSTAMP} aaaammdd 20020525
         • ${TODAY} dia mes ano 25 May 2002
•   Novas propriedades podem ser definidas, locale, etc.
•   Uso típico: <tstamp/>

•   <javadoc>: Gera documentação do código-fonte.

          <javadoc destdir="docs/api“
            packagenames=“br.com.softsite.sfc.*"
          sourcepath="tmp" />

    @regismelo                                                    111
Hibernate



                   …Ant: Algumas tarefas
•   <ftp>: Realiza a comunicação com um servidor FTP remoto para envio
    ou download de arquivos
     – Tarefa opcional que requer NetComponents.jar (
        http://www.savarese.org)

     <target name="ftp-deploy" depends="dist">
        <ftp server="${ftp.host}" port="${ftp.port}“
        remotedir="/tomcat/deploy“ userid="tomcat" password="catalina“
        depends="yes" binary="yes">
          <fileset dir="${basedir}">
                   <include name="*.war"/>
          </fileset>
        </ftp>
     </target>
    @regismelo                                                      112
Hibernate



                               Ant: Filtros
•   Permite a substituição de padrões delimitados por um caractere em arquivos
    durante a execução de uma tarefa
     – Caractere default: @
•   Exemplo: a tarefa abaixo irá substituir todas as ocorrências de @javahome@
    por c:j2sdk1.4.0 nos arquivos copiados
          <copy todir="${dest.dir}">
             <fileset dir="${src.dir}"/>
             <filterset>
                     <filter token="javahome" value="c:j2sdk1.4.0"/>
             </filterset>
          </copy>
•   Pares token=valor podem ser carregados de arquivo:
          <filterset>
             <filtersfile file="build.properties" />
          </filterset>

    @regismelo                                                             113
Hibernate




                                      Exercício

• Empacotar em um arquivo WAR o exemplo hibernate
  anterior;

• Fazer o deploy desse arquivo WAR no TomCat.




                              Consulte a resolução desse exercício em hibernate.ex02
  Antes de executar, configure o arquivo build.properties de acordo com seu ambiente

 @regismelo                                                                                114
Hibernate



                 Para saber mais


• http://ant.apache.org/

• Exemplos de build files
  dos projetos Jakarta




 @regismelo                           115
Hibernate




                   Módulo VII


                  Hibernate –
             Entendendo a Arquitetura




@regismelo                                 116
Hibernate



             Arquitetura




@regismelo                    117
Hibernate



                               Arquitetura
• Session Interface
    – É a principal interface utilizada por aplicações Hibernate;
    – Não é thread-safe;
    – Falando em banco de dados, pense em uma sessão como algo entre uma
      conexão e uma transação;
    – Falando em Java, pense em uma sessão como um cache ou uma coleção
      de objetos relativos a uma “unit of work”;
    – Ela é a interface responsável por persistir os dados no banco de dados.
    – Dica: Faça com que seu programa compartilhe em uma mesma requisição
      a mesma instância de session (ver implementação HibernateUtil).




 @regismelo                                                                     118
Hibernate



                               Arquitetura
• SessionFactory Interface
    – Mantém cache dos SQL gerados e outros mapeamentos que o Hibernate
      usa em tempo de execução;
    – Mantém também cache de dados que são lidos em uma sessão;

• Configuration Interface
    – Usado para configurar o Hibernate;
    – Configuration é utilizado para indicar o local dos arquivos XML e para obter
      SessionFactory




 @regismelo                                                                    119
Hibernate



                           Arquitetura
• Transaction Interface
    – Gerencia transações com o banco de dados;
    – É uma API opcional, pois a aplicação poderá optar por gerenciar a
      transação sozinha;
    – Abstrai o mecanismo utilizado para gerenciar uma transação (que
      pode ser uma transação JDBC, JTA ou CORBA);
    – É interessante pois permite que aplicações Hibernate sejam
      portáveis entre diferentes tipos de container e ambientes.




 @regismelo                                                           120
Hibernate



                           Arquitetura
• Query and Criteria Interface
    – Permite criar queries no banco de dados;
    – As consultas são escritas em HQL (Hibernate Query Language) ou
      em SQL nativo;
    – Criteria é uma interface muito similar que permite você criar e
      executar consultas baseadas em critérios (veremos mais a frente
      esse tópico);




 @regismelo                                                             121
Hibernate



                         Arquitetura
• Callbacks interfaces
    – Permite que a aplicação receba notificações quando algo
      “interessante” acontece com os objetos;
    – Notifica quando o objeto é lido, excluído ou armazenado no
      banco de dados;
    – Inteface Lifecycle
        • onSave: Chamado antes do objeto ser salvo
        • onUpdate: Chamado antes do objeto ser atualizado
                     (Session.update())
        • onDelete: Antes do objeto ser deletado
        • onLoad: Depois do objeto ser lido.


 @regismelo                                                     122
Hibernate



                           Arquitetura
• ...Callbacks interfaces
    – Interface Validatable
        • validate: Validar o objeto antes dele ser persistido.


    – A interface Interceptor também é utilizada para “interceptar”
      ações do Hibernate;

    – Vantagem em usar pois não força que as classes
      implementem uma interface Hibernate.




 @regismelo                                                          123
Hibernate



                         Arquitetura
• Types
    – Um tipo no Hibernate mapeia um tipo Java para um tipo no
      banco de dados;
    – Um tipo no Hibernate pode inclusive se transformar em mais
      de uma coluna no banco de dados (endereço de cobrança,
      por exemplo);

• Extension Interfaces
    – Possibilidade de extender funcionalidades do Hibernate;
    – Exemplos – Geração de primary key, dialetos SQL,
      estratégias de cache, etc.


 @regismelo                                                        124
Hibernate



                       Configurações
• Hibernate pode ser utilizado tanto em “ambientes não
  gerenciados” (tipicamente um servlet container) quanto em
  “ambientes gerenciados” (EJB);
• O desenho dos POJOs, mapeamentos e configurações do
  Hibernate são os mesmos;
• Vantagem em relação a BMP/CMP pois:
    – É portável entre tipos diferentes de arquitetura;
    – É fácil de testar (JUnit);
    – É mais natural de implementar. Você vai desenhar
      apenas JavaBeans.

 @regismelo                                                  125
Hibernate



             Configurações




@regismelo                      126
Hibernate



             Configurações




@regismelo                      127
Hibernate



             Configurações




@regismelo                      128
Hibernate



                 Dicas importantes
• Um Session Factory, usando como Factory de sessões é
  uma classe dispendiosa para ser criada;
• Ela é a responsável por fazer o parser dos arquivos XML
  de definição do Hibernate;
• Portanto, procure criar essa classe apenas uma vez!
• Você pode criar uma classe “Helper” para fazer isso...
• Vejamos o exemplo...




 @regismelo                                                129
Hibernate



                 Dicas importantes
• Um Session Factory, usando como Factory de sessões é
  uma classe dispendiosa para ser criada;
• Ela é a responsável por fazer o parser dos arquivos XML
  de definição do Hibernate;
• Portanto, procure criar essa classe apenas uma vez!
• Você pode criar uma classe “Helper” para fazer isso...
• Vejamos o exemplo...




 @regismelo                                                130
Hibernate



                  Classe Helper Hibernate
public class HibernateUtil {

     private static final SessionFactory sessionFactory;

     static {
          try {
              // Create the SessionFactory
              sessionFactory = new
                 Configuration().configure().buildSessionFactory();
          } catch (HibernateException ex) {
              System.out.println(ex);
              throw new RuntimeException(“Problemas na configuracao: " +
                  ex.getMessage(), ex);
          }
     }
}




    @regismelo                                                             131
Hibernate



                 Dicas importantes
• Você pode usar essa mesma classe Helper para garantir
  que a mesma Session seja retornada entre várias
  chamadas;
• Isso é bom pois evitará problemas de concorrência e
  fará como que dados (cache de objetos) seja
  compartilhado entre chamadas;
• Importante: Session não é Thread Safe!
• Você pode utilizar a mesma classe Helper para fazer
  isso, usando um pequeno truque com ThreadLocal;
• Vejamos o exemplo…


 @regismelo                                             132
Hibernate


public class HibernateUtil {
   // … Código do exemplo anterior         suprimido por questões de
   espaço
   private static final ThreadLocal session = new ThreadLocal();

     public static Session currentSession() throws HibernateException {
          Session s = (Session) session.get();
          // Abre uma nova sessão se necessário
          if ( (s == null) || ( ! s.isConnected() ) ){
                   s = sessionFactory.openSession();
                   session.set(s);
          }
          return s;
     }
     public static void closeSession() throws HibernateException {
          Session s = (Session) session.get();
          session.set(null);

            if (s != null)
                    s.close();
     }
}
    @regismelo                                                            133
Hibernate



                 Dicas importantes
• Você pode usar essa mesma classe Helper para garantir
  que a messa Session seja retornada entre várias
  chamadas;
• Isso é bom pois evitará problemas de concorrência e
  fará como que dados (cache de objetos) seja
  compartilhado entre chamadas;
• Importante: Session não é Thread Safe!
• Você pode utilizar a mesma classe Helper para fazer
  isso, usando um pequeno truque com ThreadLocal;
• Vejamos o exemplo…


 @regismelo                                             134
Hibernate



                 Para saber mais


• Hibernate in Action, chapter 3;



•




    @regismelo                         135
Hibernate




             Módulo VIII


 Trabalhando com Persistent Objects




@regismelo                            136
Hibernate



               Persistence Lifecycle
• Hibernate é um mecanismo de persistência
  transparente;
• Isso significa que classes não precisam se preocupar
  com a sua própria capacidade de persistência;
• Ótimo! Nossos objetos não precisam de um tratamento
  especial, não precisam herdar de uma classes
  específica, não precisam trabalhar de forma diferente
  para serem persistidos;
• Isso facilita o trabalho e principalmente nos permite
  fazer escolhas diferentes de mecanismos de
  persistência.

 @regismelo                                                  137
Hibernate



               Persistence Lifecycle
• Porém, a sua aplicação precisa interagir de alguma
  forma com a camada de persistência indicando que os
  dados precisam ser gravados no banco ou recuperados
  dele;
• Para fazer isso, é necessário o uso da API do Hibernate
  (persistence manager e query interfaces);
• O ciclo de vida dos objetos persistidos é definido em 3
  estados – Transient, Persistent e Detached;
• Vejamos o gráfico…



 @regismelo                                                 138
Hibernate



             Persistence Lifecycle




@regismelo                              139
Hibernate



             Persistence Lifecycle - Transient
•    O primeiro estado é o transiente;
•    Ele acontece quando você instancia um objeto qualquer

            Cliente a = new Cliente();
•    O estado é chamado de transient o que quer dizer que ele não está
     associado a nenhuma linha no banco de dados;
•    O seu estado será perdido assim que ele não for mais referenciado
     (garbage collector);
•    Para um objeto transient passar a ser persistent é requerida uma
     chamada a save() a partir de persistence manager ou a criação de
     uma referência a partir de um persistência já instanciada.




    @regismelo                                                      140
Hibernate


Session session = HibernateUtil.currentSession();

Transaction trans = session.beginTransaction();

                                                            Objeto
Message message = new Message();
                                                          transiente
message.setText("Hello World of Hibernate!");

                                              Objeto
session.save(message);
                                            persistente
trans.commit();
session.close();




 @regismelo                                                               141
Hibernate


Session session = HibernateUtil.currentSession();
Transaction trans = session.beginTransaction();

// Instanciar uma nova classe message
Message newMessage = new Message();                        Objeto
newMessage.setText("Hibernate é fácil!");                transiente

// 1 é o código da primeira mensagem gerada
Message messageOriginal = (Message) session.load( Message.class, new
   Long(1) );
messageOriginal.setText("Hello World, de novo!");
messageOriginal.setNextMessage( newMessage );

trans.commit();
session.close();                                         Objeto
                                                    persistente pois
                                                    foi associado a
                                                      outro objeto
                                                      persistente




 @regismelo                                                               142
Hibernate



         Persistence Lifecycle - Persistent
• É qualquer instância com “database identity”;
• Pode ser desde um objeto que foi instanciado pela
  aplicação e salvo pela chamada do método save();
• Ou um objeto que já foi recuperado do banco de dados
  (através de uma query, por exemplo);
• Vejamos o exemplo…




 @regismelo                                              143
Hibernate


Session session = HibernateUtil.currentSession();
Transaction trans = session.beginTransaction();

List messages = session.find(
                 "from Message as message order by message.text asc");

for ( Iterator iter = messages.iterator(); iter.hasNext(); ) {
        Message message = (Message) iter.next();
        out.println( message.getText() + "<BR>" );
   }                                                      Objetos
                                                        persistentes

trans.commit();
session.close();




 @regismelo                                                               144
Hibernate



          Persistence Lifecycle - Detached
• Objetos “desconectados” são objetos que não tem mais
  ligação com o banco de dados;

• Causa - A transação acabou;

• Muito útil pois pode evitar a necessidade de DTOs
  (típicos de aplicações EJB);

• Problemático pois pode gerar LazyInitializationException



 @regismelo                                              145
Hibernate



                      Persistence Manager
• Criando objetos novos:

User user = new User();
user.setFirstname("John");
user.setLastname("Doe");

Session session = sessions.openSession();
Transaction tx = session.beginTransaction();

session.save(user);
tx.commit();
session.close();




 @regismelo                                       146
Hibernate



                      Persistence Manager
• Alterando objetos:

user.setPassword("secret");
Session sessionTwo = sessions.openSession();

Transaction tx = sessionTwo.beginTransaction();

sessionTwo.update(user);
user.setUsername("jonny");
                                  Somente
tx.commit();                    necessário se
sessionTwo.close();             for um objeto
                                desconectado




 @regismelo                                          147
Hibernate



                      Persistence Manager
• Alterando objetos:

user.setPassword("secret");
Session sessionTwo = sessions.openSession();

Transaction tx = sessionTwo.beginTransaction();

sessionTwo.saveOrUpdate(user);
user.setUsername("jonny");
                                      Cria ou altera
tx.commit();                              objeto
sessionTwo.close();




 @regismelo                                               148
Hibernate



                   Persistence Manager
• Tornando objetos transientes:

Session session = sessions.openSession();
Transaction tx = session.beginTransaction();

int userID = 1234;
User user = new User();
user.setId( 1234 );

session.delete(user);
tx.commit();
session.close();




 @regismelo                                       149
Hibernate



              Primary Keys no Hibernate
• Toda tabela deve indicar qual sua chave primária;
• Use a tag “id” para indicar qual a chave primária da
  tabela:
   <id name="codigo" column="CD_LIVRO“/>

• Você pode informar também qual o mecanismo de
  geração de chaves:
   <id name="codigo" column="CD_LIVRO">
      <generator class="hilo">
           <param name="table">NrLivro</param>
           <param name="column">next_value</param>
      </generator>
   </id>

 @regismelo                                                 150
Hibernate



              Primary Keys no Hibernate
• A geração de chaves é determinada pela tag
  <generator>;
• Existem diversas classes disponibilizadas para a
  geração de chaves;
• São classes simples que implementam a interface
  net.sf.hibernate.id.IdentifierGenerator
• Você pode implementar o seu próprio mecanismo...
• Ou usar um dos diversos mecanismos já
  disponibilizados no Hibernate.



 @regismelo                                             151
Hibernate



                    Geração de Chaves
• increment
    – generates identifiers of type long, short or int that are unique
      only when no other process is inserting data into the same table.
      Do not use in a cluster.
• identity
    – supports identity columns in DB2, MySQL, MS SQL Server,
      Sybase and HypersonicSQL. The returned identifier is of type
      long, short or int.
• sequence
    – uses a sequence in DB2, PostgreSQL, Oracle, SAP DB, McKoi
      or a generator in Interbase. The returned identifier is of type
      long, short or int


 @regismelo                                                          152
Hibernate



                     Geração de Chaves
• hilo
    – uses a hi/lo algorithm to efficiently generate identifiers of type
      long, short or int, given a table and column (by default
      hibernate_unique_key and next respectively) as a source of hi
      values. The hi/lo algorithm generates identifiers that are unique
      only for a particular database.
• seqhilo
    – uses a hi/lo algorithm to efficiently generate identifiers of type
      long, short or int, given a named database sequence (Oracle,
      por exemplo).
• uuid.hex
    – uses a 128-bit UUID algorithm to generate identifiers of type
      string, unique within a network (the IP address is used). The
      UUID is encoded as a string of hexadecimal digits of length 32.
 @regismelo                                                                153
Hibernate



                     Geração de Chaves
• uuid.string
    – uses the same UUID algorithm. The UUID is encoded a string of
      length 16 consisting of (any) ASCII characters. Do not use with
      PostgreSQL.
• native
    – picks identity, sequence or hilo depending upon the capabilities
      of the underlying database.
• assigned
    – lets the application to assign an identifier to the object before
      save() is called.
• foreign
    – uses the identifier of another associated object. Usually used in
      conjunction with a <one-to-one> primary key association.

 @regismelo                                                               154
Hibernate



              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                                               155
Hibernate



                 Geração de Chaves - Exemplos
•    Identity columns and Sequences

       <id name="id" type="long" column="uid">
          <generator class="sequence">
               <param name="sequence">uid_sequence</param>
          </generator>
       </id>

       <id name="id" type="long" column="uid" unsaved-value="0">
              <generator class="identity"/>
       </id>



•    Dica  Para compatibilidade entre bancos, use native. O Hibernate
     se encarregará de usar identity, sequence ou hilo de acordo com o
     banco de dados selecionado.
    @regismelo                                                      156
Hibernate



                    Recuperando dados
•    Existem diversas formas de recuperar dados usando o Hibernate;
•    Usando o método load:
       Livro livro = (Livro)session.load( Cat.class,
                             new Long(1234) );


•    Usando o método get:
       Livro livro = (Livro)session.get( Cat.class,
                             new Long(1234) );

•    O load dispara uma exceção ObjectNotFoundException caso não
     seja encontrada a linha no banco de dados;
•    get tenta carregar a linha imediatamente e retorna null caso nada
     seja encontrado.

    @regismelo                                                           157
Hibernate



                    Recuperando dados
•    É possível também dar um refresh nos dados;
•    Pode ser útil quando um trigger altera algum dado da linha lida.
       Livro livro = (Livro)session.load( Cat.class,
                             new Long(1234) );

       livro.setPreco( 1000 );
       session.update(livro);

       session.refresh( livro );




    @regismelo                                                          158
Hibernate



                   Recuperando dados
•    É possível ainda executar consultas com Hibernate;

•    Hibernate usa uma linguagem muito parecida com SQL chamada
     HQL (Hibernate Query Language);

•    HQL não é uma linguagem de manipulação como SQL – é usada
     somente para recuperar dados (não possui funcionalidade de
     alteração/deleção);

•    HQL parece com ODMG OQL e EJB QL (A versão 3.0 do EJB QL é
     bem parecida com HQL).

•    Vejamos alguns exemplos...




    @regismelo                                                    159
Hibernate


List cats = sess.find("from Cat as cat where cat.birthdate = ?",
                       date, Hibernate.DATE );

List mates = sess.find(
   "select mate from Cat as cat join cat.mate as mate where " +
   "cat.name = ?", name, Hibernate.STRING );

List cats = sess.find( "from Cat as cat where cat.mate.bithdate is
   null" );

List moreCats = sess.find("from Cat as cat where " +
               "cat.name = 'Fritz' or cat.id = ? or cat.id = ?",
               new Object[] { id1, id2 },
               new Type[] { Hibernate.LONG, Hibernate.LONG }
   );

List problems = sess.find("from GoldFish as fish " +
   "where fish.birthday > fish.deceased or fish.birthday is null");

Query q = session.createQuery("from User u where u.firstname =
   :fname");
q.setString("fname", "Max");
List result = q.list();


   @regismelo                                                       160
Hibernate



                      Query by Criteria
•    Hibernate possui ainda um mecanismo chamado QBC – Query by
     Criteria;

•    Alguns desenvolvedores usam QBC pois o vêem como um
     mecanismo mais O.O. para realizar consultas;

•    Do outro lado, consultas feitas com QBC são menos legíveis que
     consultas expressas com HQL

      Criteria criteria = session.createCriteria(User.class);
      criteria.add( Expression.like("firstname", "Max") );
      List result = criteria.list();




    @regismelo                                                        161
Hibernate



                      Query by Example
•    Complementar a Query by Criteria existe um mecanismo chamado
     Query by Example;

•    Útil quando você quer listar dados a partir de vários filtros que
     podem ser representados em um objeto
     (usuário pode preencher qualquer dado da tela de clientes para
     pesquisar um cliente)

       User exampleUser = new User();
       exampleUser.setFirstname("Max");
       Criteria criteria = session.createCriteria(User.class);
       criteria.add( Example.create(exampleUser) );
       List result = criteria.list();




    @regismelo                                                           162
Hibernate



                         Query Nativa
•    Se você realmente precisar de algo dependente do banco de dados
     você poderá usar o mecanismo de consultas nativas do Hibernate;

•    Nele, você pode realizar as consultas e fazer mapeamentos das
     mesmas com o banco de dados;

•    Veja o exemplo:

       session.createSQLQuery(
       "select {c.*} from CATEGORY {c} where NAME like 'Laptop
          %'",
          "c",
          Category.class);




    @regismelo                                                       163
Hibernate



      O que você consegue fazer com HQL
•    The ability to apply restrictions to properties of associated objects related by
     reference or held in collections (to navigate the object graph using query language).

•    The ability to retrieve only properties of an entity or entities, without the overhead of
     loading the entity itself in a transactional scope. This is sometimes called a report
     query; it’s more correctly called projection.

•    The ability to order the results of the query.

•    The ability to paginate the results.

•    Aggregation with group by, having, and aggregate functions like sum, min, and max.

•    Outer joins when retrieving multiple objects per row.

•    The ability to call user-defined SQL functions.

•    Subqueries (nested queries).


                                                                               Fonte: Hibernate in Action

    @regismelo                                                                                     164
Hibernate



                       Query Interface
•    Executar uma query através do Hibernate pode ser feito de duas
     formas – através da própria session:
       List autores = session.find("from Autor as autor “ );


•    Ou através da criação explícita de uma Query:
       Query qry = session.createQuery("from Autor as autor“ );
       List autores = qry.list();



•    A primeira forma pode ser considerada como um “atalho” em
     relação a segunda;

•    Porém a segunda tem mais vantagens, pois oferece todas as
     funcionalidades da interface Query.

    @regismelo                                                        165
Hibernate



               Métodos interessantes de Query
 •    list()

        – Retorna os resultados da query no formato de um list. Se a
          query contém múltiplos resultados em uma linha (mais de um
          objeto está sendo retornado), o resultado é retornado como uma
          instância de Object[].
Query qry = session.createQuery("from Autor as autor“ );
List autores = qry.list();

Iterator foosAndBars = session.list(
   "select foo, bar from Foo foo, Bar bar where bar.date = foo.date"
   );
while ( foosAndBars.hasNext() ) {
   Object[] tuple = (Object[]) foosAndBars.next();
   Foo foo = tuple[0]; Bar bar = tuple[1];
   ....
}

     @regismelo                                                      166
Hibernate



             Métodos interessantes de Query
 •    iterate()

        – O mesmo que list. Porém, só as chaves primárias são
          retornadas com a chamada de iterate. Os objetos são
          populados sob demanda no momento em que são requisitados;

        – Pode ser mais eficiente que list() caso você não pretenda
          navegar em todo o result set ou se grande parte dos objetos já
          estiver carregado na memória;

        – Pode ser mais lento pois requer a execução de n+1 consultas.

Query qry = session.createQuery("from Autor as autor“ );
Iterator autores = qry.iterate();



     @regismelo                                                        167
Hibernate



              Métodos interessantes de Query
  •    Métodos de paginação – setFirstResult() e setMaxResults()

         – Usado para páginação;

         – O Hibernate decidirá como fará a paginação no seu banco de
           dados;
Query query =
session.createQuery("from User u order by u.name asc");
query.setFirstResult(0);
query.setMaxResults(10);


List results = session.createQuery("from User u order by u.name asc")
                      .setFirstResult(0)
                      .setMaxResults(10)
                      .list();



      @regismelo                                                        168
Hibernate



              Métodos interessantes de Query
  •    Passagem de parâmetros – nunca use:
String queryString =
"from Item i where i.description like '" + searchString + "'";
List result = session.createQuery(queryString).list();
  •


  •    Um usuário malicioso pode passar um parâmetro de forma que a
       consulta se comporte de outra forma:

foo' and callSomeStoredProcedure() and 'bar' = 'bar




  •    Use a passagem de parâmetros do Hibernate ao invés disso...


      @regismelo                                                        169
Hibernate



              Métodos interessantes de Query
  •    Passagem de parâmetros:
String queryString =
   "from Item item where item.description like :searchString";

List result = session.createQuery(queryString)
               .setString("searchString", searchString)
               .list();




  •    Métodos comuns para a passagem de parâmetro:

         – setString, setBoolean, setInteger, setFloat, ...

         – setParameter( String name, Object val )


      @regismelo                                                    170
Hibernate



                        Named Queries
 •    Como você já deve ter percebido, usar queries dentro do código
      pode torná-lo pouco legível;

 •    Para isso, o Hibernate possui um recurso chamado Named
      Queries;

 •    Você pode armazernar as consultas em um arquivo XML e
      simplesmente chamá-lo do seu programa Java;

 •    O interessante é que as consultas podem ser escritas em HQL ou
      SQL – o código Java não vai precisar tomar conhecimento disso;
<query name="findItemsByDescription"><![CDATA[
from Item item where item.description like :description
]]>
</query>


     @regismelo                                                        171
Hibernate




                        Exercício

• Dado o modelo de dados (ver referência no final desse
  material)...
• Faça a manutenção da tabela Autor (Inserir, Alterar,
  Consultar e Deletar).




                              Consulte a resolução desse exercício
                                                 em hibernate.ex??
                                       TODO: Finalizar o exercício
 @regismelo                                                             172
Hibernate




             Módulo IX


             XDocLet




@regismelo                  173
Hibernate




                               Xdoclet
•     Xdoclet é uma ferramenta de geração de código
       – Open Source
       – Estende a Javadoc doclet API, permitindo a criação de
         novos arquivo baseado nas tags @ do javadoc
       – Baseado no ANT
       – Extensível através de templates.
•     Site:http://xdoclet.sourceforge.net
•     Fornece suporte para geração de Arquivos EJB
       – ejb-jar.xml, interfaces home, remote etc.




    @regismelo                                                   174
Hibernate


                  Exemplo: CountBean.java
/**
 * @ejb.bean type="Stateful"
 *             view-type="both"
 *           jndi-name="CountHome"
 */
public class CountBean implements SessionBean {
    public int val;

   /**
    * Counts up
    * @ejb.interface-method
    */
   public int count() {
          System.out.println("count()");
          return ++val;
   }
  /*
   * @ejb.create-method
   */
   public void ejbCreate(int val) throws CreateException {
          this.val = val;
          System.out.println("ejbCreate()");
   }
  . . .
  @regismelo                                                    175
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate
Persistência com Hibernate - Curso sobre o framework Hibernate

Mais conteúdo relacionado

Destaque

Mini curso hibernate com anotações
Mini curso hibernate com anotaçõesMini curso hibernate com anotações
Mini curso hibernate com anotaçõesdieguinhomcz
 
Apache Cayenne: a Java ORM Alternative
Apache Cayenne: a Java ORM AlternativeApache Cayenne: a Java ORM Alternative
Apache Cayenne: a Java ORM AlternativeAndrus Adamchik
 
Curso De Hibernate 3
Curso De Hibernate 3Curso De Hibernate 3
Curso De Hibernate 3Joel Lobo
 
Introdução ao JPA com Hibernate
Introdução ao JPA com HibernateIntrodução ao JPA com Hibernate
Introdução ao JPA com HibernateDanilo Braga
 
Hibernate
Hibernate Hibernate
Hibernate Sunil OS
 
High Performance Hibernate JavaZone 2016
High Performance Hibernate JavaZone 2016High Performance Hibernate JavaZone 2016
High Performance Hibernate JavaZone 2016Vlad Mihalcea
 

Destaque (8)

JPA - Java Persistence API
JPA - Java Persistence APIJPA - Java Persistence API
JPA - Java Persistence API
 
JPA com Hibernate
JPA com HibernateJPA com Hibernate
JPA com Hibernate
 
Mini curso hibernate com anotações
Mini curso hibernate com anotaçõesMini curso hibernate com anotações
Mini curso hibernate com anotações
 
Apache Cayenne: a Java ORM Alternative
Apache Cayenne: a Java ORM AlternativeApache Cayenne: a Java ORM Alternative
Apache Cayenne: a Java ORM Alternative
 
Curso De Hibernate 3
Curso De Hibernate 3Curso De Hibernate 3
Curso De Hibernate 3
 
Introdução ao JPA com Hibernate
Introdução ao JPA com HibernateIntrodução ao JPA com Hibernate
Introdução ao JPA com Hibernate
 
Hibernate
Hibernate Hibernate
Hibernate
 
High Performance Hibernate JavaZone 2016
High Performance Hibernate JavaZone 2016High Performance Hibernate JavaZone 2016
High Performance Hibernate JavaZone 2016
 

Semelhante a Persistência com Hibernate - Curso sobre o framework Hibernate

Curso de Java (Parte 5)
Curso de Java (Parte 5)Curso de Java (Parte 5)
Curso de Java (Parte 5)Mario Sergio
 
GlassFish, Maven, Cloud e o futuro do Java EE
GlassFish, Maven, Cloud e o futuro do Java EEGlassFish, Maven, Cloud e o futuro do Java EE
GlassFish, Maven, Cloud e o futuro do Java EEBruno Borges
 
Aula 6 conexão bd
Aula 6 conexão bdAula 6 conexão bd
Aula 6 conexão bdDanilo Alves
 
GlassFish, Maven, Cloud e Java EE
GlassFish, Maven, Cloud e Java EEGlassFish, Maven, Cloud e Java EE
GlassFish, Maven, Cloud e Java EEBruno Borges
 
Apresentação palestra ireport
Apresentação palestra ireportApresentação palestra ireport
Apresentação palestra ireportfpsgyn
 
Netbeans 6.7: a única IDE que você precisa!
Netbeans 6.7: a única IDE que você precisa!Netbeans 6.7: a única IDE que você precisa!
Netbeans 6.7: a única IDE que você precisa!João Longo
 
Processos iniciais do mapeamento OR
Processos iniciais do mapeamento ORProcessos iniciais do mapeamento OR
Processos iniciais do mapeamento ORNécio de Lima Veras
 
Palest"Tecnologias para Desenvolvimento Baseado em Componentes"
Palest"Tecnologias para Desenvolvimento Baseado em Componentes"Palest"Tecnologias para Desenvolvimento Baseado em Componentes"
Palest"Tecnologias para Desenvolvimento Baseado em Componentes"sbcars
 
Introducao banco de dados
Introducao banco de dadosIntroducao banco de dados
Introducao banco de dadosvaniakenob
 
Java, NetBeans e Orientação a Objetos
Java, NetBeans e Orientação a ObjetosJava, NetBeans e Orientação a Objetos
Java, NetBeans e Orientação a ObjetosJoão Longo
 
Projeto Octopus - Database Sharding para ActiveRecord
Projeto Octopus - Database Sharding para ActiveRecordProjeto Octopus - Database Sharding para ActiveRecord
Projeto Octopus - Database Sharding para ActiveRecordtchandy
 

Semelhante a Persistência com Hibernate - Curso sobre o framework Hibernate (20)

1 jdbc
1 jdbc1 jdbc
1 jdbc
 
Curso de Java (Parte 5)
Curso de Java (Parte 5)Curso de Java (Parte 5)
Curso de Java (Parte 5)
 
GlassFish, Maven, Cloud e o futuro do Java EE
GlassFish, Maven, Cloud e o futuro do Java EEGlassFish, Maven, Cloud e o futuro do Java EE
GlassFish, Maven, Cloud e o futuro do Java EE
 
Aula 6 conexão bd
Aula 6 conexão bdAula 6 conexão bd
Aula 6 conexão bd
 
Introdução a jsf
Introdução a jsfIntrodução a jsf
Introdução a jsf
 
GlassFish, Maven, Cloud e Java EE
GlassFish, Maven, Cloud e Java EEGlassFish, Maven, Cloud e Java EE
GlassFish, Maven, Cloud e Java EE
 
Apresentação palestra ireport
Apresentação palestra ireportApresentação palestra ireport
Apresentação palestra ireport
 
Netbeans 6.7: a única IDE que você precisa!
Netbeans 6.7: a única IDE que você precisa!Netbeans 6.7: a única IDE que você precisa!
Netbeans 6.7: a única IDE que você precisa!
 
Spring data
Spring dataSpring data
Spring data
 
Java web
Java webJava web
Java web
 
Processos iniciais do mapeamento OR
Processos iniciais do mapeamento ORProcessos iniciais do mapeamento OR
Processos iniciais do mapeamento OR
 
Minicurso jpa e hibernate
Minicurso jpa e hibernateMinicurso jpa e hibernate
Minicurso jpa e hibernate
 
Mini curso JBC
Mini curso JBCMini curso JBC
Mini curso JBC
 
Pgbr2013
Pgbr2013Pgbr2013
Pgbr2013
 
MC - Java Enterprise Edition 6 (Java EE)
MC - Java Enterprise Edition 6 (Java EE)MC - Java Enterprise Edition 6 (Java EE)
MC - Java Enterprise Edition 6 (Java EE)
 
Palest"Tecnologias para Desenvolvimento Baseado em Componentes"
Palest"Tecnologias para Desenvolvimento Baseado em Componentes"Palest"Tecnologias para Desenvolvimento Baseado em Componentes"
Palest"Tecnologias para Desenvolvimento Baseado em Componentes"
 
Introducao banco de dados
Introducao banco de dadosIntroducao banco de dados
Introducao banco de dados
 
Java, NetBeans e Orientação a Objetos
Java, NetBeans e Orientação a ObjetosJava, NetBeans e Orientação a Objetos
Java, NetBeans e Orientação a Objetos
 
Projeto Octopus - Database Sharding para ActiveRecord
Projeto Octopus - Database Sharding para ActiveRecordProjeto Octopus - Database Sharding para ActiveRecord
Projeto Octopus - Database Sharding para ActiveRecord
 
Java web
Java webJava web
Java web
 

Persistência com Hibernate - Curso sobre o framework Hibernate

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

Notas do Editor

  1. 1o. Gráfico refere-se a uma app sem Hibernate 2o. Gráfico – um app sem EJB usando Hibernate
  2. Uma app EJB com hibernate
  3. LazyInitializationException pode acontecer quando Lazy Loading estiver ligado, a sessão tiver sido fechada e um objeto ainda não carregado seja solicitado.
  4. \\
  5. \\
  6. \\
  7. Fale sobre a interface Query.
  8. Example é uma classe do Hibernate usada para montar a query de acordo com o exemplo de classe passado.
  9. Como não é possível fazer um proxy de um array puro, o lazy loading não funciona.
  10. Como não é possível fazer um proxy de um array puro, o lazy loading não funciona.