Hibernate Introdução ao hibernate Ferramentas ORM (Object Relational Mapping) Características do hibernate Arquitetura Conceitos Básicos Estados de uma instância Conceitos Básicos SessionFactory e Sessions Transações Mapeamento Operações com objetos (CRUD) Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Ferramentas ORM Motivações Código de acesso a banco de dados sempre foi “comfort zone” API JDBC é relativamente simples Desenvolvedores tem controle total Trabalho manual e repetitivo Sempre os mesmos passos Obter uma conexão com o banco de dados Utilizar um objeto Statement para executar uma cláusula SQL ou chamar uma Stored Procedure Se for uma query Realiza uma iteração no ResultSet Para cada linha, cria uma instância de um DTO (ou VO) Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Porque utilizar ferramentas ORM? Diminuir erros no código de acesso a dados Evitar connection leaking, por exemplo Utilização de código otimizado Ferramentas ORM vão utilizar as melhores práticas JDBC Portabilidade Código escrito com ferramentas ORM podem ser executados em vários bancos de dados Exige apenas alteração em arquivos de configuração Reduzir tempo de desenvolvimento Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Implementação de ferramentas ORM EJB Entity Beans (padrão J2EE) JDO (padronizado, JSR 243) TopLink (comprado pela Oracle) Castor iBATIS Apache Jakarta ORB Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) EJB Entity Beans 2.X Performance inaceitável Depêndencia total ao container EJB Objetos persistentes dependentes da API EJB Não é possível utilizar Entity Beans em aplicações que não rodam em um container EJB. Objetos devem implementar interfaces da API EJB Faltam funcionalidades Não suporta herança Linguagem de query limitada (EJB QL) As queries são sempre definidas em deployment descriptors Não é possível definir queries em runtime Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Características do Hibernate Ferramenta ORM open source (licença LGPL). Porém proprietária, associada ao JBoss Group Não é um padrão J2EE Baseada em POJOs (plain old java objects) Não depende de container J2EE Suporta as características OO : herança, polimorfismo, composição e etc. Query language poderosa (HQL) Melhor performance Melhor estratégia de locking que EJB Cache em 2 camadas Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Arquitetura Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Conceitos Básicos – Session Factory Repositório de mapeamentos para um determinado banco de dados Objeto de vida longa, compartilhado para toda a aplicação Existe um SessionFactory para cada banco de dados Thread-safe Pode ser comparado com um DataSource JDBC Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Conceitos Básicos - Session Objeto utilizado na interação com o banco de dados Realizar inserções, atualizações, deleções e consultas De vida curta, é construído pela SessionFactory Uma instância de Session para cada transação Single-threaded Mantém um cache de objetos obrigatório Um objeto Session gerencia uma Connection JDBC Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Conceitos Básicos - Transaction Objeto de vida curta que representa uma transação com o banco de dados São criados por uma Session Abstrai a implementação de fato da transação Transação JDBC JTA (Java Transaction API) Transação CORBA Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Conceitos Básicos - Transaction IMPORTANTE : O hibernate exige que toda interação com o banco de dados seja realiza com um contexto de transação! Até mesmo operações de leitura Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Estados de uma instância Os objetos persistidos pelo Hibernate podem assumir 3 estados. Transient A instância nunca foi associada a uma Session. Persistent A instância está associada a uma Session. Possui identidade (chave primária) Por exemplo, um objeto recém-criado. Por exemplo, objeto acabou de ser persistido ou carregado do banco de dados Detached A instância esteve associada a uma Session. Possui identidade. Por exemplo, a Session que carregou o objeto foi fechado. Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Mapeamento As classes a serem persistidas devem ser mapeadas em arquivos XML É utilizado o conceito de “configurar por exceção” O hibernate vai inferir muitas informações da classe, se a informação não estiver presente no arquivo de mapeamento Nome da tabela = Nome da classe Nome do campo = Nome da propriedade Tipo do campo = Tipo da propriedade Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Mapeamento public class Pessoa { private String nome; private int codigo; public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public String getCodigo() { return codigo; } public void setCodigo(int idade) { this.codigo = codigo; } } <hibernate-mapping> <class name=“jfa.Pessoa”> <id name=“codigo” /> <property name=“nome” /> </class> </hibernate-mapping> Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Fluxo de uma aplicação Hibernate Passo 1: Construir um SessionFactory Processar os arquivos de mapeamento Passo efetuado uma única vez Para cada interação com o banco de dados Passo 2 : Passo 3 : Passo 4 : Passo 5 : de dados Passo 6 : Passo 7 : Obter a instância do SessionFactory Abrir uma Session Abrir uma Transaction Persistir objetos e/ou recuperar objetos no banco Fechar a Transaction (com commit ou rollback) Fechar a Session Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Construindo a SessionFactory É construída através do objeto Configuration Guarda as propriedades gerais do hibernate. As propriedades podem ser definidas: Informações do banco de dados (URL JDBC, usuário, senha) Parâmetros de runtime Através de código Através de System properties java –Dproperty=valor Através de um arquivo XML Por padrão o objeto Configuration procura por um arquivo chamado hibernate.cfg.xml na raiz do class path. Arquivo com outro nome ou localização pode ser definido no construtor do objeto Configuration Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) O objeto Configuration // Utilizando um arquivo de configuração Configuration config = new Configuration(“app-hibernatecfg.xml”); config = config.configure(); //Definindo propriedades através de códigos Configuration config = new Configuration(); config.setProperty(“connection.url”, “jdbc:postgresql://localhost/treinamento”); config.setProperty(“connection.username”, “treinamento”); config = config.configure(); Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Propriedades Importantes connection.driver_class : Nome da classe do driver JDBC. connection.url : URL JDBC do banco de dados connection.username : Usuário do banco de dados connection.password : Senha do banco de dados dialect : Classe que representa qual o dialeto que será utilizado para gerar as cláusulas SQL. Existe um dialeto para cada servidor de banco de dados. org.hibernate.dialect.PostgreSQLDialect org.hibernate.dialect.OracleDialect org.hibernate.dialect.SQLServerDialect org.hibernate.dialect.DB2Dialect E 18 outros dialetos... (versão 3.1) Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Construindo a SessionFactory Uma única instância compartilhada para toda aplicação. Variável estática ou Associada à árvore JNDI em aplicações rodando em um container J2EE Deve ser construída uma única vez Vai existir uma SessionFactory para cada banco de dados utilizado pela aplicação. Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Construindo a SessionFactory import org.hibernate.*; import org.hibernate.cfg.*; public class HibernateUtil { private static final SessionFactory factory; static { } } try { factory = new Configuration().configure().buildSessionFactory(); } catch (Exception e) { // Registra o erro no log throw new ExceptionInInitializerError(e); } Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Abrindo uma Session A SessionFactory cria objetos Session método openSession(), que normalmente NÃO é utilizado Session session = factory.openSession(); session.beginTransaction(); try { inserirPessoa(session, “Nome Pessoa”); inserirGrupo(session, “Nome do grupo”); session.getTransaction().commit(); catch (Exception e) { session.getTransaction().rollback(); } finally { session.close(); } Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Abrindo uma Session Passar o objeto Session para todos os métodos como parâmetro NÃO É ACEITÁVEL! Prejudica o design da aplicação! Como toda operação exige transação e todo o código que utiliza uma mesma transação DEVE estar na mesma thread, uma estratégia melhor é colocar o objeto Session como objeto ThreadLocal Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Entendendo variáveis ThreadLocal Variáveis que tem um escopo de uma thread. Se metodoA() define um valor em uma variável ThreadLocal e depois invoca metodoB() (logo, estão na mesma thread), o código em metodoB() pode recuperar o valor. Quando a thread encerrar, as variáres ThreadLocal associadas estarão disponíveis para o garbage collector Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Abrindo uma Session Hibernate oferece a possibilidade de guardar a Session corrente em ThreadLocal. No Configuration define a propriedade current_session_context_class <property name="current_session_context_class">thread</property> Ao invés de utilizar o método openSession(), será utilizado o método getCurrentSession() do objeto SessionFactory. Ao invocar getCurrentSession(), uma Session será criada se não existir e será colocada em uma variável ThreadLocal. Se a sessão já existir para a thread atual, será retornada. Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Abrindo uma Session Hibernate oferece a possibilidade de guardar a Session corrente em ThreadLocal. No Configuration define a propriedade current_session_context_class <property name="current_session_context_class">thread</property> Ao invés de utilizar o método openSession(), será utilizado o método getCurrentSession() do objeto SessionFactory. Ao invocar getCurrentSession(), uma Session será criada se não existir e será colocada em uma variável ThreadLocal. Se a sessão já existir para a thread atual, será retornada. Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Utilizando o objeto Session public void inserePessoa(String nome) { SessionFactory factory = HibernateUtil.getSessionFactory(); Session session = factory.getCurrentSession(); try { session.beginTransaction(); Pessoa pessoa = new Pessoa(nome); session.save(pessoa); session.getTransaction().commit(); } catch (Exception e) { session.getTransaction().rollback(); throw e; } } Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Abrindo uma Session Quando utilizado o método getCurrentSession(), não é necessário fechar a Session explicitamente. A Session será fechada quando a transação encerrar. Session session = factory.getCurrentSession(); session.beginTransaction(); try { inserirPessoa(“Nome Pessoa”); inserirGrupo(“Nome do grupo”); session.getTransaction().commit(); catch (Exception e) { session.getTransaction().rollback(); throw e; } Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) A classe utilitária public class HibernateUtil { private static final SessionFactory factory; static { try { factory = new Configuration().configure().buildSessionFactory(); } catch (Exception e) { // Registra o erro no log throw new ExceptionInInitializerError(e); } } public static Session getCurrentSession() { return factory.getCurrentSession(); } } Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Utilizando o objeto Session para persistir objetos A interação com o banco de dados é feita através do objeto Session save() : Persiste uma instância no estado transient. Insere no banco de dados e torna a instância persistent. update() : Atualiza no banco de dados os dados de uma instância transient. Não é necessário invocar update() para instâncias persistent! get() : Recupera um instância persistent utilizando a chave primária delete() : Exclui uma instância persistent ou transient no banco de dados Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Conceitos Básicos Laboratório 1 Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Flush Flush é o momento que o hibernate sincroniza o estado dos objetos com o banco de dados O flush NÃO ocorre necessariamente a cada invocação de um método no objeto Session! Executa cláusulas no banco de dados O hibernate tende a adiar a sincronização com o banco para o fim da transação. Pode ser forçado um flush através do método flush() do objeto Session. Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Flush Por padrão o flush acontece nos seguintes momentos: Antes da execução de algumas queries. No momento que o método commit() é invocado. No momento que o método flush() é invocado. Os comandos SQL serão executados na seguinte ordem: Inserções de entidades Atualizações de entidades Deleção de coleções Deleção, inserção e atualização de elementos de coleções Inserção de coleções Deleção de entidades Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Flush Por padrão, não existe garantia de QUANDO as atualizações no banco de dados serão efetuadas! Exceto quando o método flush() é invocado Hibernate garante que nenhuma consulta retornará dados desatualizados ou incorretos Para garantir esta premissa, o hibernate realiza um flush() antes de algumas consultas O momento em que ocorre o flush pode ser configurado através do método setFlushMode() do objeto Session. Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Cache de primeiro nivel O objeto Session mantém um cache de primeiro nível obrigatório No trecho de código abaixo, apenas um comando SELECT será executado: Session session = HibernateUtil.getCurrentSession(); try { session.beginTransaction(); Grupo grupo = (Grupo) session.get(Grupo.class ,new Integer(1)); Grupo oMesmoGrupo = (Grupo) session.get(Grupo.class ,new Integer(1)); session.getTransaction().commit(); } catch (Exception e) { session.getTransaction().rollback(); throw new PersistenciaException(e); } Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Cache de primeiro nivel Dois objetos com a mesma identidade (chave primária) não podem estar associadas a mesma Session. Se ocorrer, uma NonUniqueObjectException será lançada Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Cache de primeiro nivel O que vai ocorrer no trecho abaixo? Session session = HibernateUtil.getCurrentSession(); try { session.beginTransaction(); Grupo grupo = (Grupo) session.get(Grupo.class ,new Integer(1)); Grupo oMesmoGrupo = new Grupo(); oMesmoGrupo.setCodigo(1); session.save(oMesmoGrupo); session.getTransaction().commit(); } catch (Exception e) { session.getTransaction().rollback(); throw new PersistenciaException(e); } Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Cache de primeiro nivel Como evitar a NonUniqueObjectException? Limpando todo o cache da Session Retirando objetos do cache Método evict() Obtendo sempre o objeto do cache Método clear() Sempre utilizar um get() Comando SELECT será realizado no máximo UMA vez Realizando o merge Método merge() atualiza o estado de uma instância persistent com os dados de uma instância transient Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Mapeamento O hibernate descreve em arquivos XML o mapeamento entre classes e tabelas Associações Associações entre entidades fortes Podem ser unidirecionais ou bidirecionais Coleções Uma entidade pode possuir coleções de objetos que não são entidades para o hibernate Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Modelo ER Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Modelo de classes Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Mapeamento de uma classe Propriedades persistentes são mapeadas com tags <property /> Considera-se “propriedades”, a definição java bean: Um atributo de classe privado com métodos get e set associados É possível configurar o hibernate para persistir atributos publicos Uma propriedade deve ser definida como chave primária A tag <id /> identifica a propriedade chave simples. A tag <composite-id /> identifica a propriedade chave composta Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Mapeando a chave primária Para chaves artificiais (geradas pela aplicação ou banco de dados), é possível definir uma classe generator O hibernate já traz implementações para várias estratégias de chaves artificiais Campos Identity (SQL Server, DB2, MySQL ...) Sequences (Oracle, PostgreSQL, DB2 ...) HILO : Tabela de sequencia Select : Chaves geradas por triggers E outras estratégias É possível implementar uma classe generator Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Mapeando a chave primária <id name=“codigo” column=“codigo_grupo”> <generator class=“sequence”> <param name=“sequence”>sq_grupo</param <generator> </id> Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Mapeando associações Associações comuns Many to one unidirecional One to many unidirecional One to many / many to one bidirecional (parent/child) One to one bidirecional na chave primária One to one bidirecional na chave estrangeira Many to many unidirecional Many to many bidirecional Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Mapeamento many to one unidirecional Um grupo possui muitos usuários A terminação “muitos” está na entidade usuário. Na classe Usuario : Mapeamento <many-to-one> <many-to-one name=“grupo” column=“codigo_grupo”/> O atributo name representa a propriedade que é uma referência para classe Grupo O atributo column representa a coluna na tabela que é chave estrangeira para a tabela Grupo. Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Mapeamento many to one unidirecional Mapeamento da classe Usuario <hibernate-mapping> <class name="jfa.model.Usuario" table="usuario"> <id name="username" /> <property name="nome" /> <property name="email" /> <many-to-one name="grupo" column="codigo_grupo" /> </class> </hibernate-mapping> Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Mapeamento many to one unidirecional Classe Usuario public class Usuario { private String username; private String nome; private String email; private Grupo grupo; public Grupo getGrupo() { return grupo; } public void setGrupo(Grupo grupo) { this.grupo = grupo; } // Demais getters and setters omitidos } Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Mapeamento one to one bidirecional Um usuário possui um login e um login está associado a apenas um usuário Nas classes Usuario e Login : Mapeamento <one-to-one> Geralmente ambas as entidades compartilham a mesma chave primária <one-to-one name=“grupo” column=“codigo_grupo” /> Na classe que possui a chave estrangeira o atributo constrained deve ser adicionado a tag <one-to-one /> A classe que herdar a chave primária, um id generator do tipo foreign deve ser usado. Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Mapeamento one to one bidirecional Mapeamento da classe Usuario <hibernate-mapping> <class name=“fja.model.Usuario" table="usuario"> <id name="username" /> <property name="nome" /> <property name="email" /> <many-to-one name="grupo" column="codigo_grupo" /> <one-to-one name="login" cascade="all" /> </class> </hibernate-mapping> Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Mapeamento one to one bidirecional Mapeamento da classe Login <hibernate-mapping> <class name=“fja.model.Login" table="login"> <id name="username"> <generator class="foreign"> <param name="property">usuario</param> </generator> </id> <property name="senha" /> <property name="ativo" /> <one-to-one name="usuario" constrained="true" /> </class> </hibernate-mapping> Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Mapeamento one to one bidirecional O id generator foreign recupera o valor da chave primária de um objeto associado Logo, a classe Login DEVE ter uma referência para a classe Usuario O parâmetro constrained informa ao hibernate que existe uma chave estrangeira definida. Esta informação garante que a ordem das operações de delete e insert não causarão violação da chave estrangeira. Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Mapeamento many to many bidirecional Um usuário está associado a muitos papéis e um papel tem muitos usuários associados Nas classes Usuario e Papel : <many-to-many> O parâmetro table especifica o nome da tabela associativa Em ambas as classes terão propriedades do tipo coleção papeis (Set) na classe Usuario Usuarios (Set) na classe Papel Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Mapeamento many to many bidirecional Mapeamento da classe Usuario <set name="papeis" table="desempenha"> <key column="username" /> <many-to-many class="Papel" column="codigo_papel" /> </set> Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Mapeamento many to many bidirecional Mapeamento da classe Papel <set name="usuarios" inverse="true" table="desempenha"> <key column="codigo_papel" /> <many-to-many class="Usuario" column="username" /> </set> Em uma associação many-to-many um dos lados DEVE ter o parâmetro inverse Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Mapeamento bidirecionais Todos as associacões one to many, many to one e many to many bidirecionais precisam ter um dos “lados” configurados como inverse Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Mapeando associações Laboratório 2 Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Persistência transitiva Por padrão, o hibernate não propaga o comando de persistência para os objetos associados Associações podem ser configuradas com um cascade style Para cada operação da Session existe uma opção de cascade style correspondente Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Persistência transitiva save() – create merge() – merge saveOrUpdate() – save-update delete() – delete lock() – lock refresh() – refresh evict() – evict replicate() – replicate Todas as operacões - all Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Persistência transitiva O cascade delete-orphans se aplica a associações many to one. Exclui as entidades que não tem mais referência para a entidade pai Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Mapeando herança O hibernate oferece 3 estratégias básicas para mapear herança Tabela por hierarquia de classes Tabela por subclasse Uma tabela para todas as classes concretas de uma hierarquia Uma tabela para a superclasse e uma tabela para cada subclasse Tabela por classe concreta Uma tabela para cada subclasse. Não existe tabela para a superclasse. Os atributos em comun são replicados em cada tabela Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Tabela por hierarquia de classes Todas as classes da hierarquia são persistidas na mesma tabela O tipo de cada instância é identificada através de uma coluna na tabela chamada discriminator As subclasses são mapeadas através da tag <subclass> e as subclasses não podem mapear propriedades not null. Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Tabela por hierarquia de classes Classes Usuario e Funcionario public class Usuario { private String username; // outras propriedades e getters and setters omitidos } public class Funcionario extends Usuario { private String matricula; private String departamento // getters and setters omitidos } Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Tabela por hierarquia de classes Mapeamento de Usuario e Funcionario <hibernate-mapping> <class name=“fja.model.Usuario" table="usuario" discriminator-value="U"> <id name="username" /> <discriminator column="tipo" type="string" /> <!-- Outras propriedades e associações omitidas --> <subclass name=“fja.model.Funcionario" discriminator-value="F" > <property name="matricula" /> <property name="departamento" /> </subclass> </class> </hibernate-mapping> Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Tabela por subclasse Cada classe na hierarquia é persistida em uma tabela diferente Uma tabela para a super classe com todos as colunas em comum Uma tabela para CADA subclasse. As subclasses são mapeadas através da tag <joined-subclass> Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Tabela por subclasse Mapeamento de Usuario e Funcionario utilizando a estratégia tabela por subclasse <hibernate-mapping> <class name="Usuario" table="usuario" > <id name="username" /> <!-- Outras propriedades e associações omitidas --> <joined-subclass name="Funcionario“ table=“funcionario” > <key column=“username” /> <property name="matricula" /> <property name="departamento" /> </joined-subclass> </class> </hibernate-mapping> Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Tabela por subclasse Mapeamento de Usuario e Funcionario utilizando a estratégia tabela por subclasse <hibernate-mapping> <class name="Usuario" table="usuario" > <id name="username" /> <!-- Outras propriedades e associações omitidas --> <joined-subclass name="Funcionario“ table=“funcionario” > <key column=“username” /> <property name="matricula" /> <property name="departamento" /> </joined-subclass> </class> </hibernate-mapping> Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) Mapeando Herança Laboratório 3 Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) HQL Hibernate query language Linguagem de query orientada a objetos, capaz de reconhecer conceitos como herança, associações e polimorfismo Similar a OQL (object query language) e EJB-QL Cláusulas HQL são executado através do objeto Query e retornam coleções de objetos persistentes ou valores escalares (int, float, boolean, String e etc.) Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) HQL – A cláusula FROM A principal cláusula do HQL, informa sobre que coleção de objetos será feita a consulta from Grupo Retorna todas as instâncias de Grupo no banco de dados Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) HQL – A cláusula FROM Pode fazer join com associações de forma implícita from Usuario u where u.grupo.codigo = 3 Retorna todas as instâncias de Usuario onde o grupo associado tem o codigo 3. Neste caso o hibernate é inteligente o bastante para não fazer o join, pois a tabela “usuario” tem a chave estrangeira pesquisada! Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) HQL – A cláusula FROM Pode fazer join com associações de forma implícita from Usuario u where u.grupo.nome = ‘Grupo 3’ Neste caso o hibernate necessita gerar um join com a tabela “Grupo” Para o HQL, é abstraída a necessidade ou não de fazer joins SQL, mas o desenvolvedor deve estar atento! Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) HQL – A cláusula FROM A cláusula JOIN explícita é utilizada com associações select u from Usuario u inner join u.grupo grupo_usuario Retorna todos os usuários que tem grupos associados. Usuários sem grupo não serão retornados select u from Usuario u left join u.grupo grupo_usuario Retorna todos os usuários, com grupos ou não Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) HQL – A cláusula SELECT A cláusula SELECT diz que objetos ou valores serão retornados select u.grupo from Usuario u where u.username = ‘user01’ Retorna uma instância de Grupo associado ao usuário com username ‘user01’ Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) HQL – A cláusula SELECT Além de instâncias de objetos persistentes, outros objetos podem ser retornados select u.grupo.nome from Usuario u where u.username = ‘user01’ Retorna o nome do grupo associado (String) ao usuário com username ‘user01’ Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) HQL – A cláusula SELECT Vários objetos podem ser retornados, em um array de Object... select u.grupo.nome, u.grupo.codigo from Usuario u where u.username = ‘user01’ ... Ou como um List ... select new list(u.grupo.nome, u.grupo.codigo) from Usuario u where u.username = ‘user01’ Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected]) HQL – A cláusula SELECT ... Ou como uma instância de classe qualquer, que tenha um construtor correspondente ... select new GrupoResumo(u.grupo.nome, u.grupo.codigo) from Usuario u where u.username = ‘user01’ ... Ou um Map utilizando os alias como chaves select new map(u.grupo.nome nome, u.grupo.codigo cod) from Usuario u where u.username = ‘user01’ Arleys Pereira Nunes de Castro - Mestrando : Modelagem computacional (SENAI-MCTI) Especialista : Sistema distribuídos (UFBA)([email protected])