Hibernate

4.941 visualizações

Publicada em

Material do Curso de Hibernate 2008

Publicada em: Tecnologia
1 comentário
1 gostou
Estatísticas
Notas
Sem downloads
Visualizações
Visualizações totais
4.941
No SlideShare
0
A partir de incorporações
0
Número de incorporações
5
Ações
Compartilhamentos
0
Downloads
193
Comentários
1
Gostaram
1
Incorporações 0
Nenhuma incorporação

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

    1. 1. Hibernate Persistência com Hibernate Régis Melo @regismelo@regismelo 1
    2. 2. Hibernate MissãoApresentar, motivar e exercitar mecanismosde persistência em Java, com enfoque noframework Hibernate. @regismelo 2
    3. 3. Hibernate Metodologias• Exposição e discussão teóricas;• Exercícios práticos de projeto e modelagem em laboratório. @regismelo 3
    4. 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. 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. 6. Hibernate Livros sugeridos@regismelo 6
    7. 7. HibernatePrepara os teus trabalhos de fora, apronta bem o teu campo; e depois edifica a tua casa. Provérbios 24:27@regismelo 7
    8. 8. Hibernate Módulo I E no princípio, era o JDBC…@regismelo 8
    9. 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. 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. 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. 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. 13. Hibernate API JDBC@regismelo 13
    14. 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. 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. 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. 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. 18. Hibernate Tipo 2 – Java Nativo• Java / Nativo Aplicação JAVA Dados API API Driver Nativa JDBC JDBC SGBD @regismelo 18
    19. 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. 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. 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. 22. Hibernate Tipo 4 – All Java Driver• All Java Driver Aplicação API Driver JDBC Dados JAVA JDBC @regismelo 22
    23. 23. Hibernate@regismelo 23
    24. 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. 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. 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. 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. 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. 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. 30. Hibernate Executando uma consultaStatement 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. 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. 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. 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. 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. 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. 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. 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. 38. Hibernate ResultSet e os métodos get@regismelo 38
    39. 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. 40. Hibernate Para saber mais• http://java.sun.com/docs/books/tutorial/jdbc/index .html @regismelo 40
    41. 41. Hibernate Módulo II Pool de conexões@regismelo 41
    42. 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. 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. 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. 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. 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. 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. 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. 49. Hibernate Pool de Conexões no TomCat@regismelo 49
    50. 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. 51. Hibernate Pool de Conexões no TomCatNome da conexão JNDIString DataSource Específico do Driver JDBCNome da Classe JDBCQuantidade máxima de conexões abertas pelo poolQuantidade 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. 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. 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. 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. 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. 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. 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. 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. 59. Hibernate Para saber mais• http://jakarta.apache.org/tomcat/tomcat-5.0-doc/jndi-r @regismelo 59
    60. 60. Hibernate Módulo III Data Access Objects@regismelo 60
    61. 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. 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. 63. Hibernate Estrutura de um DAO@regismelo 63
    64. 64. Hibernate Estrutura de um DAO@regismelo 64
    65. 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. 66. Hibernate DAO e Abstract Factorypublic 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. 67. Hibernate DAO e Abstract Factorypublic 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. 68. Hibernate DAO e Abstract Factorypublic 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. 69. Hibernate DAO e Abstract Factorypublic class Teste { public static void main( String args[] ) { AutorDAO autorDAO = DAOFactory.getInstance( conn, AutorDAO.class ); autorDAO.getAutores(); ... }}____________________________________________________________________________ @regismelo 69
    70. 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. 71. Hibernate Para saber mais• http://java.sun.com/j2ee/patterns/DataAccessObject.html• http://www.fluffycat.com/java/JavaNotes-GoFAbstractFactory.h @regismelo 71
    72. 72. Hibernate Módulo IV Frameworks de Persistência@regismelo 72
    73. 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. 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. 75. HibernateImplementaçõ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. 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. 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. 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. 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. 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. 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. 82. Hibernate Módulo V Hibernating…@regismelo 82
    83. 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. 84. Hibernatepackage 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 98. Hibernate Módulo V Ant@regismelo 98
    99. 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. 100. Hibernate Integração contínua com Ant@regismelo 100
    101. 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. 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. 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. 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. 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. 106. Hibernate Ant: Como funciona?@regismelo 106
    107. 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. 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. 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. 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. 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. 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. 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. 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. 115. Hibernate Para saber mais• http://ant.apache.org/• Exemplos de build files dos projetos Jakarta @regismelo 115
    116. 116. Hibernate Módulo VII Hibernate – Entendendo a Arquitetura@regismelo 116
    117. 117. Hibernate Arquitetura@regismelo 117
    118. 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. 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. 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. 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. 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. 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. 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. 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. 126. Hibernate Configurações@regismelo 126
    127. 127. Hibernate Configurações@regismelo 127
    128. 128. Hibernate Configurações@regismelo 128
    129. 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. 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. 131. Hibernate Classe Helper Hibernatepublic class HibernateUtil { private static final SessionFactory sessionFactory; static { try { // Create the SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory(); } catch (HibernateException ex) { System.out.println(ex); throw new RuntimeException(“Problemas na configuracao: " + ex.getMessage(), ex); } }} @regismelo 131
    132. 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. 133. Hibernatepublic 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. 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. 135. Hibernate Para saber mais• Hibernate in Action, chapter 3;• @regismelo 135
    136. 136. Hibernate Módulo VIII Trabalhando com Persistent Objects@regismelo 136
    137. 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. 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. 139. Hibernate Persistence Lifecycle@regismelo 139
    140. 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. 141. HibernateSession session = HibernateUtil.currentSession();Transaction trans = session.beginTransaction(); ObjetoMessage message = new Message(); transientemessage.setText("Hello World of Hibernate!"); Objetosession.save(message); persistentetrans.commit();session.close(); @regismelo 141
    142. 142. HibernateSession session = HibernateUtil.currentSession();Transaction trans = session.beginTransaction();// Instanciar uma nova classe messageMessage newMessage = new Message(); ObjetonewMessage.setText("Hibernate é fácil!"); transiente// 1 é o código da primeira mensagem geradaMessage messageOriginal = (Message) session.load( Message.class, new Long(1) );messageOriginal.setText("Hello World, de novo!");messageOriginal.setNextMessage( newMessage );trans.commit();session.close(); Objeto persistente pois foi associado a outro objeto persistente @regismelo 142
    143. 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. 144. HibernateSession 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 persistentestrans.commit();session.close(); @regismelo 144
    145. 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. 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. 147. Hibernate Persistence Manager• Alterando objetos:user.setPassword("secret");Session sessionTwo = sessions.openSession();Transaction tx = sessionTwo.beginTransaction();sessionTwo.update(user);user.setUsername("jonny"); Somentetx.commit(); necessário sesessionTwo.close(); for um objeto desconectado @regismelo 147
    148. 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 alteratx.commit(); objetosessionTwo.close(); @regismelo 148
    149. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 160. HibernateList 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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

    ×