Curso De Hibernate 3

15,859 views
15,546 views

Published on

Published in: Technology
4 Comments
16 Likes
Statistics
Notes
No Downloads
Views
Total views
15,859
On SlideShare
0
From Embeds
0
Number of Embeds
395
Actions
Shares
0
Downloads
1,415
Comments
4
Likes
16
Embeds 0
No embeds

No notes for slide

Curso De Hibernate 3

  1. 1. Curso: Persistência em Java com Hibernate <ul><ul><li>Instrutor: Fabrício Lemos </li></ul></ul>23/04/2007
  2. 2. Persistência <ul><li>É um tópico vital para o desenvolvimento de aplicações </li></ul><ul><li>Quase todas as aplicações necessitam que dados sejam persistidos </li></ul><ul><li>Necessidades </li></ul><ul><ul><li>Armazenamento </li></ul></ul><ul><ul><li>Busca </li></ul></ul><ul><ul><li>Organização </li></ul></ul><ul><ul><li>Compartilhamento dos dados </li></ul></ul>
  3. 3. Persistência <ul><li>Necessidades </li></ul><ul><ul><li>Integridade dos dados </li></ul></ul><ul><ul><li>Controle de concorrência </li></ul></ul><ul><li>Performance e a escalabilidade são fortemente afetadas pela estratégia de acesso a dados escolhida </li></ul>
  4. 4. Banco de Dados Relacionais <ul><li>Geralmente são utilizados banco de dados SQL </li></ul><ul><ul><li>Flexível </li></ul></ul><ul><ul><li>Robusto </li></ul></ul><ul><ul><li>Eficiente </li></ul></ul><ul><ul><li>Confiável </li></ul></ul><ul><ul><li>Maneira mais utilizada e conhecida de armazenar dados </li></ul></ul>
  5. 5. Banco de Dados Relacionais <ul><li>Dados são armazenados de forma independente </li></ul><ul><ul><li>Independência de linguagem </li></ul></ul><ul><ul><li>Independência de aplicação </li></ul></ul><ul><li>Os dados geralmente possuem longevidade maior do que as aplicações que os acessam </li></ul><ul><li>A utilização de algum framework não elimina a necessidade de conhecimento de SQL e do modelo relacional </li></ul>
  6. 6. Persistindo dados com Java <ul><li>Realizado através da API Java Database Connectivity (JDBC) </li></ul><ul><li>Tarefas de baixo nível </li></ul><ul><ul><li>Preparar consultas </li></ul></ul><ul><ul><li>Associar parâmetros </li></ul></ul><ul><ul><li>Executar a consulta </li></ul></ul><ul><ul><li>Percorrer e retornar o resultado </li></ul></ul><ul><li>Tarefas de alto nível </li></ul><ul><ul><li>Salvar e recuperar objetos </li></ul></ul>
  7. 7. Persistindo objetos com Java (ou qualquer outra linguagem OO) <ul><li>Linguagem orientada a objetos </li></ul><ul><li>Deve-se poder armazenar o estado de um objeto, mesmo após o objeto ser destruído </li></ul><ul><li>Deve ser possível criar um novo objeto com o mesmo estado do anterior </li></ul><ul><li>Operações não devem ser limitadas a um único objeto </li></ul><ul><ul><li>Associações devem ser salvas </li></ul></ul>
  8. 8. Persistindo objetos com Java <ul><li>A aplicação deve trabalhar diretamente com objetos, ao invés de linhas e colunas da base de dados </li></ul><ul><li>Lógica de negócio deve ser implementada na aplicação, utilizando-se Java, e não diretamente na base de dados </li></ul><ul><ul><li>Limitar o uso de stored procedures </li></ul></ul><ul><li>Conceitos da Orientação a Objetos não devem ser restringidos pela solução adotada </li></ul>
  9. 9. Diferença dos Paradigmas: OO/Relacional <ul><li>Granularidade </li></ul><ul><ul><li>Objetos de baixa granularidade podem ser persistidos em tabelas de grande granularidade ou vice-versa </li></ul></ul><ul><ul><ul><li>Uma tabela armazena diversos tipos de objetos </li></ul></ul></ul><ul><ul><ul><li>Um objeto é armazenado em diversas tabelas </li></ul></ul></ul><ul><li>Herança </li></ul><ul><ul><li>Modelo relacional não possui o conceito de herança </li></ul></ul>
  10. 10. Diferença dos Paradigmas <ul><li>Polimorfismo </li></ul><ul><ul><li>Necessidade de um objeto referenciar outros através de superclasses </li></ul></ul><ul><ul><li>Uma referência pode estar associada o objetos de tipos diferentes </li></ul></ul><ul><ul><li>Chaves estrangeiras referenciam uma tabela específica </li></ul></ul>
  11. 11. Diferença dos Paradigmas OO/Relacional <ul><li>Identidade dos objetos </li></ul><ul><ul><li>Java </li></ul></ul><ul><ul><ul><li>Operador == </li></ul></ul></ul><ul><ul><ul><li>Método equals() </li></ul></ul></ul><ul><ul><li>Banco de dados </li></ul></ul><ul><ul><ul><li>Chave primária </li></ul></ul></ul><ul><ul><ul><li>Atualização de algum atributo que faz parte da chave requer que outras tabelas sejam atualizadas </li></ul></ul></ul>
  12. 12. Diferença dos Paradigmas OO/Relacional <ul><li>Associações </li></ul><ul><ul><li>OO possui associações unidirecionais e bidirecionais </li></ul></ul><ul><ul><li>Junções de tabelas e projeções não possuem o conceito de “direção” de uma associação </li></ul></ul><ul><ul><li>Associações em OO podem ser do tipo many-to-many </li></ul></ul><ul><ul><li>Associações entre tabelas só podem ser one-to-many e one-to-one </li></ul></ul><ul><ul><ul><li>Necessidade de criar uma tabela de relacionamento para associações many-to-many </li></ul></ul></ul><ul><ul><ul><li>Tabela não presente no modelo do domínio da aplicação </li></ul></ul></ul>
  13. 13. Diferença dos Paradigmas: Custo <ul><li>Necessário escrever muito código para (tentar) contornar o problema </li></ul><ul><li>Código se torna repetitivo e de difícil manutenção </li></ul><ul><li>A escrita de código SQL pode tornar a aplicação dependente do banco de dados </li></ul><ul><li>Modelagem dos objetos fica prejudicada </li></ul><ul><li>Outras camada ficam fortemente acopladas à Camada de Persistência </li></ul><ul><li>Produtividade pode ser fortemente afetada </li></ul>
  14. 14. Estratégias de Persistência <ul><li>JDBC e SQL </li></ul><ul><ul><li>Faz parte da plataforma Java </li></ul></ul><ul><ul><li>Necessário escrever bastante código de baixo nível </li></ul></ul><ul><li>Stored Procedures </li></ul><ul><ul><li>Lógica de negócio sai da aplicação e vai para a base de dados </li></ul></ul><ul><ul><li>Perde-se a portabilidade </li></ul></ul>
  15. 15. Estratégias de Persistência <ul><li>Framework corporativo </li></ul><ul><ul><li>Necessário grande esforço da empresa </li></ul></ul><ul><ul><li>Demora-se muito para que a solução implementada atinga maturidade </li></ul></ul><ul><ul><li>Documentação muitas vezes é esquecida </li></ul></ul><ul><ul><li>Falta de suporte </li></ul></ul>
  16. 16. Estratégias de Persistência <ul><li>Java Persistence API (JPA) </li></ul><ul><ul><li>Especificação elaborada pelo Java Community Process para persistência em Java </li></ul></ul><ul><ul><li>Baseou-se em diversas soluções existentes </li></ul></ul><ul><ul><li>Frameworks existentes passaram a implementar a especificação </li></ul></ul><ul><ul><li>Recursos são um sub-conjunto dos encontrados nos frameworks que a implementam </li></ul></ul><ul><ul><li>Atualizações são lentas e burocráticas </li></ul></ul>
  17. 17. Estratégias de Persistência <ul><li>Frameworks de terceiros </li></ul><ul><ul><li>TopLink </li></ul></ul><ul><ul><ul><li>Framework de persistência Objeto/Relacional </li></ul></ul></ul><ul><ul><ul><li>Desenvolvido pela Oracle </li></ul></ul></ul><ul><ul><ul><li>Gratuito para avaliação e nas fases de desenvolvimento </li></ul></ul></ul><ul><ul><li>Hibernate </li></ul></ul>
  18. 18. Hibernate <ul><li>Framework de mapeamento Objeto-Relacional </li></ul><ul><li>Preenche a lacuna entre a base de dados relacional e a aplicação orientada a objetos </li></ul><ul><li>Framework de persistência Java mais utilizado e documentado </li></ul><ul><li>Mantido pela Jboss sob a licensa LGPL </li></ul><ul><li>Suporta classes desenvolvidas com agregação, herança, polimorfismo, composição e coleções </li></ul>
  19. 19. Hibernate <ul><li>Permite a escrita de consultas tanto através de uma linguagem própria (HQL) como também através de SQL </li></ul><ul><li>Framework não intrusivo </li></ul><ul><ul><li>Não restringe a arquitetura da aplicação </li></ul></ul><ul><li>Implementa a especificação Java Persistence API </li></ul><ul><li>Grande e ativa comunidade </li></ul><ul><ul><li>Mais de 25 mil desenvolvedores registrados nos foruns oficiais </li></ul></ul>
  20. 20. Mapeamento Objeto Relacional <ul><li>Permite a persistência de objetos em tabelas de uma base de dados relacional </li></ul><ul><li>Automática e Transparente </li></ul><ul><li>Utiliza metadados para descrever o relacionamento entre os objetos e a base de dados </li></ul><ul><ul><li>XML </li></ul></ul><ul><ul><li>Xdoclet </li></ul></ul><ul><ul><li>Annotations </li></ul></ul>
  21. 21. Mapeamento Objeto Relacional <ul><li>O SQL é gerado automaticamente a partir dos metadados </li></ul><ul><li>A escrita e manutenção de metadados necessita de esforço nas etapas de implementação </li></ul><ul><ul><li>Esforço bem menor do que o necessário para fazer a conversão manualmente </li></ul></ul><ul><li>A conversão entre os tipos de representação pode trazer perca de performance </li></ul><ul><ul><li>Ferramentas maduras otimizam a conversão em diversos pontos </li></ul></ul>
  22. 22. Mapeamento Objeto Relacional <ul><li>Possui quatro partes principais </li></ul><ul><ul><li>API para realização de operações básicas (CRUD) </li></ul></ul><ul><ul><li>Linguagem ou API para a realização de consultas </li></ul></ul><ul><ul><li>Maneira para a especificação de metadados </li></ul></ul><ul><ul><li>Técnicas de otimização </li></ul></ul><ul><ul><ul><li>Dirty checking </li></ul></ul></ul><ul><ul><ul><li>Carregamento tardio (lazy association fetching) </li></ul></ul></ul>
  23. 23. Mapeamento Objeto Relacional: Vantagens <ul><li>Produtividade </li></ul><ul><ul><li>Elimina a necessidade de escrita de grande parte do código relativo a persistência </li></ul></ul><ul><ul><li>Maior tempo disponível para implementar a lógica da aplicação </li></ul></ul><ul><li>Manutenibilidade </li></ul><ul><ul><li>Menos código </li></ul></ul><ul><ul><li>Maior entendimento da aplicação </li></ul></ul><ul><ul><li>Camada de abstração </li></ul></ul><ul><ul><li>Facilita a refatoração </li></ul></ul>
  24. 24. Vantagens <ul><li>Performance </li></ul><ul><ul><li>Tarefas manuais nem sempre tem performance melhor do que tarefas automatizadas </li></ul></ul><ul><ul><ul><li>Considerando limitações de custo e tempo </li></ul></ul></ul><ul><ul><li>Frameworks maduros são bastantes otimizados </li></ul></ul><ul><ul><li>Com o aumento de produtividade, você pode dedicar mais tempo para resolver possíveis gargalos </li></ul></ul><ul><li>Portabilidade </li></ul><ul><ul><li>Independência nem sempre é algo simples de ser alcançado, mesmo em aplicações Java </li></ul></ul><ul><ul><li>Suporte a diversos tipos de banco de dados </li></ul></ul>
  25. 25. Hibernate: Módulos <ul><li>Hibernate Core </li></ul><ul><ul><li>Contém os serviços básicos </li></ul></ul><ul><ul><li>Metadados escritos em XML </li></ul></ul><ul><ul><li>Consultas </li></ul></ul><ul><ul><ul><li>HQL: Hibernate Query Language </li></ul></ul></ul><ul><ul><ul><li>Interfaces utilizando critérios e exemplos </li></ul></ul></ul><ul><ul><li>Não depende de outros módulos </li></ul></ul><ul><ul><li>Não depende de uma versão específica do JDK </li></ul></ul><ul><ul><li>Executável em qualquer servidor Web e/ou de Aplicação e também em aplicações desktop </li></ul></ul>
  26. 26. Módulos <ul><li>Hibernate Annotations </li></ul><ul><ul><li>Permite a escrita de metadados através de Annotations </li></ul></ul><ul><ul><li>Beneficia-se da tipagem do Java </li></ul></ul><ul><ul><li>Compatível com refatorações de código </li></ul></ul><ul><ul><li>Semântica familiar para quem já está acostumado com metadados em XML </li></ul></ul><ul><ul><li>Utiliza as Annotations da especificação JPA </li></ul></ul><ul><ul><li>Possui Annotations próprias para configurações avançadas não presentes na especificação </li></ul></ul><ul><ul><li>Necessita do JDK 5.0 </li></ul></ul>
  27. 27. Módulos <ul><li>Hibernate Entity Manager </li></ul><ul><ul><li>Implementação da especificação JPA </li></ul></ul><ul><ul><li>Permite a escrita de código compatível com qualquer framework de persistência que implemente a especificação </li></ul></ul><ul><ul><li>Utiliza o pacote javax.persistence </li></ul></ul><ul><ul><li>Não disponibiliza todas as funcionalidades do Hibernate </li></ul></ul>
  28. 28. Separação em camadas <ul><li>É uma boa prática dividir aplicações de médio e grande porte em camadas </li></ul><ul><ul><li>Padrão Layers (Pattern-Oriented Software architecture) </li></ul></ul><ul><li>Divisão mais utilizada </li></ul><ul><ul><li>Apresentação </li></ul></ul><ul><ul><li>Negócio </li></ul></ul><ul><ul><li>Persistência </li></ul></ul>
  29. 29. Separação em camadas <ul><li>Permite a especificação de intefaces para os diversos tipos de serviços </li></ul><ul><ul><li>A implementação pode ser mudada sem afetar significativamente o código de outras camadas </li></ul></ul><ul><li>A comunicação ocorre das camadas superiores para as camadas inferiores </li></ul><ul><li>Uma camada só depende da camada imediatamente inferior </li></ul><ul><ul><li>Camada de apresentação não sabe da existência da camada de persistência </li></ul></ul>
  30. 31. Criando um projeto
  31. 32. Next >....
  32. 33. Finish
  33. 34. Adicionando as bibliotecas
  34. 35. Criando uma entidade @Entity @Table (name = &quot;MESSAGES&quot; ) public class Message { @Id @GeneratedValue @Column (name = &quot;MESSAGE_ID&quot; ) private Long id ; @Column (name = &quot;MESSAGE_TEXT&quot; ) private String text ; @ManyToOne (cascade = CascadeType. ALL ) @JoinColumn (name = &quot;NEXT_MESSAGE_ID&quot; ) private Message nextMessage ; private Message() {} public Message(String text) { this . text = text; } //gets e sets }
  35. 36. Annotations da classe <ul><li>Entity </li></ul><ul><ul><li>Informa que a classe pode ser persistida pelo Hibernate </li></ul></ul><ul><li>Table </li></ul><ul><ul><li>Informa o nome da tabela em que os objetos da classe devem ser armazenados </li></ul></ul>@Entity @Table (name = &quot;MESSAGES&quot; ) public class Message {
  36. 37. Construtores <ul><li>Obrigatório um construtor sem argumentos </li></ul>private Message() {} public Message(String text) { this . text = text; }
  37. 38. Propriedades <ul><li>Representa o identificador do objeto </li></ul><ul><li>Preenchido automaticamente quando o objeto é salvo </li></ul><ul><li>Mapeado para a chave primária da tabela </li></ul><ul><li>Se duas instâncias tiverem o mesmo identificador, elas representam a mesma linha da tabela </li></ul>@Id @GeneratedValue @Column (name = &quot;MESSAGE_ID&quot; ) private Long id ;
  38. 39. Atributos <ul><li>O atributo text é armazenado na coluna MESSAGE_TEXT </li></ul>@Column (name = &quot;MESSAGE_TEXT&quot; ) private String text ; <ul><li>O atributo nextMessage é uma associação many-to-one </li></ul><ul><li>Mapeado pela chave estrangeira NEXT_MESSAGE_ID </li></ul>@ManyToOne (cascade = CascadeType. ALL ) @JoinColumn (name = &quot;NEXT_MESSAGE_ID&quot; ) private Message nextMessage ;
  39. 40. Transparência <ul><li>Não há a necessidade de se herdar de uma superclasse ou de implementar um interface </li></ul><ul><ul><li>POJO - Plain Ordinary Java Objects </li></ul></ul><ul><li>Classes podem ser reutilizadas fora do contexto de persistência </li></ul><ul><ul><li>Interface com o usuário </li></ul></ul><ul><ul><li>Testes de unidades </li></ul></ul><ul><li>As entidades não precisam nem saber que serão persistidas </li></ul><ul><li>Grande nível de portabilidade </li></ul>
  40. 41. Configurando o Hibernate <ul><li>Configuração feita através do arquivo hibernate.cfg.xml </li></ul><ul><li>Deve estar localizado na raiz do classpath </li></ul><ul><ul><li>Localização default </li></ul></ul><ul><ul><li>Para projetos maven, utilizar a pasta src/main/resources </li></ul></ul><ul><li>Configurações contém </li></ul><ul><ul><li>Parâmetros de acesso a base de dados </li></ul></ul><ul><ul><li>Pool de conexões </li></ul></ul><ul><ul><li>Entidades a serem persistidas </li></ul></ul>
  41. 42. hibernate.cfg.xml < hibernate-configuration > < session-factory > <!-- Parâmetros de acesso a base de dados --> < property name = &quot;connection.driver_class&quot; > org.postgresql.Driver </ property > < property name = &quot;connection.url&quot; > jdbc:postgresql://localhost:5432/curso </ property > < property name = &quot;connection.username&quot; > postgresql </ property > < property name = &quot;connection.password&quot; > postgresql </ property > < property name = &quot;dialect&quot; > org.hibernate.dialect.PostgreSQLDialect </ property > ...
  42. 43. hibernate.cfg.xml ... <!-- Configuração do Pool de conexões --> < property name = &quot;c3p0.min_size&quot; > 5 </ property > < property name = &quot;c3p0.max_size&quot; > 20 </ property > < property name = &quot;c3p0.timeout&quot; > 300 </ property > < property name = &quot;c3p0.max_statements&quot; > 50 </ property > < property name = &quot;c3p0.idle_test_period&quot; > 3000 </ property > <!-- Exibe no console o SQL gerado pelo hibernate--> < property name = &quot;show_sql&quot; > true </ property > <!-- Cria e executa a DDL (tabelas, colunas, etc...)--> < property name = &quot;hbm2ddl.auto&quot; > create </ property > <!-- Informa as Entidades da aplicação --> < mapping class = &quot;br.gov.serpro.curso.hibernate.exemplo1.Message&quot; /> </ session-factory > </ hibernate-configuration >
  43. 44. Armazenando uma Mensagem //Obtendo o Session Session session = HibernateUtil.getSessionFactory().openSession(); //Iniciando a transação Transaction tx = session.beginTransaction(); // Criando uma mensagem Message message = new Message( &quot;Hello World&quot; ); // Salvando a Mensagem Long msgId = (Long) session.save(message); //Fazendo o commit da transação tx.commit(); //Fechando o Session session.close(); HibernateUtil.shutdown();
  44. 45. Objetos utilizados <ul><li>Session </li></ul><ul><ul><li>Contém métodos utilizados para armazenar e recuperar entidades </li></ul></ul><ul><ul><li>Armazena uma lista de comandos SQL que serão executados, em algum momento, na base de dados </li></ul></ul><ul><ul><li>Mantém as entidades gerenciadas pelo Hibernate </li></ul></ul><ul><ul><ul><li>Recuperadas, inseridas ou atualizadas através do Session </li></ul></ul></ul><ul><ul><li>Único para cada thread </li></ul></ul>
  45. 46. Objetos utilizados <ul><li>Transaction </li></ul><ul><ul><li>Utilizado para delimitar as transações com a base de dados </li></ul></ul><ul><ul><li>Geralmente gerenciado pelo container </li></ul></ul><ul><ul><ul><li>EJB </li></ul></ul></ul><ul><ul><ul><li>Spring </li></ul></ul></ul><ul><li>SessionFactory </li></ul><ul><ul><li>Utilizado para criar os Session </li></ul></ul><ul><ul><li>Reutilizável por toda a aplicação </li></ul></ul>
  46. 47. HibernateUtil public class HibernateUtil { private static SessionFactory sessionFactory ; static { sessionFactory = new AnnotationConfiguration().configure() .buildSessionFactory(); } public static SessionFactory getSessionFactory() { return sessionFactory ; } public static void shutdown() { getSessionFactory ().close(); } }
  47. 48. Recuperando as Mensagens Session newSession = HibernateUtil.getSessionFactory().openSession(); Transaction newTransaction = newSession.beginTransaction(); //Criando e executando uma consulta Query query = newSession .createQuery( &quot;from Message m order by m.text asc&quot; ); List<Message> messages = query.list(); //Retornando a quantidade de mensagens encontradas System. out .println(messages.size() + &quot; message(s) found:&quot; ); //Retornando as mensagens encontradas for (Message msg : messages) { System. out .println(msg.getText()); } newTransaction.commit(); newSession.close(); HibernateUtil.shutdown();
  48. 49. Objetos Utilizados <ul><li>Query </li></ul><ul><ul><li>Cria as consultas </li></ul></ul><ul><ul><li>Associa os parâmetros </li></ul></ul><ul><ul><li>Executa as consultas </li></ul></ul>
  49. 50. Dirty Checking e Cascade Session thirdSession = HibernateUtil.getSessionFactory().openSession(); Transaction thirdTransaction = thirdSession.beginTransaction(); // recuperando a mensagem message = (Message) thirdSession.get(Message. class , msgId); //Alterando o texto message.setText( &quot;Greetings Earthling&quot; ); //Criando uma nova mensagem e associando à antiga message.setNextMessage( new Message( &quot;Take me to your leader&quot; )); thirdTransaction.commit(); thirdSession.close(); HibernateUtil.shutdown();
  50. 51. Dirty Checking e Cascade <ul><li>Dirty Checking </li></ul><ul><ul><li>O Hibernate automaticamente verifica quando um atributo é modificado </li></ul></ul><ul><ul><li>O atributo é atualizado na base de dados sem a necessidade de uma chamada explicita </li></ul></ul><ul><ul><li>É possível somente dentro de uma transação e para objetos gerenciados pelo Session </li></ul></ul><ul><li>Cascade </li></ul><ul><ul><li>Novas entidades são persistidas automaticamente </li></ul></ul><ul><ul><li>Devem ser alcançáveis a partir de uma entidade gerenciada </li></ul></ul>
  51. 52. Metadados <ul><li>Utilizados para especificar o mapeamento entre </li></ul><ul><ul><li>Classes e tabelas </li></ul></ul><ul><ul><li>Propriedades e colunas </li></ul></ul><ul><ul><li>Associações e chaves estrangeiras </li></ul></ul><ul><ul><li>Tipos de atributos Java e tipos de atributos SQL </li></ul></ul><ul><li>Pode ser escrita de duas formas </li></ul><ul><ul><li>Arquivos XML </li></ul></ul><ul><ul><li>Xdoclet </li></ul></ul><ul><ul><li>Java Annotations </li></ul></ul>
  52. 53. Porque não usar XML <ul><li>Pode ser tornar pouco legível e de difícil edição </li></ul><ul><ul><li>Requer maior digitação </li></ul></ul><ul><ul><li>Falta de valores default para atributos e elementos </li></ul></ul><ul><li>Não necessariamente mais flexível e mais fácil de manter do que código Java </li></ul><ul><li>Mais fácil encontrar um bom editor Java do que um bom editor de XML </li></ul>
  53. 54. Metadados com Annotations <ul><li>A meta-informação fica perto dos dados que ela descreve </li></ul><ul><li>Compatível com refatoração de código </li></ul><ul><ul><li>Renomear, deletar e remover classes e propriedades </li></ul></ul><ul><li>Sem necessidade de fazer parser em XML </li></ul><ul><ul><li>Inicialização mais rápida </li></ul></ul><ul><li>Lido através de reflection na inicialização do Hibernate </li></ul><ul><li>Disponível a partir da JDK 5.0 </li></ul>
  54. 55. Mapeando Propriedades <ul><li>Ao mapear uma classe através da Annotation @ Entity , todas as propriedades serão consideradas persistentes </li></ul><ul><li>Propriedades não persistentes devem receber a Annotation @ Transient ou o modificador transient </li></ul><ul><li>Por default, o nome da coluna será o mesmo da propriedade </li></ul><ul><li>Meio de acesso é o mesmo do @ID </li></ul><ul><ul><li>Definido na propriedade ou no método get() </li></ul></ul>
  55. 56. @Column <ul><li>Aplicável para propriedades simples </li></ul><ul><li>Atributos </li></ul><ul><ul><li>name </li></ul></ul><ul><ul><ul><li>Nome da coluna a qual a propriedade é mapeada </li></ul></ul></ul><ul><ul><li>unique </li></ul></ul><ul><ul><ul><li>Se o valor deve ser único ou não </li></ul></ul></ul><ul><ul><li>nullable </li></ul></ul><ul><ul><ul><li>Se a propriedade pode ser nula ou não </li></ul></ul></ul>
  56. 57. Mapeando Propriedades: Tipos
  57. 58. Mapeando Propriedades: Tipos
  58. 59. Datas <ul><li>Propriedades podem ser do tipo java.util.Date ou java.util.Calendar </li></ul><ul><li>Precisão default é TIMESTAMP </li></ul><ul><li>Precisão pode ser alterada através da Annotation @Temporal </li></ul>@Temporal (TemporalType. DATE ) private Date date1 ; @Temporal (TemporalType. TIME ) private Date date2 ; @Temporal (TemporalType. TIMESTAMP ) private Date date3 ;
  59. 60. Identidade das Entidades <ul><li>Identidade versus Equivalência em Java </li></ul><ul><ul><li>Identidade </li></ul></ul><ul><ul><ul><li>Operador == </li></ul></ul></ul><ul><ul><ul><li>Definido pela máquina virtual </li></ul></ul></ul><ul><ul><ul><li>Dois objetos são idênticos se eles apontam para o mesmo local da memória </li></ul></ul></ul><ul><ul><li>Equivalência </li></ul></ul><ul><ul><ul><li>Definida pelas classes que sobreescrevem o método equals() </li></ul></ul></ul><ul><ul><ul><li>Dois objetos diferentes possuem o mesmo valor </li></ul></ul></ul><ul><ul><ul><li>Dois objetos String podem ter a mesma seqüência de caracteres </li></ul></ul></ul>
  60. 61. Identidade das Entidades <ul><li>Identidade na base de dados </li></ul><ul><ul><li>Duas Entidades são idênticas se elas representam a mesma linha na base de dados </li></ul></ul><ul><ul><ul><li>Se são armazenadas na mesma tabela e possuem a mesma chave primária </li></ul></ul></ul>
  61. 62. Adicionando um Identificador <ul><li>O valor é gerado automaticamente pelo Hibernate </li></ul><ul><li>Não deve ser mudado pela aplicação </li></ul>@Entity @Table (name= &quot;CATEGORY&quot; ) public class Category { @Id @GeneratedValue (strategy = GenerationType. AUTO ) @Column (name = &quot;CATEGORY_ID&quot; ) private Long id ; public Long getId() { return id ; } }
  62. 63. Escolhendo a chave primária <ul><li>Uma chave candidata é uma coluna, ou um conjunto de colunas, que pode ser utilizada para identificar um registro na base de dados </li></ul><ul><li>Requisitos </li></ul><ul><ul><li>O valor nunca deve ser nulo </li></ul></ul><ul><ul><li>Cada registro deve ter um valor único </li></ul></ul><ul><ul><li>O valor nunca deve mudar </li></ul></ul>
  63. 64. Escolhendo a chave primária <ul><li>Chaves naturais são aquelas que possuem significado para o domínio da aplicação </li></ul><ul><ul><li>CPF de um usuário </li></ul></ul><ul><ul><li>Seqüencial gerado pela aplicação </li></ul></ul><ul><li>Dificilmente chaves naturais atendem os requisitos necessários </li></ul>
  64. 65. Escolhendo a chave primária <ul><li>Chaves cegas </li></ul><ul><ul><li>Melhor alternativa </li></ul></ul><ul><ul><li>Não possuem significado para o domínio da aplicação </li></ul></ul><ul><ul><li>Geradas pelo banco de dados ou pela aplicação </li></ul></ul>
  65. 66. Geração automática de chaves <ul><li>Hibernate suporta diversas estratégias para geração automática de chaves </li></ul><ul><li>A estratégia deve ser especificada através da Annotations @ GeneratedValue </li></ul>
  66. 67. Estratégias <ul><li>IDENTITY </li></ul><ul><ul><li>Suporte para colunas IDENTITY nos bancos de dados DB2, MySQL, MS SQL Server, Sybase e HypersonicSQL </li></ul></ul><ul><ul><li>Os tipos devem ser long , short ou int </li></ul></ul><ul><li>SEQUENCE </li></ul><ul><ul><li>Utiliza um Sequence para a geração de chaves </li></ul></ul><ul><ul><li>Suporte para DB2, PostgreSQL e Oracle dentre outros </li></ul></ul><ul><ul><li>Nome default da sequence é hibernate_sequence </li></ul></ul>
  67. 68. Estratégias <ul><li>increment </li></ul><ul><ul><li>Na inicialização o Hibernate lê qual o maior valor para a chave da tabela </li></ul></ul><ul><ul><li>O valor é atribuído e incrementado em cada inserção </li></ul></ul><ul><ul><li>Não deve ser utilizado se o Hibernate não tiver acesso exclusivo para a base de dados </li></ul></ul>
  68. 69. Estratégias <ul><li>AUTO </li></ul><ul><ul><li>Escolhe entre as estratégias IDENTITY, SEQUENCE ou HILO </li></ul></ul><ul><ul><li>Estratégia escolhida depende do banco de dados utilizado </li></ul></ul><ul><ul><li>Utilizado para manter a portabilidade </li></ul></ul><ul><li>Outras </li></ul><ul><ul><li>hilo, seqhilo, uuid.hex, guid, select </li></ul></ul><ul><ul><li>IdentifierGenerator </li></ul></ul><ul><ul><ul><li>Permite a implementação de sua própria estratégia </li></ul></ul></ul>
  69. 70. Mapeando Componentes <ul><li>Entidades são classes persistentes que representam objetos do domínio da aplicação </li></ul><ul><ul><li>Possuem identidade própria </li></ul></ul><ul><li>Hibernate suporta a construção de um modelo de objetos de alta granularidade </li></ul><ul><ul><li>Propriedades de uma Entidade podem ser encapsuladas em outros objetos </li></ul></ul><ul><ul><ul><li>Tais objetos não possuem identidade própria </li></ul></ul></ul><ul><ul><ul><li>Chamados de Objetos Valores ou Componentes </li></ul></ul></ul><ul><ul><li>Mais classes do que tabelas </li></ul></ul>
  70. 71. Mapeando Componentes
  71. 72. Mapeando Componentes <ul><li>User </li></ul><ul><ul><li>Representa uma Entidade </li></ul></ul><ul><ul><li>Possui identidade própria </li></ul></ul><ul><ul><ul><li>Chave primária na base de dados </li></ul></ul></ul><ul><ul><li>Uma referência para User é persistida como uma chave estrangeira </li></ul></ul><ul><ul><li>Tem seu próprio ciclo de vida </li></ul></ul><ul><ul><ul><li>Existe independentemente de qualquer outra entidade </li></ul></ul></ul>
  72. 73. Mapeando Componentes <ul><li>Address </li></ul><ul><ul><li>Representa um Componente </li></ul></ul><ul><ul><li>Não possui identidade própria </li></ul></ul><ul><ul><li>Pertence a Entidade User </li></ul></ul><ul><ul><li>Estado é persistido no registro referente ao User a qual está associado </li></ul></ul><ul><ul><li>Ciclo de vida dependente de User </li></ul></ul><ul><ul><li>Se dois Usuários morarem no mesmo apartamento, cada um tem uma referência para um objeto distinto </li></ul></ul><ul><ul><li>Comportamento similar a tipos como String e Integer </li></ul></ul>
  73. 74. Mapeando Componentes @Embeddable public class Address { @Column (name = &quot;ADDRESS_STREET&quot; , nullable = false ) private String street ; @Column (name = &quot;ADDRESS_CITY&quot; , nullable = false ) private String city ; //gets e sets... }
  74. 75. Mapeando Componentes @Entity @Table (name = &quot;USERS&quot; ) public class User { @Id @GeneratedValue (strategy=GenerationType. AUTO ) private Long id ; private String name ; private String email ; private Address address ; //gets e sets }
  75. 76. Mapeando Herança <ul><li>A utilização de uma tabela para cada entidade não funciona tão bem para heranças entre entidades </li></ul><ul><li>Bancos de dados SQL, de maneira geral, não possuem o conceito de herança </li></ul><ul><ul><li>Soluções proprietária podem comprometer a portabilidade da aplicação </li></ul></ul>
  76. 77. Estratégias <ul><li>Tabela por classe concreta </li></ul><ul><li>Tabela por classe concreta, utilizando junção </li></ul><ul><li>Tabela por hierarquia </li></ul><ul><li>Tabela por classe (concreta ou não) </li></ul>
  77. 78. Uma tabela por Classe Concreta: Modelagem
  78. 79. Uma tabela por Classe Concreta <ul><li>Estratégia mais simples </li></ul><ul><li>Todas propriedades de uma classe, incluindo as herdadas, são mapeadas para a mesma tabela </li></ul><ul><li>Mapeamento convencional pode ser utilizado </li></ul><ul><li>Não suporta associações polimórficas adequadamente </li></ul><ul><ul><li>Associação para classe abstrata necessitaria que a chave estrangeira referenciasse duas tabelas </li></ul></ul>
  79. 80. Uma tabela por Classe Concreta <ul><li>Diferentes colunas em diferentes tabelas passariam a possuir a mesma semântica </li></ul><ul><li>Recomendável somente para a hierarquia superior </li></ul><ul><ul><li>Associações polimórficas geralmente não necessárias e não recomendadas </li></ul></ul><ul><ul><li>Modificações na superclasse são muito raras </li></ul></ul>select CREDIT_CARD_ID, OWNER, NUMBER, EXP_MONTH, EXP_YEAR ... from CREDIT_CARD select BANK_ACCOUNT_ID, OWNER, ACCOUNT, BANKNAME, ... from BANK_ACCOUNT
  80. 81. Mapeando a Superclasse <ul><li>Mapear a super classe através da Annotattion @ MappedSuperclass </li></ul>@MappedSuperclass public abstract class BillingDetails { @Column (name = &quot;OWNER&quot; , nullable = false ) private String owner ; //gets e sets... }
  81. 82. Mapeando as Subclasses <ul><li>Nenhuma configuração extra é necessária </li></ul>@Entity public class BankAccount extends BillingDetails{ @Id @GeneratedValue private Long id ; private Integer account ; private String bank ; }
  82. 83. Mapeando as Subclasses <ul><li>Mapeamento das propriedades herdadas pode ser alterado </li></ul><ul><li>Adicionar a Annotation @AttributeOverride </li></ul>@Entity @AttributeOverride (name = &quot;owner&quot; , column = @Column (name = &quot;CC_OWNER&quot; , nullable = false )) public class CreditCard extends BillingDetails { @Id @GeneratedValue private Long id ; private String number ; }
  83. 84. Uma tabela por Classe Concreta: Union <ul><li>Com a utilização de consultas com Union, alguns problemas podem ser eliminados </li></ul><ul><li>Suporte a associações polimórficas </li></ul><ul><ul><li>Hibernate utiliza o Union para simular uma única tabela </li></ul></ul><ul><li>As subclasses herdam o Id da super-classe </li></ul>
  84. 85. Mapeando a Super Classe <ul><li>É utilizada a Annotation @Inheritance </li></ul>@Entity @Inheritance (strategy = InheritanceType. TABLE_PER_CLASS ) public class BillingDetails { @Id @ GeneratedValue @Column (name = &quot;BILLING_DETAILS_ID&quot; ) private Long id = null ; @Column (name = &quot;OWNER&quot; , nullable = false ) private String owner ; }
  85. 86. Mapeando as Subclasses <ul><li>Não é necessário mapear o identificador </li></ul><ul><ul><li>O Identificador é mapeado na super-classe </li></ul></ul>@Entity public class CreditCard extends BillingDetails{ @Column (name = &quot;CC_NUMBER&quot; ) private String number ; }
  86. 87. Tabela por Hierarquia
  87. 88. Tabela por Hierarquia <ul><li>Toda uma hierarquia é mapeada em uma única tabela </li></ul><ul><li>A tabela possui colunas para todas as propriedades de todas as entidades da hierarquia </li></ul><ul><li>A subclasse de cada registro é identificada através de uma coluna discriminatória </li></ul><ul><li>Vantagem </li></ul><ul><ul><li>Possui a melhor performance </li></ul></ul>
  88. 89. Tabela por Hierarquia <ul><li>Desvantagens </li></ul><ul><ul><li>Valores para colunas das subclasses devem sempre permitir NULL </li></ul></ul><ul><ul><ul><li>Perca da restrição NOT NULL </li></ul></ul></ul><ul><ul><li>Dados são desnormalizados </li></ul></ul>
  89. 90. Mapeando a Superclasse <ul><li>O valor do atributo strategy deve ser mudado para InheritanceType.SINGLE_TABLE </li></ul>@Entity @Inheritance (strategy = InheritanceType. SINGLE_TABLE ) public abstract class BillingDetails { @Id @GeneratedValue @Column (name = &quot;BILLING_DETAILS_ID&quot; ) private Long id = null ; @Column (name = &quot;OWNER&quot; , nullable = false ) private String owner ; }
  90. 91. Tabela por classe
  91. 92. Tabela por classe <ul><li>Uma tabela para todas as classes, incluindo as abstratas, que possuem propriedades para serem persistidas </li></ul><ul><li>Relação de herança é representada por uma chave estrangeira </li></ul><ul><li>As tabelas não contém colunas para as propriedades herdadas </li></ul><ul><li>A chave primária é também uma chave estrangeira para a super classe </li></ul>
  92. 93. Tabela por classe <ul><li>Vantagens </li></ul><ul><ul><li>Os dados são normalizados </li></ul></ul><ul><ul><li>Restrições podem ser mantidas </li></ul></ul><ul><li>Desvantagens </li></ul><ul><ul><li>Performance pode ser muito baixa para hierarquias complexas </li></ul></ul><ul><ul><ul><li>Necessidade de muitas junções </li></ul></ul></ul>
  93. 94. Mapeando a Superclasse <ul><li>O valor do atributo strategy deve ser mudado para InheritanceType.JOINED </li></ul>@Entity @Inheritance (strategy = InheritanceType. JOINED ) public abstract class BillingDetails { @Id @GeneratedValue @Column (name = &quot;BILLING_DETAILS_ID&quot; ) private Long id = null ; @Column (name = &quot;OWNER&quot; , nullable = false ) private String owner ; }
  94. 95. Mapeando as Subclasses <ul><li>Id é mapeado na super-classe </li></ul>@Entity public class CreditCard extends BillingDetails{ @Column (name = &quot;CC_NUMBER&quot; ) private String number ; }
  95. 96. Escolhendo a melhor estratégia <ul><li>Tabela por classe concreta, utilizando junção </li></ul><ul><ul><li>Se associações ou consultas polimórficas nunca ou raramente são utilizadas </li></ul></ul><ul><li>Tabela por hierarquia </li></ul><ul><ul><li>Se associações ou consultas polimórficas são utilizadas e </li></ul></ul><ul><ul><li>Se as subclasses declaram poucas propriedades </li></ul></ul><ul><ul><ul><li>Maior diferença entre as subclasses é o comportamento </li></ul></ul></ul>
  96. 97. Escolhendo a Melhor Estratégia <ul><li>Tabela por Classe </li></ul><ul><ul><li>Se associações ou consultas polimórficas são utilizadas e </li></ul></ul><ul><ul><li>Se as subclasses declaram muitas propriedades </li></ul></ul><ul><ul><ul><li>Maior diferença entre as subclasses são os dados que elas armazenam </li></ul></ul></ul><ul><ul><li>Se a largura e o comprimento da hierarquia não for muito grande </li></ul></ul>
  97. 98. Mapeando coleções <ul><li>Objetos podem possuir coleções </li></ul><ul><li>As coleções podem ter duas naturezas </li></ul><ul><ul><li>Coleções de valores </li></ul></ul><ul><ul><ul><li>Tipos primitivos </li></ul></ul></ul><ul><ul><ul><li>Componentes </li></ul></ul></ul><ul><ul><li>Coleções de entidades </li></ul></ul>
  98. 99. Coleção de tipos primitivos: Set <ul><li>Um Item possui um conjunto de imagens </li></ul><ul><li>Somente o nome da imagem é persistido </li></ul><ul><li>Nomes não devem ser duplicados para um determinado Item </li></ul>
  99. 100. Annotations <ul><li>@CollectionOfElements </li></ul><ul><ul><li>Utilizada para coleções de tipos primitivos ou para coleções de objetos valores </li></ul></ul><ul><li>@JoinTable </li></ul><ul><ul><li>Informa a tabela em que a coleção é persistida </li></ul></ul><ul><ul><li>Atributos </li></ul></ul><ul><ul><ul><li>Name </li></ul></ul></ul><ul><ul><ul><ul><li>Nome da tabela </li></ul></ul></ul></ul><ul><ul><ul><li>JoinColumns </li></ul></ul></ul><ul><ul><ul><ul><li>Coluna que é chave estrangeira </li></ul></ul></ul></ul><ul><ul><ul><ul><li>Chave estrangeira referencia a tabela da entidade que possui a coleção </li></ul></ul></ul></ul>
  100. 101. Annotations <ul><li>@JoinColumn </li></ul><ul><ul><li>É o tipo do atributo JoinColumns da Annotation @JoinTable </li></ul></ul><ul><ul><ul><li>Annotation dentro de outra Annotation </li></ul></ul></ul><ul><ul><li>Mapeia a coluna utilizada para junções </li></ul></ul><ul><ul><li>Atributos </li></ul></ul><ul><ul><ul><li>Name </li></ul></ul></ul><ul><ul><ul><ul><li>Nome da coluna </li></ul></ul></ul></ul>
  101. 102. Classe Item @Entity public class Item { @Id @GeneratedValue @Column (name = &quot;ITEM_ID&quot; ) private Long id ; private String name ; @CollectionOfElements @JoinTable (name = &quot;ITEM_IMAGE&quot; , joinColumns = @JoinColumn (name = &quot;ITEM_ID&quot; )) @Column (name = &quot;FILENAME&quot; , nullable = false ) private Set<String> images = new HashSet<String>(); }
  102. 103. Coleção de tipos primitivos: List <ul><li>Caso a aplicação necessite guardar a ordem dos elementos </li></ul><ul><li>Necessário uma coluna para informar a posição de cada elemento </li></ul>
  103. 104. Classe Item <ul><li>Deve-se adicionar a Annotation @IndexColumn </li></ul>@Entity public class Item { ... @CollectionOfElements @JoinTable (name = &quot;ITEM_IMAGE&quot; , joinColumns = @JoinColumn (name = &quot;ITEM_ID&quot; )) @Column (name = &quot;FILENAME&quot; , nullable = false ) @IndexColumn (name = &quot;POSITION&quot; ) private List<String> images = new ArrayList<String>(); }
  104. 105. Coleção de tipos primitivos: Map <ul><li>Se o Item possuir um Map de imagens </li></ul><ul><li>É necessário guardar o elemento e sua chave </li></ul>
  105. 106. Classe Item <ul><li>Utilizar a Annotation @MapKey </li></ul><ul><ul><li>Atributo columns informa o nome da coluna que armazena a chave </li></ul></ul>@Entity public class Item { ... @CollectionOfElements @JoinTable (name = &quot;ITEM_IMAGE&quot; , joinColumns = @JoinColumn (name = &quot;ITEM_ID&quot; )) @Column (name = &quot;FILENAME&quot; , nullable = false ) @MapKey (columns = @Column (name = &quot;IMAGENAME&quot; )) private Map<String, String> images = new HashMap<String, String>(); }
  106. 107. Associação entre Entidades <ul><li>Podem ser de diversas multiplicidades </li></ul><ul><ul><li>One-to-many </li></ul></ul><ul><ul><li>One-to-one </li></ul></ul><ul><ul><li>Many-to-many </li></ul></ul><ul><ul><li>Many-to-one </li></ul></ul><ul><li>Também são implementadas através de atributos </li></ul><ul><li>Para associações one-to-many e many-to-many é necessário a utilização de coleções </li></ul>
  107. 108. Implementando associações <ul><li>Coleções devem ser acessadas através de suas Interfaces </li></ul><ul><ul><li>Set, ao invés de HashSet </li></ul></ul><ul><ul><li>List, ao invés de ArrayList </li></ul></ul>
  108. 109. Associações Bidirecionais <ul><li>Os dois lados da associação devem estar consistentes </li></ul><ul><ul><li>Necessário mesmo para aplicações que não usam Hibernate </li></ul></ul>
  109. 110. Classe Category public class Category { private String name ; private Category parentCategory ; private Set<Category> childCategories = new HashSet<Category>(); //gets e sets //... }
  110. 111. Mantendo a Consistência Category aParent = new Category(); Category aChild = new Category(); aChild.setParentCategory(aParent); aParent.getChildCategories().add(aChild);
  111. 112. Relacionamento Pai-Filho
  112. 113. Classe Bid <ul><li>Relaciona-se a somente um Item </li></ul><ul><li>Mapeamento realizado através da Annotation @ManyToOne </li></ul><ul><li>Annotation @JoinColumn informa qual a chave estrangeira </li></ul><ul><ul><li>Atributo name </li></ul></ul><ul><ul><ul><li>Nome da coluna </li></ul></ul></ul><ul><ul><li>Atributo nullable </li></ul></ul><ul><ul><ul><li>Se o relacionamento é opcional ou não </li></ul></ul></ul>
  113. 114. Classe Bid @Entity public class Bid { @Id @GeneratedValue @Column (name = &quot;BID_ID&quot; ) private Long id ; private Integer amount ; @ManyToOne @JoinColumn (name = &quot;ITEM_ID&quot; , nullable = false ) private Item item ; }
  114. 115. Relacionamento Bidirecional <ul><li>O relacionamento pode ou não ser declarado como bidirecional </li></ul><ul><li>Para relacionamentos bidirecionais o outro lado da associação é mapeado com a Annotation inversa </li></ul><ul><ul><li>@OneToMany no caso de Item </li></ul></ul><ul><ul><ul><li>Classe Bid utiliza a Annotation @ManyToOne </li></ul></ul></ul>
  115. 116. Relacionamento Bidirecional @Entity public class Item { @Id @GeneratedValue @Column (name = &quot;ITEM_ID&quot; ) private Long id ; private String name ; @OneToMany (mappedBy = &quot;item&quot; ) private Set<Bid> bids = new HashSet<Bid>(); }
  116. 117. Relacionamento Bidirecional <ul><li>@OneToMany(mappedBy = &quot;item&quot;) </li></ul><ul><ul><li>Detalhes do mapeamento são configurados no outro lado da associação </li></ul></ul><ul><ul><ul><li>Através da Annotation @ManyToOne </li></ul></ul></ul><ul><li>Quando as referências de uma associação mudam, as duas propriedades são alteradas </li></ul><ul><ul><li>bid.setItem(item); </li></ul></ul><ul><ul><li>item.getBids().add(bid); </li></ul></ul>
  117. 118. Relacionamento Bidirecional <ul><li>Na base de dados somente uma atualização precisa ser feita </li></ul><ul><ul><li>Atualização da chave estrangeira </li></ul></ul><ul><ul><li>Hibernate não precisa executar dois comandos UPDATE </li></ul></ul><ul><li>Uma das alterações é sincronizada e a outra é ignorada </li></ul><ul><ul><li>Não há efeito colateral se as associações estiverem consistentes </li></ul></ul>
  118. 119. Relacionamento Bidirecional <ul><li>O lado que contém os detalhes do mapeamento é o lado que é sincronizado </li></ul><ul><ul><li>Relacionamentos many-to-one ou one-to-many </li></ul></ul><ul><ul><ul><li>Lado Many é sincronizado </li></ul></ul></ul><ul><ul><li>Relacionamento one-to-one </li></ul></ul><ul><ul><ul><li>Lado que possuir a chave estrangeira é sincronizado </li></ul></ul></ul><ul><ul><li>Relacionamento many-to-many </li></ul></ul><ul><ul><ul><li>Lado que mapear a tabela de junção é sincronizado </li></ul></ul></ul><ul><li>Os lados do relacionamento não sincronizados possuem o atributo mappedBy na Annotation </li></ul>
  119. 120. Relacionamento Bidirecional Bid bid = new Bid(); bid.setAmount(Integer. valueOf (1000)); Item item = new Item(); item.setName( &quot;computador&quot; ); bid.setItem(item); item.getBids(). add (bid); Session session = HibernateUtil. getSessionFactory ().openSession(); Transaction transaction = session.beginTransaction(); //O item tem que ser salvo primeiro session.save(item); session.save(bid);
  120. 121. Relacionamento One-to-One
  121. 122. One-to-One <ul><li>O atributo deve conter a Annotation @OneToOne </li></ul><ul><li>Se o relacionamento for bidirecional os dois atributos devem conter a Annotation </li></ul><ul><li>Em uma das propriedades deve ser adicionada a Annotation @JoinColumn </li></ul><ul><li>Na outra propriedade deve ser adicionado o atributo mappedBy à Annotation @OneToOne </li></ul>
  122. 123. Classe User @Entity @Table (name = &quot;USERS&quot; ) public class User { @Id @GeneratedValue (strategy=GenerationType. AUTO ) private Long id ; private String name ; @OneToOne @JoinColumn (name = &quot;SHIPPING_ADDRESS_ID&quot; ) private Address address ; }
  123. 124. Classe Address @Entity public class Address { @Id @GeneratedValue private Long id ; @Column (nullable = false ) private String street ; @OneToOne (mappedBy = &quot;address&quot; ) private User user ; }
  124. 125. Ralacionamento Many-to-Many
  125. 126. Many-to-Many <ul><li>O atributo deve conter a Annotation @ManyToMany </li></ul><ul><li>Se o relacionamento for bidirecional os dois atributos devem conter a Annotation </li></ul><ul><li>Em uma das propriedades deve ser adicionada a Annotation @JoinTable </li></ul><ul><li>Na outra propriedade deve ser adicionado o atributo mappedBy à Annotation @ManyToMany </li></ul>
  126. 127. @JoinTable <ul><li>Contém o nome da tabela de relacionamento </li></ul><ul><li>O atributo joinColumns mapeia a coluna associada à entidade mapeada </li></ul><ul><ul><li>O tipo do atributo é @JoinColumn </li></ul></ul><ul><ul><ul><li>Annotation dentro de annotation </li></ul></ul></ul><ul><li>O atributo inverseJoinColumns mapeia a coluna associada à outra entidade </li></ul><ul><ul><li>O tipo do atributo também é @JoinColumn </li></ul></ul>
  127. 128. Classe Category @Entity public class Category { @Id @GeneratedValue @Column (name = &quot;CATEGORY_ID&quot; ) private Long id ; private String name ; @ManyToMany @JoinTable (name = &quot;CATEGORY_ITEM&quot; , joinColumns = @JoinColumn (name = &quot;CATEGORY_ID&quot; ), inverseJoinColumns = @JoinColumn (name = &quot;ITEM_ID&quot; )) private Set<Item> items = new HashSet<Item>(); }
  128. 129. Classe Item @Entity public class Item { @Id @GeneratedValue @Column (name = &quot;ITEM_ID&quot; ) private Long id ; private String name ; @ManyToMany (mappedBy = &quot;items&quot; ) private Set<Category> categories = new HashSet<Category>(); }
  129. 130. Polimorfismo e LazyLoading <ul><li>Utilizando-se polimorfismo, as entidades são referenciadas através de suas super classes </li></ul><ul><li>Não se deve fazer o cast da referência para alguma das subclasses, mesmo que se saiba o tipo do objeto </li></ul><ul><li>Para associações carregadas por LazyLoading, é utilizado um objeto proxy </li></ul><ul><li>O objeto proxy não pode ser atribuído a uma subclasse da classe referenciada </li></ul>
  130. 131. Associações: Polimorfismo
  131. 132. Entidade User @Entity @Table (name = &quot;USERS&quot; ) public class User { @Id@GeneratedValue private Long id ; @OneToOne (fetch = FetchType. LAZY ) @JoinColumn (name = &quot;DEFAULT_BILLING_ID&quot; ) private BillingDetails defaultBilling ; }
  132. 133. Polimorfismo e LazyLoading User user = (User) session.get(User. class , userId); BillingDetails bd = user.getDefaultBilling(); CreditCard cc = (CreditCard) session.load(CreditCard. class , bd.getId()); System. out .println(cc.getNumber()); User user = (User) session.get(User. class , userId); BillingDetails billingDetails = user.getDefaultBilling(); //imprime false System. out .println(billingDetails instanceof CreditCard); //ClassCastException CreditCard creditCard = (CreditCard) billingDetails;
  133. 134. Ciclo de Vida dos Objetos <ul><li>Em seu ciclo de vida, uma entidade pode assumir diversos estados relativos a sua persistência </li></ul><ul><ul><li>Transiente </li></ul></ul><ul><ul><li>Persistente </li></ul></ul><ul><ul><li>Desconectada </li></ul></ul><ul><ul><li>Removida </li></ul></ul><ul><li>Entidades devem se comportar de maneira apropriada mesmo que ainda não estejam persistentes </li></ul>
  134. 135. Ciclo de Vida dos Objetos <ul><li>O ciclo de vida de uma entidade pode ser afetado através de chamadas às interfaces do Hibernate </li></ul><ul><ul><li>Operações de alterações e consultas na base de dados </li></ul></ul><ul><ul><li>Operações para delimitar a existência de uma transação e de um Sesssion </li></ul></ul><ul><li>Para o correta implementação, a aplicação deve se preocupar com o estado e o ciclo de vida do objeto </li></ul>
  135. 136. Ciclo de Vida dos Objetos: Conceitos <ul><li>Unidade de trabalho </li></ul><ul><ul><li>Conjunto de operações, geralmente atômicas </li></ul></ul><ul><li>Contexto de persistência </li></ul><ul><ul><li>Cache de todas alterações feitas em entidades em uma única unidade de trabalho </li></ul></ul>
  136. 137. Estado Transiente <ul><li>É o estado que um objeto assume quando é criado através do operador new </li></ul><ul><li>Não está associado a nenhum registro da base de dados </li></ul><ul><li>Os dados são perdidos quando o objeto não é mais referenciado e torna-se disponível para o Coletor de Lixo </li></ul><ul><li>Não são gerenciados pelo Hibernate </li></ul><ul><ul><li>Não possuem comportamento transacional </li></ul></ul>
  137. 138. Estado Persistente <ul><li>É uma entidade com um identificador na base de dados </li></ul><ul><ul><li>Possui uma chave primária </li></ul></ul><ul><li>São objetos gerenciados pelo Hibernate </li></ul><ul><li>Podem ser objetos criados pela aplicação </li></ul><ul><ul><li>Tornam-se persistentes através de chamadas ao Hibernate </li></ul></ul><ul><ul><li>Tornam-se persistentes se passarem a ser referenciados por outros objetos persistentes </li></ul></ul><ul><ul><ul><li>Depende do tipo de Cascade </li></ul></ul></ul>
  138. 139. Persistente <ul><li>Podem ser objetos retornados da base de dados </li></ul><ul><ul><li>Através de uma consulta </li></ul></ul><ul><ul><li>Através de uma associação entre um objeto persistente </li></ul></ul><ul><li>Podem ser objetos atualizados na base de dados </li></ul><ul><li>São sempre associados a um Contexto de Persistência </li></ul><ul><li>São guardados em um cache </li></ul><ul><li>Hibernate identifica qualquer alteração realizado no objeto </li></ul>
  139. 140. Removido <ul><li>Um objeto pode ser removido de duas maneiras </li></ul><ul><ul><li>Uma chamada explicita ao Hibernate </li></ul></ul><ul><ul><li>Através de uma operação com Cascade </li></ul></ul><ul><li>Um objeto neste estado é removido ao final da Unidade de Trabalho </li></ul><ul><ul><li>É gerenciado pelo Contexto de Persistência até que a Unidade de Trabalho termine </li></ul></ul>
  140. 141. Desconectado <ul><li>Objetos Persistentes passam para o estado Desconectado quando a Unidade de Trabalho é completada e o Contexto de Persistência é encerrado </li></ul><ul><li>O objeto não é mais sincronizado com a base de dados </li></ul><ul><li>Os dados do objeto podem se tornar desatualizados </li></ul><ul><li>Seus dados ainda podem ser alterados pela aplicação </li></ul><ul><li>Podem voltar ao estado Persistente </li></ul>
  141. 142. Contexto de Persistência <ul><li>Mantém um cache de instâncias gerenciadas </li></ul><ul><ul><li>Entidades no estado Persistente e Removido </li></ul></ul><ul><li>Conceito abstrato </li></ul><ul><ul><li>Não representado por um único objeto </li></ul></ul><ul><li>Cada objeto Session possui um Contexto de Persistência </li></ul><ul><li>Permite Dirty Checking automático </li></ul><ul><li>Delimita um escopo para a identidade das Entidades </li></ul><ul><ul><li>Não possui instâncias duplicadas </li></ul></ul>
  142. 143. Dirty Checking Automático <ul><li>É possível através do Contexto de Persistência </li></ul><ul><li>O dados de uma entidade são sincronizados com a base de dados </li></ul><ul><ul><li>No final da unidade de trabalho </li></ul></ul><ul><ul><li>Em outros momentos: antes de uma consulta </li></ul></ul><ul><li>Somente os objetos alterados são atualizados na base de dados </li></ul><ul><li>Atualização é retardada o máximo possível e é feita de forma automática </li></ul><ul><ul><li>Tempo de Lock do banco de dados é reduzido </li></ul></ul>
  143. 144. Cache de Primeiro Nível <ul><li>Armazenado no Contexto de Persistência </li></ul><ul><li>Mantém todas as instâncias de uma Unidade de Trabalho </li></ul><ul><li>Provê ganho de performance para a aplicação </li></ul><ul><li>Torna possível Repeatable Read </li></ul><ul><ul><li>Ao buscar mais de uma vez uma mesma entidade, os dados retornados são os mesmos </li></ul></ul><ul><li>O escopo é restrito à thread de execução </li></ul>
  144. 145. Cache de Primeiro Nível <ul><li>Um único objeto representa um determinado registro na base de dados </li></ul><ul><ul><li>Evita alterações conflitantes </li></ul></ul>
  145. 146. Contexto Persistência: Escopo <ul><li>Algumas funcionalidades da aplicação necessitam de diversas requisições para serem completadas </li></ul><ul><li>O escopo do Contexto de Persistência pode, ou não, ser o mesmo da funcionalidade </li></ul><ul><li>Duas estratégias são as mais utilizadas para delimitar o escopo do Contexto de Persistência </li></ul><ul><ul><li>Um objeto Session por requisição </li></ul></ul><ul><ul><li>Unidade de Trabalho de longa duração </li></ul></ul>
  146. 147. Uma Session por Requisição <ul><li>Quando o servidor recebe alguma requisição que requer acesso a base de dados uma nova Unidade de Trabalho é iniciada </li></ul><ul><li>A Unidade de Trabalho é encerrada quando a requisição é processada e a resposta está pronta para ser enviada ao usuário </li></ul><ul><li>As entidades são mantidas em estado Desconectado entre uma requisição e outra </li></ul>
  147. 148. Uma Session por Requisição <ul><li>Entidades mantidas entre duas requisições necessitam ser reconectadas para acessar serviços de persistência novamente </li></ul><ul><li>Qualquer alteração feita em entidades desconectadas deve ser sincronizada manualmente </li></ul><ul><ul><li>Operações de atualização e/ou merge </li></ul></ul>
  148. 149. Objetos Desconectados
  149. 150. Unidade de Trabalho de Longa Duração <ul><li>Objeto Session é mantido aberto durante várias requisições </li></ul><ul><ul><li>O Contexto de Persistência se propaga durante toda a conversação </li></ul></ul><ul><li>Conexões com a base de dados não são mantidas abertas </li></ul><ul><ul><li>A cada nova requisição o contexto é reconectado à base de dados </li></ul></ul><ul><li>As entidades são mantidas no estado Persistente </li></ul><ul><ul><li>Não requer merge ou atualização manual </li></ul></ul>
  150. 151. Unidade de Trabalho de Longa Duração <ul><li>No final da conversação, o Contexto é sincronizado com a base de dados e encerrado </li></ul><ul><li>A atomicidade das alterações é relativa à funcionalidade como um todo </li></ul>
  151. 152. Contexto expandido
  152. 153. Escopo limitado ao Contexto de Persistência Session session = HibernateUtil. getSessionFactory ().openSession(); Transaction transaction = session.beginTransaction(); Long id = (Long) session.save( new Message( &quot;Hibernate&quot; )); Message messageB = (Message) session.get(Message. class , id); Message messageC = (Message) session.get(Message. class , id); System. out .println(messageB.equals(messageC)); transaction.commit(); session.close(); Session session2 = HibernateUtil. getSessionFactory ().openSession(); Transaction transaction2 = session2.beginTransaction(); Message messageD = (Message) session2.get(Message. class , id); System. out .println(messageC.equals(messageD));
  153. 154. Identidade de objetos Desconectados <ul><li>Sempre que se for trabalhar com objetos desconectados, deve-se sobrescrever o método equals() </li></ul><ul><ul><li>Para objetos desconectados a garantia de uma única instância por registro é perdida </li></ul></ul><ul><ul><li>Implementação default não garante o comportamento desejado </li></ul></ul><ul><ul><li>Mesmo que dois objetos possuam todas as propriedades iguais, o método pode retornar false </li></ul></ul>
  154. 155. equals() <ul><li>Deve retornar verdadeiro se duas instâncias corresponderem ao mesmo registro </li></ul><ul><li>Quais propriedades devem ser comparadas? </li></ul><ul><li>Somente a chave primária </li></ul><ul><ul><li>Problema: entidades transientes não possuem valores para a chave primária </li></ul></ul><ul><li>Todas as propriedades </li></ul><ul><ul><li>Problema: entidades referentes ao mesmo registro não são consideradas iguais se alguma propriedade mudar </li></ul></ul><ul><li>Melhor abordagem: comparar a chave de negócio </li></ul>
  155. 156. Chave de negócio <ul><li>Uma propriedade, ou um conjunto delas, que é único para cada registro </li></ul><ul><ul><li>Chave candidata </li></ul></ul><ul><li>Não precisa ser imutável, basta que mude com pouca freqüência </li></ul>
  156. 157. Implementação public boolean equals(Object other) { if (!(other instanceof User)){ return false ; } User that = (User) other; return this . name .equals(that.getName()); } public int hashCode() { return this . name .hashCode(); }
  157. 158. Interagindo com o Hibernate <ul><li>O Hibernate provê diversos serviços </li></ul><ul><ul><li>Operações CRUD </li></ul></ul><ul><ul><ul><li>Criar </li></ul></ul></ul><ul><ul><ul><li>Recuperar </li></ul></ul></ul><ul><ul><ul><li>Atualizar </li></ul></ul></ul><ul><ul><ul><li>Deletar </li></ul></ul></ul><ul><ul><li>Realização de consultas </li></ul></ul><ul><ul><li>Controle de transação </li></ul></ul><ul><ul><li>Gerenciamento do Contexto de Persistência </li></ul></ul>
  158. 159. Interagindo com o Hibernate <ul><li>Os serviços são disponibilizados através de diversas Interfaces </li></ul><ul><ul><li>Session </li></ul></ul><ul><ul><li>Transaction </li></ul></ul><ul><ul><li>Query </li></ul></ul><ul><ul><li>Criteria </li></ul></ul>
  159. 160. Armazenando e Recuperando Objetos <ul><li>Para armazenar ou recuperar objetos, é necessário iniciar uma Unidade de Trabalho </li></ul>Session session = sessionFactory.openSession(); Transaction transaction = session.beginTransaction(); <ul><li>Um Contexto de Persistência é criado </li></ul><ul><ul><li>Irá gerenciar todas as entidades do Session </li></ul></ul><ul><li>Uma transação também deve ser iniciada </li></ul><ul><ul><li>mesmo para operações de leitura </li></ul></ul>
  160. 161. Armazenando um Objeto // Quando é instanciado, o item está no estado Transiente Item item = new Item(); item.setName( &quot;Item 1&quot; ); // um novo Session é aberto Session session = HibernateUtil. getSessionFactory ().openSession(); Transaction transaction = session.beginTransaction(); // O item passa para o estado Persistente e fica associado //ao Session e ao Contexto de Persistência session.save(item); //As mundanças são sincronizadas com a base de dados transaction.commit(); //O Session é fechado e o Contexto de Persistência encerrado. //O item passa para o estado Desconectado session.close();
  161. 162. Armazenando um Objeto
  162. 163. Recuperando uma Entidade Session session = HibernateUtil. getSessionFactory ().openSession(); Transaction tx = session.beginTransaction(); //Item é recuperado no estado Transiente Item item = (Item) session.load(Item. class , new Long(1234)); // Item item = (Item) session.get(Item.class, new Long(1234)); tx.commit(); //Item passa para o estado Desconectado session.close();
  163. 164. Recuperando uma Entidade
  164. 165. Recuperando uma Entidade <ul><li>Método get() </li></ul><ul><ul><li>Se o objeto procurado não for encontrado, retorna null </li></ul></ul><ul><li>Método load() </li></ul><ul><ul><li>Se o objeto procurado não for encontrado, lança a exceção ObjectNotFoundException </li></ul></ul><ul><ul><li>A existência do objeto só é verificada quando alguma propriedade é acessada </li></ul></ul>
  165. 166. Modificando um Objeto Persistente <ul><li>Todo objeto retornado pelos métodos load() ou get() ou através de uma consulta, assume o estado Persistente </li></ul><ul><li>Os objetos podem ser modificados e as alterações são sincronizadas com a base de dados </li></ul>
  166. 167. Modificando um Objeto Persistente Long id = armazenarItem (); Session session = HibernateUtil. getSessionFactory ().openSession(); Transaction tx = session.beginTransaction(); Item item = (Item) session.get(Item. class , id); item.setName( &quot;Playstation&quot; ); //Dados sincronizados com a base de dados. Dirty Cheking automático tx.commit(); session.close();
  167. 168. Modificando um Objeto Persistente
  168. 169. De Persistente para Transiente Long id = armazenarItem (); Session session = HibernateUtil. getSessionFactory ().openSession(); Transaction tx = session.beginTransaction(); //Item no estado Persistente Item item = (Item) session.load(Item. class , id); //Item no estado Removido session.delete(item); tx.commit(); //Item no estado Transiente session.close();
  169. 170. De Persistente para Transiente
  170. 171. Trabalhando com Objetos Desconectados <ul><li>Modificações realizadas em objetos Desconectados não são sincronizadas na base de dados </li></ul><ul><li>A atualização da base de dados pode ser feita de duas formas </li></ul><ul><ul><li>Reconectando o objeto – reattach </li></ul></ul><ul><ul><li>Realizando o merge do objeto </li></ul></ul>
  171. 172. Reconectando um Objeto <ul><li>Um objeto é reconectado através do método update() da interface Session </li></ul><ul><li>O objeto passa a ser gerenciado pelo Session e assume o estado Persistente </li></ul><ul><li>Deve-se ter certeza de que o Session ainda não possui um objeto gerenciado com o mesmo Id </li></ul><ul><ul><li>Somente uma instância do Contexto de Persistência pode estar associada a um determinado registro </li></ul></ul>
  172. 173. Reconectando um Objeto Item item = recuperarItem ( armazenarItem ()); item.setName( &quot;Novo nome&quot; ); Session session = HibernateUtil. getSessionFactory ().openSession(); Transaction transaction = session.beginTransaction(); session.update(item); item.setPrice(Integer. valueOf (114)); transaction.commit(); session.close();
  173. 174. Reconectando um Objeto
  174. 175. NonUniqueObjectException Long id = armazenarItem (); Item item = recuperarItem (id); item.setName( &quot;Novo nome&quot; ); Session session = HibernateUtil. getSessionFactory ().openSession(); Transaction transaction = session.beginTransaction(); Item item2 = (Item) session.get(Item. class , id); session.update(item); item.setPrice(Integer. valueOf (114)); transaction.commit(); session.close();
  175. 176. Realizando o merge() de um Objeto <ul><li>O merge de um objeto é feito através do método merge() da Interface Session </li></ul><ul><li>A a base de dados é atualizada com os valores contidos no objeto </li></ul><ul><li>Os dados do objeto também atualizam o objeto persistente que possuir o mesmo identificador </li></ul><ul><ul><li>Se não existir um objeto persistente associado ao Session, ele é carregado </li></ul></ul>
  176. 177. Método merge() <ul><li>O objeto desconectado não passa a ser associado ao Session </li></ul><ul><ul><li>Continua desconectado </li></ul></ul><ul><li>O objeto persistente é retornado </li></ul>
  177. 178. Método merge() Long id = armazenarItem (); Item item = recuperarItem (id); item.setName( &quot;Novo nome!!!&quot; ); Session session = HibernateUtil. getSessionFactory ().openSession(); Transaction transaction = session.beginTransaction(); Item item2 = (Item) session.get(Item. class , id); Item item3 = (Item) session.merge(item); transaction.commit(); session.close();
  178. 179. Método merge()
  179. 180. Persistência Transitiva <ul><li>Em aplicações não triviais, diversas Entidades podem estar associadas </li></ul><ul><li>A aplicação deve poder manipular as associações </li></ul><ul><li>Uma rede de objetos pode consistir de objetos em diferentes estados </li></ul><ul><ul><li>Persistentes </li></ul></ul><ul><ul><li>Desconectados </li></ul></ul><ul><ul><li>Transientes </li></ul></ul>
  180. 181. Persistência Transitiva <ul><li>A Persistência Transitiva permite persistir objetos Desconectados e Transientes automaticamente </li></ul><ul><li>Um objeto Transiente associado a um Persistente, torna-se persistente automaticamente </li></ul><ul><ul><li>Não há necessidade de chamar o método save() </li></ul></ul><ul><li>Diversas operações poder ser cascateadas </li></ul><ul><ul><li>Salvar </li></ul></ul><ul><ul><li>Deletar </li></ul></ul><ul><ul><li>Reconectar (update) </li></ul></ul><ul><ul><li>Merge </li></ul></ul>
  181. 182. Cascade <ul><li>Por default, em nenhuma operação é feito o cascade </li></ul><ul><li>O Hibernate permite a configuração do tipo de comportamento desejado para cada associação </li></ul><ul><li>Todos os tipos de associações podem ser configuradas </li></ul><ul><ul><li>one-to-one </li></ul></ul><ul><ul><li>one-many </li></ul></ul><ul><ul><li>many-to-many </li></ul></ul><ul><ul><li>many-to-one </li></ul></ul>
  182. 183. org.hibernate.annotations.CascadeType <ul><li>SAVE_UPDATE </li></ul><ul><ul><li>Objetos transientes são salvos </li></ul></ul><ul><ul><li>Objetos desconectados são sincronizados </li></ul></ul><ul><li>DELETE </li></ul><ul><ul><li>Objetos relacionados são deletados após a chamada do método delete() </li></ul></ul><ul><li>ALL </li></ul><ul><ul><li>Habilita todos os tipos de cascade </li></ul></ul>
  183. 184. org.hibernate.annotations.CascadeType <ul><li>DELETE_ORPHAN </li></ul><ul><ul><li>Deleta um objeto se ele for excluído da coleção </li></ul></ul><ul><ul><li>Aplicável somente para relacionamentos One-to-Many </li></ul></ul><ul><li>Cascade é aplicável somente para relacionamentos entre entidades </li></ul>
  184. 185. Exercício
  185. 186. Consultas <ul><li>Umas das partes mais interessantes do acesso a dados </li></ul><ul><li>Consultas complexas podem levar um bom tempo para serem escritas e podem ter considerável impacto na performance da aplicação </li></ul><ul><li>Consultas são escritas utilizando conceitos de orientação a objetos </li></ul><ul><ul><li>Objetos no lugar de tabelas </li></ul></ul><ul><ul><li>Propriedades no lugar de colunas </li></ul></ul><ul><li>Experiência em SQL não é desprezada </li></ul>
  186. 187. Consultas <ul><li>Podem ser feitas de três maneiras </li></ul><ul><ul><li>Hibernate Query Language (HQL) </li></ul></ul><ul><ul><li>Criteria API e Query by Example </li></ul></ul><ul><ul><li>Utilizando SQL </li></ul></ul>
  187. 188. Consultas: Exemplos // Através de HQL session.createQuery( &quot;from Category c where c.name like 'Laptop%'&quot; ); // Utilizando-se Criteria session.createCriteria(Category. class ).add( Restrictions. like ( &quot;name&quot; , &quot;Laptop%&quot; )); // Através de SQL session.createSQLQuery( &quot;select {c.*} from CATEGORY {c} where NAME like 'Laptop%'&quot; ) .addEntity( &quot;c&quot; , Category. class );
  188. 189. Consultas <ul><li>Envolve alguns passos </li></ul><ul><ul><li>Criar a consulta com as restrições necessárias </li></ul></ul><ul><ul><li>Adicionar parâmetros à consulta </li></ul></ul><ul><ul><li>Executar a consulta e recuperar o resultado </li></ul></ul><ul><ul><ul><li>A forma de execução da consulta e obtenção dos dados pode ser configurada </li></ul></ul></ul>
  189. 190. Criando a Consulta <ul><li>Objetos Query e Criteria são obtidos através do Session </li></ul><ul><ul><li>org.hibernate.Query </li></ul></ul><ul><ul><li>org.hibernate.Criteria </li></ul></ul>Query query = session.createQuery( &quot;from User&quot; ); Criteria criteria = session.createCriteria(User. class );
  190. 191. Adicionando Parâmetros à Consulta <ul><li>Parâmetros não devem ser adicionados na própria String da consulta </li></ul><ul><ul><li>&quot;from Item i where i.description like '&quot; + search + &quot;'&quot; </li></ul></ul><ul><li>Evita-se ataque do tipo SQL Injection </li></ul><ul><ul><li>foo' and callSomeStoredProcedure() and 'bar' = 'bar </li></ul></ul><ul><li>Parâmetros podem ser adicionados através de sua posição ou de seu nome </li></ul>
  191. 192. Adicionando Parâmetros pelo Nome <ul><li>Nome do parâmetro é precedido de “:” </li></ul><ul><li>O valores são adicionados através de métodos sets </li></ul>String queryString = &quot;from Item item where item.description like :search&quot; ; Query q = session.createQuery(queryString).setString( &quot;search&quot; , searchString); String queryString = &quot;from Item item&quot; + &quot; where item.description like :search&quot; + &quot; and item.date > :minDate&quot; ; Query q = session.createQuery(queryString).setString( &quot;search&quot; , searchString).setDate( &quot;minDate&quot; , mDate);
  192. 193. Adicionando Parâmetros pela Posição <ul><li>A consulta contém “?” para indicar a existência de alguma parâmetro </li></ul><ul><li>Os valores também são adicionado através de métodos sets </li></ul>String queryString = &quot;from Item item&quot; + &quot; where item.description like ?&quot; + &quot; and item.date > ?&quot; ; Query q = session.createQuery(queryString).setString(0, searchString).setDate(1, minDate);
  193. 194. Executando a Consulta <ul><li>Se mais de um objeto pode ser retornado, chama-se o método list() </li></ul><ul><ul><li>List list = query.list(); </li></ul></ul><ul><li>Se somente um objeto pode ser retornado, chama-se o método uniqueResult() </li></ul><ul><ul><li>User user = (User) query.uniqueResult(); </li></ul></ul><ul><ul><li>O método retorna null se nenhum objeto for encontrado </li></ul></ul><ul><ul><li>Se a consulta retornar mais de um objetos, a exceção NonUniqueResultException é lançada </li></ul></ul>
  194. 195. Executando a Consulta Query query = session.createQuery( &quot;from User&quot; ); List<User> list = query.list(); for (User user : list) { System. out .println(user.getName()); } Query query2 = session.createQuery( &quot;from User user where user.name =:name&quot; ).setString( &quot;name&quot; , &quot;SUNSP&quot; ); User user = (User) query2.uniqueResult(); System. out .println(user.getName());
  195. 196. Consultas Básicas <ul><li>A consulta mais simples tem somente a cláusula FROM </li></ul><ul><ul><li>“ from Item” </li></ul></ul><ul><li>Para se referenciar as propriedades de uma entidade, um ALIAS deve ser criado </li></ul><ul><ul><li>“ from Item as item” </li></ul></ul><ul><ul><li>“ from Item item” </li></ul></ul><ul><ul><ul><li>Palavra chave “as” é opcional </li></ul></ul></ul><ul><li>A consulta não é case-sensitive </li></ul><ul><ul><li>“ FROM Item AS item” também pode ser utilizada </li></ul></ul>
  196. 197. Consultas Polimórficas <ul><li>Consultas podem ser escritas utilizando polimorfismo </li></ul><ul><li>“ from BillingDetails” </li></ul><ul><ul><li>Retorna todas as entidades que herdam de BillingDetails </li></ul></ul><ul><ul><ul><li>CreditCard </li></ul></ul></ul><ul><ul><ul><li>BankAccount </li></ul></ul></ul><ul><li>A superclasse não precisa estar mapeada </li></ul><ul><ul><li>“ from java.lang.Object” </li></ul></ul><ul><ul><li>“ from java.io.Serializable” </li></ul></ul>
  197. 198. Restrições <ul><li>Geralmente não se quer trazer todo o conteúdo da tabela </li></ul><ul><li>Restrições devem ser adicionadas para restringir os objetos retornados </li></ul><ul><li>HQL também utiliza-se a cláusula WHERE </li></ul><ul><li>As restrições são feitas sobre propriedades da entidade </li></ul>
  198. 199. Restrições <ul><li>Literais e condições podem ser incluídos </li></ul><ul><ul><li>Utiliza-se aspas simples para literais do tipo String </li></ul></ul><ul><ul><li>“ from User u where u.email = 'foo@hibernate.org '” </li></ul></ul><ul><ul><li>“ from Item i where i.isActive = true” </li></ul></ul><ul><li>Comparações podem ser realizadas </li></ul><ul><ul><li>“ from Bid bid where bid.amount between 1 and 10” </li></ul></ul><ul><ul><li>“ from Bid bid where bid.amount > 100” </li></ul></ul><ul><ul><li>“ from User u where u.email in ('foo@bar', 'bar@foo')” </li></ul></ul>
  199. 200. <ul><li>Operador LIKE pode ser utilizado </li></ul><ul><ul><li>“ %” representa qualquer seqüência de caracteres </li></ul></ul><ul><ul><li>_ (Under_Score) representa qualquer caractere </li></ul></ul><ul><ul><li>“ from User u where u.firstname like 'G%'” </li></ul></ul><ul><ul><li>Negação pode ser utilizada </li></ul></ul><ul><ul><ul><li>“ from User u where u.firstname not like '%Foo B%'” </li></ul></ul></ul><ul><li>Operadores lógicos e parênteses </li></ul><ul><ul><li>“ from User user where user.firstname like 'G%' and user.lastname like 'K%'” </li></ul></ul>Comparações
  200. 201. Comparações <ul><li>Operadores lógicos e parênteses </li></ul><ul><ul><li>“ from User u where (u.firstname like 'G%' and u.lastname like 'K%' ) or u.email in ('foo@hibernate.org', 'bar@hibernate.org' )” </li></ul></ul><ul><li>Coleções </li></ul><ul><ul><li>&quot;from Item i where i.bids is not empty&quot; </li></ul></ul>
  201. 202. Comparações <ul><li>Funções podem ser chamadas a partir do HQL </li></ul><ul><ul><li>HQL permite a chamada de funções SQL na cláusula WHERE </li></ul></ul><ul><ul><li>Funções podem ser definidas pelo usuário </li></ul></ul><ul><ul><ul><li>Depende do suporte do banco de dados </li></ul></ul></ul><ul><ul><li>Funções UPPER() e LOWER() </li></ul></ul><ul><ul><ul><li>&quot;from User u where lower(u.email) = 'foo@hibernate.org '&quot; </li></ul></ul></ul><ul><ul><li>Função SIZE() </li></ul></ul><ul><ul><ul><li>from Item i where size(i.bids) > 3 </li></ul></ul></ul><ul><ul><li>E muitas outras... </li></ul></ul>
  202. 203. Comparações <ul><li>Outras funções </li></ul><ul><ul><li>CONCAT(s1, s2) </li></ul></ul><ul><ul><li>SUBSTRING(s, offset, length) </li></ul></ul><ul><ul><ul><li>Offset começa a partir de 1 </li></ul></ul></ul><ul><ul><li>TRIM( [[BOTH|LEADING|TRAILING] s) </li></ul></ul><ul><ul><ul><li>&quot;from Item i where TRIM(BOTH i.name) = 'Computador'&quot; </li></ul></ul></ul><ul><ul><li>LENGTH(s) </li></ul></ul><ul><ul><li>LOCATE(search, s, offset) </li></ul></ul><ul><ul><ul><li>Procura a localização de uma substring dentro de uma string </li></ul></ul></ul>
  203. 204. Comparações <ul><li>Outras funções </li></ul><ul><ul><li>CURRENT_DATE(), CURRENT_TIME(), CURRENT_TIMESTAMP() </li></ul></ul><ul><ul><ul><li>Valores retornados são referentes ao SGBD </li></ul></ul></ul><ul><ul><li>SECOND(d), MINUTE(d), HOUR(d), DAY(d), MONTH(d), YEAR(d) </li></ul></ul><ul><ul><ul><li>Extraem os valores de um argumento temporal </li></ul></ul></ul>
  204. 205. Ordenando o Resultado <ul><li>A Cláusula ORDER BY é utilizada para ordenar o resultado </li></ul><ul><ul><li>&quot;from User u order by u.name&quot; </li></ul></ul><ul><li>Ordem ascendente ou descendente </li></ul><ul><ul><li>Utiliza-se asc ou desc </li></ul></ul><ul><ul><li>from User u order by u.username desc </li></ul></ul><ul><li>Ordenando por mais de uma propriedade </li></ul><ul><ul><li>“ from User u order by u.lastname asc, u.firstname asc” </li></ul></ul>
  205. 206. Junções <ul><li>A habilidade de realizar junções é uma das principais forças do modelo relacional </li></ul><ul><li>Permite selecionar diferentes objetos associados e coleções em uma única consulta </li></ul>
  206. 207. Inner Join <ul><li>Contém somente os registros que estão relacionados com o outro lado da junção </li></ul><ul><ul><li>Contém somente os Itens que possuem Bids </li></ul></ul>
  207. 208. (left) Outer Join <ul><li>Retorna todos os Itens </li></ul><ul><ul><li>Dados de Bid são preenchidos com NULL se não houver uma correspondência </li></ul></ul>
  208. 209. Junção com HQL <ul><li>Coluna de junção não precisar ser informada na consulta </li></ul><ul><ul><li>Informação é extraída do mapeamento </li></ul></ul><ul><li>É necessário ser informado somente o nome da associação </li></ul><ul><ul><li>Nome do atributo que referencia a classe ou coleção de classes </li></ul></ul><ul><li>Joins podem ser executados de duas maneiras </li></ul><ul><ul><li>Join implícitos na Associação </li></ul></ul><ul><ul><li>Join especificado na cláusula FROM </li></ul></ul>
  209. 210. Join Implícito na Associação <ul><li>O Join é realizado através da associação entre duas entidades </li></ul><ul><li>Exemplo: </li></ul><ul><ul><li>“ from Bid bid where bid.item.description like '%Foo%'” </li></ul></ul><ul><ul><li>Bid é associado a Item através do atributo “item” </li></ul></ul><ul><ul><li>Hibernate sabe que a associação está mapeada a partir da chave estrangeira ITEM_ID da tabela BID </li></ul></ul><ul><li>Joins implícitos são sempre realizados através de associações many-to-one ou one-to-one </li></ul>
  210. 211. Join Implícito na Associação <ul><li>Múltiplos joins são possíveis </li></ul><ul><ul><li>from Bid bid where bid.item.category.name like 'Laptop%' </li></ul></ul>
  211. 212. Join especificado na Cláusula FROM <ul><li>Joins podem ser especificados explicitamente na cláusula FROM </li></ul><ul><li>Exemplo </li></ul><ul><ul><li>&quot;select i from Item i join i.bids b where b.amount > 10&quot; </li></ul></ul><ul><li>Aliases devem ser especificados na cláusula FROM e utilizados na cláusula WHERE </li></ul><ul><li>Cláusula SELECT é utilizada para que somente Itens sejam retornados </li></ul>
  212. 213. Join especificado na Cláusula FROM <ul><li>Na consulta, um Item pode ser retornado mais de uma vez </li></ul><ul><ul><li>Uma para cada Bid associado </li></ul></ul><ul><ul><li>Somente uma instância é utilizada </li></ul></ul><ul><li>A consulta possui o mesmo formato para associações many-to-one e one-to-one </li></ul>
  213. 214. Outer Joins <ul><li>Para a utilização de Outer Joins utiliza-se a cláusula LEFT JOIN </li></ul><ul><ul><li>LEFT OUTER JOIN e RIGHT OUTER JOIN também podem ser utilizados </li></ul></ul><ul><li>A cláusula WITH é utilizada para adicionar restrições </li></ul><ul><li>&quot;select i from Item i left join i.bids b with b.amount >= 9&quot; </li></ul><ul><ul><li>Itens que não possuem Bids também são retornados </li></ul></ul>
  214. 215. Comparando Identificadores <ul><li>Na Orientação a Objetos não são os identificadores, mas as referências ao objetos que são comparadas </li></ul><ul><li>Comparações podem ser feitas através dos atributos das entidades </li></ul><ul><li>&quot;select i from Item i join i.bids b where i.seller = b.bidder&quot; </li></ul><ul><ul><li>i.seller e b.bidder representam referências para a entidade User </li></ul></ul><ul><ul><li>Retorna os Itens em que o próprio vendedor deu um lance </li></ul></ul>
  215. 216. Comparando Identificadores <ul><li>Entidades também podem ser adicionadas como parâmetros de uma consulta </li></ul>Query query = session.createQuery( &quot;from Item i where i.seller = :seller&quot; ); query.setEntity( &quot;seller&quot; , user);
  216. 217. FIM... <ul><li>Referências </li></ul><ul><ul><li>Livro Java Persistence with Hibernate </li></ul></ul><ul><ul><ul><li>Edição revisada do livro Hibernate in Action </li></ul></ul></ul><ul><ul><ul><li>Autores </li></ul></ul></ul><ul><ul><ul><ul><li>Christian Bauer </li></ul></ul></ul></ul><ul><ul><ul><ul><li>Gavin King </li></ul></ul></ul></ul><ul><ul><li>http://www.hibernate.org/ </li></ul></ul><ul><ul><ul><li>Documentação e Javadoc </li></ul></ul></ul><ul><ul><ul><li>Fórum de discuções e dúvidas </li></ul></ul></ul><ul><ul><li>JSR 220: Enterprise JavaBeans Version 3.0 </li></ul></ul><ul><ul><ul><li>Para as Annotations do pacote javax.persistence </li></ul></ul></ul>

×