Hibernate

Propaganda
Hibernate Introdução
Caio Nakashima
[email protected]
[email protected]
1
Primeira Aplicação
• Será criada uma aplicação simples baseado no
console do Hibernate.
• O banco de dados neste exemplo poderá
armazenar eventos que se deseja atender e
informações sobre o anfitrião destes eventos.
• O primeiro passo é configurar a pasta de
desenvolvimento e colocar todas as bibliotecas Java
necessárias nele.
• Abaixar a distribuição do Hibernate do site
http://www.hibernate.org ou da pasta do servidor.
2
Bibliotecas necessárias
• +lib
–
–
–
–
–
–
–
–
–
–
–
antlr.jar
cglib-full.jar
asm.jar
asm-attrs.jars
commons-collections.jar
commons-logging.jar
ehcache.jar
hibernate3.jar
jta.jar
dom4j.jar
log4j.jar
3
Bibliotecas necessárias
• Extrair o pacote e colocar todas as bibliotecas
necessárias que se encontram em /lib para a pasta
/lib da pasta de desenvolvimento.
• A lista da transparência anterior é o conjunto
mínimo das bibliotecas necessárias.
• É interessante consultar o arquivo README.txt da
pasta /lib da distribuição do Hibernate para maiores
informações sobre as bibliotecas adicionais de
terceiros.
4
Classe
• Será criada uma classe que representa um evento
que se deseja armazenar no banco de dados.
• A classe deste exemplo é uma classe JavaBean
com algumas propriedades.
• Observe que a classe utiliza o padrão de nomes do
JavaBean para as propriedades dos métodos get e
set, assim como a visibilidade dos campos privados.
• Esta é uma recomendação de projeto, mas não é
obrigatório.
• Hibernate pode acessar campos diretamente, o
benefício de métodos de acesso é a robustez para
refactoring.
5
import java.util.Date;
public class Event {
private Long id;
private String title;
private Date date;
Event() {}
public Long getId() {
return id;
}
private void setId(Long id) {
this.id = id;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
Event.java
6
Identificadores
• A propriedade ID carrega o valor do identificador único para
um evento particular.
• Todas as classes de persistência de entidades necessitam
de uma propriedade identificadora para utilizar o conjunto
completo das características do Hibernate.
• Em geral não se manipula o identificador de um objeto, então
o método set deve ser privado.
– Somente o Hibernate pode atribuir valores aos identificadores quando
um objeto é salvo.
• Observa-se que o Hibernate pode acessar métodos de
acesso public, private e protected assim como os campos
diretamente.
7
import java.util.Date;
public class Event {
private Long id;
private String title;
private Date date;
Event() {}
public Long getId() {
return id;
}
private void setId(Long id) {
this.id = id;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
Event.java
Identificadores,
definição das
interfaces
8
Construtor
• É necessário um construtor sem argumentos para
todas as classes de persistência.
– Hibernate tem que criar uma classe utilizando Java
Reflection.
• O construtor pode ser privado, porém a visibilidade
do pacote (package) é requerida pelo runtime proxy
generation e uma recuperação de dados eficiente
sem a instrumentação de bytecode.
• Para o exemplo colocar a fonte Java em uma pasta
denominada /src na pasta de desenvolvimento.
+lib
<Hibernate and third-party libraries>
+src
Event.java
9
import java.util.Date;
public class Event {
private Long id;
private String title;
private Date date;
Event() {}
public Long getId() {
return id;
}
private void setId(Long id) {
this.id = id;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
Event.java
Construtores
10
Arquivo de mapeamento
• É necessário especificar para o Hibernate como
carregar e armazenar objeto da classe de
persistência.
• O arquivo de mapeamento faz este papel
– Especifica qual tabela do banco de dados deve ser
acessado
– Quais colunas da tabela devem ser utilizadas.
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
[...]
</hibernate-mapping>
11
Arquivo DTD
• Pode-se utilizar o arquivo DTD do Hibernate para a
auto complementação dos elementos de
mapeamento XML e atributos em um editor de
programas ou IDE.
• Sugere-se abrir o arquivo DTD para verificar todos
os elementos, atributos e valores padrão.
• Hibernate não carregará o arquivo DTD da internet,
mas primeiro procura-o no classpath da aplicação.
– Esta localizado em .\src\org\hibernate
12
hibernate-mapping
• Entre duas tags hibernate de mapeamento, incluir
uma classe de elemento.
• Todas as classes de persistência de entidade
necessitam um mapeamento para uma tabela em
uma tabela do banco de dados SQL.
• Abaixo definiu-se como persistir e carregar objetos
da classe Event para a tabela EVENTS, cada
instância representada por uma linha desta tabela.
<hibernate-mapping>
<class name="Event" table="EVENTS">
</class>
</hibernate-mapping>
13
Identificador único de entidade
• Para mapear o identificador único para a chave
primária da tabela, é necessário configurar a
estratégia de geração dos valores para serem
colocadas na coluna da chave primária.
<hibernate-mapping>
<class name="Event" table="EVENTS">
<id name="id" column="EVENT_ID">
<generator class="increment"/>
</id>
</class>
</hibernate-mapping>
14
Chave primária
• O elemento ID é a declaração da propriedade do
identificador.
– name="id"
• declara o name da propriedade Java-Hibernate que será utilizada para
métodos SET e GET para acessar dos dados.
• O atributo column faz a ligação para o Hibernate qual coluna
da tabela EVENTS será utilizado como chave primária.
– column="EVENT_ID"
• O elemento generator especifica qual estratégia para
gerador de dados.
– Neste exemplo está sendo utilizado o método de incremento inmemory, muito útil para teste.
• Hibernate também suporta geração de valor automáticos
pelo banco de dados, assim como identificadores atribuídos
pela aplicação.
15
Propriedades de persistência
• Por padrão nenhuma propriedade da classe é
considerada para persistência.
• O nome do atributo da propriedade do elemento
indica para o Hibernate qual método get e set deve
ser utilizado.
• Por que a propriedade de mapeamento data incluir
o atributo da coluna e a propriedade title não?
• Sem o atributo coluna Hibernate por padrão utiliza a
propriedade nome como o nome da coluna.
• Date é uma palavra reservada na maioria dos banco
de dados, assim é melhor mapear com um nome
diferente.
16
Event.hbm.xml
<hibernate-mapping>
<class name="Event" table="EVENTS">
<id name="id" column="EVENT_ID">
<generator class="increment"/>
</id>
<property name="date" type="timestamp"
column="EVENT_DATE"/>
<property name="title"/>
</class>
</hibernate-mapping>
17
Forma de mapeamento
• Por que o atributo title não tem definido seu tipo?
– Os tipos declarados e utilizados no arquivo de mapeamento não são
tipos de dados Java.
– Também não são tipos de dados SQL.
• São tipos denominados Tipos de Dados de Mapeamento
Hibernate.
– Ele converte tipos de dados Java para tipos de dados SQL e vice
versa.
• Hibernate tenta determinar a conversão correta e mapear
tipos de atributos que não estão presentes no arquivo de
mapeamento.
• Em alguns casos detecção automática de tipo de dados,
utilizando Reflection on Java Class, pode não ter um valor
padrão conforme esperado.
– Este é o caso da propriedade date.
– Hibernate não sabe se a propriedade deve ser mapeada para o tipo
DATE ou TIMESTAMP ou TIME do SQL.
18
Event.hbm.xml
• O arquivo de mapeamento deve ser salvo com o
nome Event.hbm.xml, na pasta onde está
armazenado a fonte do Event.java.
• O nome do arquivo pode ser de livre escolha, mas o
sufixo deve ser hbm.xml.
• A estrutura de diretório deve ser:
+lib
<Hibernate and third-party libraries>
+src
Event.java
Event.hbm.xml
19
Exercício
• Criar um arquivo denominado Event.hbm.xml o
mapeamento do arquivo. (Pasta src)
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Event" table="EVENTS">
<id name="id" column="EVENT_ID">
<generator class="increment"/>
</id>
<property name="date" type="timestamp" column="EVENT_DATE"/>
<property name="title"/>
</class>
</hibernate-mapping>
20
Configurando para acessar Postgresql
• Buscar no site do PostgreSql
(http://jdbc.postgresql.org/download.html/) os drivers
JDBC.
• Colocar na pasta lib o arquivo
• Criar na raiz da pasta de desenvolvimento uma
pasta denominada data.
+lib
<Hibernate and third-party libraries>
postgresql-8.1-404.jdbc2.jar
+src
Event.java
Event.hbm.xml
+data
21
Conexão com o banco de dados
• Hibernate é a camada da aplicação que conecta-se com o
banco de dados, assim ele necessita de informações sobre a
conexão.
• As conexões são efetivadas através de um grupo de
conexões JDBC (JDBC connection pool) que deve ser
configurado também.
• A distribuição Hibernate contém inúmeras ferramentas de
conexões JDBC de código aberto (open source JDBC
connection).
• Para a configuração do Hibernate pode utilizar o arquivo
hibernate.properties ou hibernate.cfg.xml ou via aplicação.
22
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">
org.postgresql.Driver
</property>
<property name="connection.url">
jdbc:postgresql://localhost:5432/postgres
</property>
<property name="connection.username">postgres</property>
<property name="connection.password">1234</property>
23
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">
org.hibernate.dialect.PostgreSQLDialect
</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">create</property>
<mapping resource="Event.hbm.xml"/>
</session-factory>
</hibernate-configuration>
24
<session-factory>
• Este arquivo de configuração XML utiliza um arquivo
DTD diferente.
• Configura-se Hibernate's SessionFactory uma
fábrica responsável por um banco de dados
particular.
• Se existirem mais de um banco de dados, utiliza-se
inúmeras configurações <session-factory>
geralmente um arquivo para cada configuração para
facilitar a sua inicialização.
25
JDBC
• Os primeiros 4 elementos (propriedades) contém as
informações necessárias para a conexão JDBC.
<property name="connection.driver_class">
org.postgresql.Driver
</property>
<property name="connection.url">
jdbc:postgresql://localhost:5432/postgres
</property>
<property name="connection.username">postgres</property>
<property name="connection.password">1234</property>
26
Dialeto
• Propriedade do elemento dialeto especifica uma variante
SQL particular gerado pelo Hibernate
<property name="dialect">
org.hibernate.dialect.PostgreSQLDialect
</property>
• A opção hbm2ddl.auto habilita a geração automática dos
esquemas de banco de dados (database schemas)
diretamente dentro de banco de dados.
• Removendo-se esta opção de configuração pode-se
desligar esta característica.
• Pode-se redirecionar para um arquivo com a ajuda do
SchemaExport (ANT)
<property name="hbm2ddl.auto">create</property>
27
Event Mapping
• Adiciona-se o(s) arquivo(s) de mapeamento para as classes
de persistência.
<mapping resource="Event.hbm.xml"/>
• Copia-se este arquivo para o diretório fonte, assim completa
o classpath. .
• Hibernate automaticamente procura por um arquivo
denominado hibernate.cfg.xml na raiz do classpath durante a
inicialização.
• Criar o arquivo de configuração do Hibernate
(hibernate.cfg.xml).
+lib
<Hibernate and third-party libraries>
+src
Event.java
Event.hbm.xml
hibernate.cfg.xml
28
Inicialização
• Na inicialização deve incluir a construção de um objeto
SessionFactory para armazena-lo em algum lugar para fácil
acesso pelo código da aplicação.
• Uma SessionFactory pode abrir uma nova seção.
• Uma seção representa uma unidade de trabalho thread
simples (single thread), a SessionFactory é um objeto global
de uma thread segura, instanciada uma única vez.
• Será criada uma classe de ajuda HibernateUtil que cuidará
da inicialização e fará com que a manipulação da seção seja
conveniente.
• Assim o padrão de seção ThreadLocal chamado é útil aqui,
para manter a unidade de trabalho corrente com a thread
corrente.
29
SessionFactory
• Esta classe além de produzir uma seção global do
SessionFactory em sua inicialização estática
(chamada uma única vez pelo JVM quando a classe
é carregada), mas também tem uma variável
ThreadLocal para armazenar a seção da thread
corrente.
• Sempre que for chamado o método
HibernateUtil.currentSession() retornará sempre a
mesma unidade de trabalho Hibernate em um
mesmo thread.
• Uma chamda para o método
HibernateUtil.closeSession() finaliza a unidade de
trabalho corrente associada com um thread.
30
Nota: HibernateUtil
• Esta classe não é necessária se for implementar o
Hibernate em um servidor de aplicações J2EE:
– Um seção será automaticamente limitado pela transação
corrente JTA e pode-se procurar a SessionFactory
através do JNDI.
• Se utilizar o servidor de aplicação JBoss, pode se
implementado como um serviço de gerenciamento
de sistema e será automaticamente associada a
SessionFactory para uma nome JNDI.
build.xml
+lib
<Hibernate and third-party libraries>
+src
Event.java
Event.hbm.xml
HibernateUtil.java
hibernate.cfg.xml
+data
31
Registro de Ocorrências
• Agora é necessário configurar o sistema de registro
de ocorrências (logging system).
• Hibernate utiliza commons logging e permite
escolher entre Log4j e JDK 1.4 logging.
• A maioria dos desenvolvedores preferem Log4j.
– Copiar o arquivo log4j.properties para a pasta /src na
mesma pasta do hibernate.cfg.xml.
• A saída padrão das mensagens de inicialização são
apresentadas em stout.
32
Armazenado e Carregando Objetos
import org.hibernate.Transaction;
import org.hibernate.Session;
import java.util.Date;
public class EventManager {
public static void main(String[] args) {
EventManager mgr = new EventManager();
if (args[0].equals("store")) {
mgr.createAndStoreEvent("My Event", new Date());
}
HibernateUtil.sessionFactory.close();
}
private void createAndStoreEvent(String title, Date theDate){
Session session = HibernateUtil.currentSession();
Transaction tx = session.beginTransaction();
Event theEvent = new Event();
theEvent.setTitle(title);
theEvent.setDate(theDate);
session.save(theEvent);
tx.commit();
HibernateUtil.closeSession();
}
}
33
• Cria-se um novo objeto Event, que manipula o Hibernate.
• Hibernate cuida do SQL e executa as inserções no banco de
dados.
• Uma seção é uma simples unidade de trabalho.
• Uma unidade de trabalho pode ser mais longa que uma
simples transação no banco de dados.
– Exemplo: uma unidade de trabalho que faz inúmeras chamadas http
request/response em uma aplicação web.
• Separar a transação com o banco de dados da unidade de
trabalho e com a aplicação do ponto de vista do usuário é
um dos conceitos básicos de projeto do Hibernate.
34
Application Transaction
• Pode-de denominar uma unidade de trabalho longa que
geralmente encapsula inúmeras transações pequenas de
banco de dados como Application Transaction.
• O API de Transação Hibernate, é opcional, mas é utilizado
por sua portabilidade e conveniência.
• Para manipular a transação do banco dados, chamando o
método session.connection.commit(), deve-se atribuir um
código específico para o ambiente de desenvolvimento.
• Por padrão de configuração do Hibernate pode-se implantar
a camada de persistência em qualquer banco de dados.
• No capítulo 12 do Hibernate Reference Documentation
pode-se obter mais informações sobre o assunto.
35
NetBeans
Lib localizado em
minLib do Hibernate –
Postgresql
Netbeans
Eclipse
36
Eclipse
Lib localizado em
minLib do Hibernate –
Postgresql
37
Para adicionar eventos
• Para armazenar eventos, pode-se adicionar uma
opção no método main:
sf = new Configuration().configure().buildSessionFactory();
Session session = sf.openSession(); //Abre sessao
Transaction tx = session.beginTransaction(); //Cria
transacao
//Cria objeto Evento
Event theEvent = new Event();
theEvent.setTitle("Evento Novo");
theEvent.setDate(new Date());
session.save(theEvent);
tx.commit(); //Fecha transacao
session.close(); //Fecha sessao
13:45:09,734 DEBUG SchemaExport:301 - drop table EVENTS_POSJAVA
13:45:09,890 DEBUG SchemaExport:301 - drop sequence hibernate_sequence
13:45:09,906 DEBUG SchemaExport:301 - create table EVENTS_POSJAVA (EVENT_ID int8 not null,
EVENT_DATE timestamp, title varchar(255), primary key (EVENT_ID))
13:45:10,171 DEBUG SchemaExport:301 - create sequence hibernate_sequence
13:45:10,187 INFO SchemaExport:194 - schema export complete
Hibernate: select nextval ('hibernate_sequence')
Hibernate: insert into EVENTS_POSJAVA (EVENT_DATE, title, EVENT_ID) values (?, ?, ?)
38
listEvents()
sf = new Configuration().configure().buildSessionFactory();
Session session = sf.openSession(); //Abre sessao
List listaEventos = session.createQuery("from Event").list();
for (int i = 0; i < listaEventos.size(); i++) {
Event theEvent = (Event) listaEventos.get(i);
System.out.println(" Id:"+theEvent.getId());
System.out.println(" Titulo:"+theEvent.getTitle());
System.out.println(" Data: "+ theEvent.getDate());
}
session.close(); //Fecha sessao
• É utilizado aqui HQL (Hibernate Query Language)
para consultar e carregar todos os objetos de
Eventos existentes do banco de dados.
• Hibernate gerará a expressão SQL apropriada e
enviará para o banco de dados e populará os
objetos Events com os dados.
39
Exercício
• Desenvolver um código para criar, inserir e listar os dados da
tabela abaixo:
– A) PostgreSQL
– B) MySQL
Pessoa
Pessoa_ID (PK)
Nome
Sexo
Data_nascimento
• Analise o exemplo Estado, que lista os dados da tabela estado.
• Elabore um exemplo para listar o Municípios.
40
Download