JPA (Java Persistence API)
http://www.marcomendes.com/ArquivosBlog/AloMundoJPA.pdf
http://www.devmedia.com.br/articles/viewcomp.asp?comp=4590
http://evandropaes.wordpress.com/2007/06/22/introducao-a-java-persistence-api-%E2%80%93-jpa/
http://www.slideshare.net/caroljmcdonald/td09jpabestpractices2
http://www.slideshare.net/guestf54162/jpa-java-persistence-api
http://www.slideshare.net/rodrigocasca/jpa
https://www.redhat.com/docs/manuals/jboss/jboss-eap-4.2/doc/Server_Configuration_Guide/Java_EE_5_Application_Configuration.html
http://www.slideshare.net/junyuo/java-persistence-api-jpa-step-by-step-presentation
JPA é um framework utilizado na camada de persistência para obter maior produtividade. Modo padrão de mapeamento Objeto/Relacional.
O JPA define um caminho para mapear os POJOs para um BD (Java Persistence Metadata). Os pojos são vistos como beans de entidade(Entity Beans).
Utiliza-se o ORM(Mapeamento Objeto/Relacional) para os entity Beans possam ser portados facilmente de um fabricante para outro.
Entity: POJO, suporta herança e polimorfismo
EntityManager: Responsável pelas operações de persistência de objetos.
PersistenceContext: Área de memória que mantém os objetos que estão sendo manipulados pelos EntityManager
Provedores: Especificação para framework de persistência.
Persistence Unit: Configuração do provedor JPA para localizar o banco de dados e estabelecer conexões JDBC.
Exemplo simples:
package addressbook;
import javax.persistence.*;
@Entity
public class Person {
@Id @GeneratedValue
public Long id;
public String first;
public String middle;
public String last;
}
package addressbook;
import javax.persistence.*;
public class Main {
EntityManagerFactory factory; //Um factory por aplicação, pois é thread-safe. Mas só é importante para aplicações Web. App desktop só tem 1 usuário mesmo.
EntityManager manager; //Um manager por usuário.
public void init() {
factory = Persistence.createEntityManagerFactory("sample");//Persistence unit no persistence.xml.
manager = factory.createEntityManager();
}
private void shutdown() {
manager.close();
factory.close();
}
public static void main(String[] args) {
// TODO code application logic here
Main main = new Main();
main.init();
try {
// do some persistence stuff
} catch (RuntimeException ex) {
ex.printStackTrace();
} finally {
main.shutdown();
}
}
//Para fazer uma persistência, é só criar uma transação, criar os objetos e salvá-los
private void create() {
System.out.println("creating two people");
EntityTransaction tx = manager.getTransaction(); //Criou a Transação.
tx.begin();
try {
Person person = new Person();
person.first = "Joshua";
person.middle = "Michael";
person.last = "Marinacci";
manager.persist(person);
tx.commit();
} catch (Exception ex) {
tx.rollback();
}
System.out.println("created one person");
}
}
Chaves compostas usando @EmbeddedId
@Embeddable
public class ContactPK implements Serializable {
@Column(name = "FIRSTNAME", nullable = false)
private String firstname;
@Column(name = "LASTNAME", nullable = false)
private String lastname;
}
A chave primária da classe da Entidade é anotada com a anotação @EmbeddedId.
@Entity
public class Contact implements Serializable {
/**
* EmbeddedId primary key field
*/
@EmbeddedId
protected ContactPK contactPK;
public void hashcode(){} // tem que incluir esses dois métodos para garantir que terá só uma chave.
public void equals() {}
...
}
Persistence.xml
• Lista as classes a serem persistidas
• A conexão do Banco de Dados
• E propriedades específicas para a implementação de persistência (ex:Hibernate, Hypersonic)
• Deve ficar dentro do META-INF
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="sample" transaction-type="RESOURCE_LOCAL"> //Tem o nome da unidade, que tem que ser o mesmo recebido em Persistence.createEntityManagerFactory()
<class>addressbook.Person</class>
<properties>
<property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/>
<property name="hibernate.connection.username" value="sa"/>
<property name="hibernate.connection.password" value=""/>
<property name="hibernate.connection.url" value="jdbc:hsqldb:hsql://test"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.hbm2ddl.auto" value="update"/> //Controla como o hibernate cria e gerencia as suas tabelas
o Validate:
o Update: Cria as tabelas se elas não existirem, se adicionar novos campos, altera a tabela, deixando os dados intactos.
o Create: Cria a tabela na primeira conexão, destruindo todos os dados anteriores. Bom para teste.
o Create-drop: como o Create, mas destroy a tabela quando a conexão é fechada. Bom pra teste de unidade.
</properties>
</persistence-unit>
</persistence>
Rodar
java -classpath lib/hsqldb.jar org.hsqldb.Server //Para rodar o hypersonic
public static void main(String[] args) throws Exception {
// start hypersonic
Class.forName("org.hsqldb.jdbcDriver").newInstance();
Connection c = DriverManager.getConnection(
"jdbc:hsqldb:file:test", "sa", "");
// start persistence
Main main = new Main();
main.init();
// rest of the program....
// shutdown hypersonic
Statement stmt = c.createStatement();
stmt.execute("SHUTDOWN");
c.close();
}
Outros exemplos de Persistence.xml
http://download.oracle.com/docs/cd/B31017_01/web.1013/b28221/cfgdepds005.htm
Usado para o servidor saber qual DabaBase será usado. Nele é configurado qual engine de mapeamento Objeto/Relacional, cache para melhor performance. Ele dá a flexibilidade completa para configurar o EntityManager.
Colocar em: META-INF dentro do diretorio WEB-INF/classes ou do Jar.
OpenJPA
<?xml version="1.0"?>
<persistence>
<persistence-unit name="testjpa" transaction-type="RESOURCE_LOCAL">
<provider>
org.apache.openjpa.persistence.PersistenceProviderImpl
</provider>
<class>entidades.Cliente</class>
<properties>
<property name="openjpa.ConnectionURL" value="jdbc:postgresql://localhost:5432/jpateste"/>
<property name="openjpa.ConnectionDriverName" value="org.postgresql.Driver"/>
<property name="openjpa.ConnectionUserName" value="postgres"/>
<property name="openjpa.ConnectionPassword" value="123456"/>
<property name="openjpa.Log" value="SQL=TRACE"/>
</properties>
</persistence-unit>
</persistence>
Hibernate
<persistence>
<persistence-unit name="EmployeeService" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/DefaultDS</jta-data-source>
<properties>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name="hibernate.connection.driver_class" value="org.apache.derby.jdbc.EmbeddedDriver"/>
<property name="hibernate.connection.url" value="jdbc:derby:db; create=true"/>
<property name="hibernate.connection.autocommit" value="true"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" ou “DerbyDialect”/>
<property name="hibernate.connection.username" value="APP" />
<property name="hibernate.connection.password" value="APP" />
</properties>
</persistence-unit>
OU
<persistence>
<persistence-unit name="EmployeeService" transaction-type="RESOURCE_LOCAL">
<properties>
<property name="hibernate.connection.driver_class" value="org.apache.derby.jdbc.ClientDriver" />
<property name="hibernate.connection.url" value="jdbc:derby://localhost:1527/EmpServDB;create=true" />
<property name="hibernate.connection.username" value="APP" />
<property name="hibernate.connection.password" value="APP" />
<property name="hibernate.dialect" value="org.hibernate.dialect.DerbyDialect" />
</properties>
</persistence-unit>
</persistence>
TopLink
<persistence>
<persistence-unit name="EmployeeService" transaction-type="RESOURCE_LOCAL">
<properties>
<property name="toplink.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/>
<property name="toplink.jdbc.url" value="jdbc:derby://localhost:1527/EmpServDB;create=true"/>
<property name="toplink.jdbc.user" value="APP"/>
<property name="toplink.jdbc.password" value="APP"/>
</properties>
</persistence-unit>
</persistence>
Tabela:
create table bug (
id_bug int(11) not null auto_increment,
titulo varchar(60) not null,
data date default null,
texto text not null,
primary key (id_bug)
);
Classe POJO
@entity
@table(name=”bug”)
public class bug implements java.io.serializable {
private integer id_bug;
private string titulo;
private java.util.date data;
private string texto;
@Enumerated(EnumType.STRING) → Define que um tipo vem de um enum
@Conumn(name=”TIPO_MOEDA”, nullable=false, columnDefinition=”CHAR(1)”))
private TipoMoeda tipoMoeda;
@Transient → Valor não será gravado.
private Integer valor = new Integer();
/** creates a new instance of bug */
public bug() {}
/*a notação @generatedvalue(strategy=generationtype.sequence) informa que o id será gerado automaticamente pelo db.*/
@id
@generatedvalue(strategy=generationtype.sequence)
@column(name=”id_bug”)
public integer getid_bug() { return id_bug; }
public void setid_bug(integer id_bug) { this.id_bug = id_bug; }
@column(name=”titulo”, lenght=255, nullable=true)
public string gettitulo() { return titulo; }
public void settitulo(string titulo) { this.titulo = titulo; }
@temporal(temporaltype.date)
@column(name=”data”)
public java.util.date getdata() { return data; }
public void setdata(java.util.date data) { this.data = data; }
@column(name=”texto”)
@Lob → Define que o campo armazenará dados do tipo Long Object Binary(texto)
public string gettexto() { return texto; }
public void settexto(string texto) { this.texto = texto; }
@override
public string tostring(){ return “id: “+this.id_bug; }
}
Query
• NamedQuery
o Query predefinidaes executadas por nome.
@NamedQuery cria consulta predefinida (estática) associado com o @Entity
@Entity
@NamedQuery(name = “ConsultaPorId”, query = “SELECT f FROM Funcionarios f WHERE f.id = :id”)
public class Funcionario implements Serializable {
...
}
• Criteria
o So do Hibernate, baseado na API Criteria
• By Example
• JPAQL/ HQL / EJB3-QL
o Parecidas com SQL, mas mais objec-centric
o Suporta (Seleção de instancias, propriedades, polimorfismo), joining automático para propriedades nested.
o Confortável para quem é familiar ao SQL
o JPAQL é um subconjunto do HQL (Hibernate suporta ambos)
o Para rodar:
EntityManager.createQuery(String jpaql)
Session.createQuery(String hql)
Ex: “from Item i where i.name = “aaa”
private void search() {
EntityTransaction tx = manager.getTransaction();
tx.begin();
System.out.println("searching for people");
Query query = manager.createQuery("select p from Person p");
List<Person> results = (List<Person>)query.getResultList();
for(Person p : results) {
System.out.println("got a person: " + p.first + " " + p.last);
}
System.out.println("done searching for people");
tx.commit();
}
• Native SQL
o Session.createSQLQuery(SQL)
o EntityManager.createNativeQuery(sql)
Relacionamento
• Um para Um (@OneToOne)
@OneToOne (mapedBy = “pessoa”)
private Ramal ramal;
@OneToOne
@JoinColumn( name = “id_pessoa”)
private Pessoa pessoa;
Tabelas.
ramal pessoa
- numero:Integer - id:Integer
- pessoa_id: Integer (FK) - nome: VARCHAR(50)
• Um para Muitos(@OneToMany)´
Uma entidade possui uma coleção de outras entidades.
@OneToMany(mappedBy=”pessoa”, cascade = CascadeType.ALL)
private List<Ramal> ramais = new ArrayLIst<Ramal>();
• Muitos para um (@ManyToOne)
A entidade faz parte de uma coleção de entidades de outra entidade.
@ManyToOne(cascade=CascadeType.PERSIST)
@JoinColumn(name=”id_pessoa”)
private Pessoa pessoa;
• Muitos para muitos(@ManyToMany)
@ManyToMany
@JoinTable(name=”ramal_pessoa”,
joinColumns=(@JoinColumn(name = “id_pessoa”)),
inverseJoinColumns = (@JoinColumn(name = “id_ramal”))
)
@Column (name = “id_ramal”);
private List<Ramal> ramais = new ArrayList<Ramal>();
@ManyToMany
@JoinTable(name=”ramal_pessoa”,
joinColumns=(@JoinColumn(name = “id_ramal”)),
inverseJoinColumns = (@JoinColumn(name = “id_pessoa”))
)
@Column(name = “id_pessoa”)
private List<Ramal> pessoas= new ArrayList<Ramal>();
Tabelas:
Ramal pessoa_has_ramal pessoa
- numero:INTEGER - pessoa_id: INTEGER (FK) - id:INTEGER
- ramal_numero: INTEGER - nome: VARCHAR(50)
Características dos Relacionamentos:
• Lazy loading
o Otimização de Performance
o Itens relacionados não são carregados até que eles sejam acessados pela primeira vez. (acesso a nível de Campo)
o Limitado para trabalhar somente com a Sessão ou EntityManager que carregou o objeto pai.
Pode causar problemas em aplicações web.
• Fetch
o Fetch Mode
Lazy
Eager – desabilita o lazy loading
o Modo pode ser configurado em cada relacionamento.
o Considerar a performance e usar quando estiver configurando o fetch.
@Basic(fetch = FetchType.LAZY) //Só vai carregar o objeto quando o método for acessado.
@Lob //Permite um BLOB ou CLOB (Bit or Char Large Object transforma valores para charS ou biteS
public BufferedImage getPhoto() {
return photo;
}
• Cascading
o Fala do Hibernate o que fazer com o relacionamento nos casos de Insert, Update, Delete, All
o Cascade=PERSIST, REMOVE, MERGE, REFRESH, ALL.
• Polimorphic
o Três abordagens:
Tabela por hierarquia de classe
• Todo dado de todas as propriedades das classes na herança são guardadas na tabela.
• Requer que as colunas que representam campos na subclasses permitam NULL.
• Usa uma coluna discriminadora para determinar o tipo de objeto representado em uma tupla.
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name=”person_type”)
public class Person {
@Id @GeneratedValue(strategy=GenerationType.AUTO)
private int id = 0;
private String name;
}
@Entity @DiscriminatorValue(value=”p”
public class Patient extends Person {
private boolean insured = false;
}
@Entity @DiscriminatorValue(value=”d”)
public class Physician extends Person {
private boolean accredited;
}
create table person {
patient_id INTEGER,
person_type varchar(255) not null,
name varchar(255) not null,
insured bit
accredited bit
primary key (patient_id));
Tabela por sub-classe.
• Cada sub-classe tem a sua própria tabela.
• Campos da classe Pai estão em outra tabela.
• PK na tabela da sub-classe referem à tabela da classe pai.
• Usar configuração joined-subclass
• Também suporta o uso de discriminator
@Entity @Inheritance(strategy=InheritanceType.JOINED)
public abstract class Payment
@Id @Column(name=”payment_id”)
@GeneratedValue(strategy=GenerationType.AUTO)
private int id = 0;
}
@Entity @Table(name=”check_payment”)
@PrimaryKeyJoinColumn(name=”payment_id”)
public class CheckPayment extends Payment{
private int check;
}
@Entity @Table(name=”credit_card_payment”)
@PrimaryKeyJoinColumn(name=”payment_id”)
public class CreditCardPayment extends Payment{
@Column(nullable=false)
private String account;
}
create table payment { payment_id INTEGER, amount INTEGER, primary key(payment_id));
create table check_payment { payment_id INTEGER, check-numer INTEGER, primary key(payment_id));
create table credit_card_payment { payment_id INTEGER, account INTEGER, primary key(payment_id));
Table por classe concreta
• Cada classe na hierarquia tem a sua própria tabela.
• O campos da classe pai são duplicadas em cada tabela.
• Duas abordagens:
o Subclass Union.
Mapeia a classe pai normalmente, sem discriminador.
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
Papeia cada uma das subclasses
• Especifica o nome da tabela
• Especifica as propriedades das subclasses
o Polimorfismo Implícito
Class pai não é mapeada usando hibernate (@MappedSuperclass)
Cada subclasse é mapeada como uma clase normal.
• Mapeia todas as propriedades, inclusive as propriedades do pai.
@MappedSuperclass
public class Vehicle{ //Class não é mapeada, mas as propriedades são.
@Id @Column(name=”vehicle_id”)
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
}
@Entity
public class Car extends Vehicle{
boolean coupe;
}
@Entity
public class Truck extends Vehicle {
@Column (name=”Max_weight”)
private int maxWeight;
}
public SUV extends Truck {
@Column (name=”spinner_wheels”)
private boolean spinnerWheels;
}
create table vehicle ( vehicle_id INTEGER, coupe_ind bit, primary key(vehicle_id));
create table truck ( vehicle_id INTEGER, max_weight bit, primary key(vehicle_id));
create table suv ( vehicle_id INTEGER, max_weight bit, primary key(vehicle_id));
Sem EJB
EntityManagerFactory emf = Persistence.createEntityManagerFactory(“myapp);//O que está no persistence-unit
EntityManager em = emf.createEntityManager();
EntityTransaction et = em.getTransaction();
et.begin();
Insert: em.persist(carro);
Update: em.merge(carro);
Remove: em.remove(carro);
Busca: Carro carro = em.find(Carro.class, id);
et.commit() ou et.roolback();
Com EJB
EntityManagerFactory emf = Persistence.createEntityManagerFactory(“myapp);//O que está no persistence-unit
@PersistenceContext
EntityManager em = emf.createEntityManager();
EntityTransaction et = em.getTransaction();
et.begin();
Insert: em.persist(carro);
Update: em.merge(carro);
Remove: em.remove(carro);
Busca: Carro carro = em.find(Carro.class, id);
et.commit() ou et.roolback();
6.4.9.1 Entity Manager
• No Hibernate
o Configuration -> SessionFactoryy -> Session
o Session é o gateway para as funções de persistência.
• JPA
o Persistence -> EntityManagerFactory -> EntityManager
o EntityManager é o gateway para as funções de persistência.
Ciclo de Vida de um Objeto
Um objeto(Entity) pode ter 4 estados que indicam como eles estão conectados ao BD.
• New(transient): Objeto foi criado, mas ainda não foi persistido ou associado ao BD. Ao ser salvo com o EntityManager.persist() ele passa ao estado Managed.
• Managed(Persistent): O objeto já está associado ao BD. Mudanças no objeto vão, potencialmente gerar mudança no BD. Se necessário pode-se chamar EntityManager.flush() para sincronizar as mudanças, senão somente no commit da transação.
• Detached: O objeto já foi associado ao BD, mas não está mais. Um objeto Detached pode ser reatached usando o EntityManager.merge().
• Removed: Objeto que recebeu a operação de remoção. EntityManager.remove();
Similar ao Hibernate Session, controla o ciclo de vida das entidades.
• new() → Cria uma nova entidade
• persist() → Salva ou faz um update em uma entidade
public Order createNewOrder(Customer customer){
Order order = new Order(customer);
entityManager.persist(order);
return order; }
• refresh() → Atualiza o estado da entidade
• remove() → Marca uma entidade para remoção
public void removeOrder(Long orderId){
Order order = entityManager.find(Order.class, orderId);
entityManager.remove(order); }
• merge() → Sincroniza o estado de entidades desacopladas.
public void updateOrder(Order order){
entityManager.merge(order); }
• find(Class type, Serializeble id) – Obtém o item de um tipo pelo id
• getTransaction
◦ Prove um objeto de transação para fazer o commit e rollback.
http://www.devmedia.com.br/articles/viewcomp.asp?comp=4590
http://evandropaes.wordpress.com/2007/06/22/introducao-a-java-persistence-api-%E2%80%93-jpa/
http://www.slideshare.net/caroljmcdonald/td09jpabestpractices2
http://www.slideshare.net/guestf54162/jpa-java-persistence-api
http://www.slideshare.net/rodrigocasca/jpa
https://www.redhat.com/docs/manuals/jboss/jboss-eap-4.2/doc/Server_Configuration_Guide/Java_EE_5_Application_Configuration.html
http://www.slideshare.net/junyuo/java-persistence-api-jpa-step-by-step-presentation
JPA é um framework utilizado na camada de persistência para obter maior produtividade. Modo padrão de mapeamento Objeto/Relacional.
O JPA define um caminho para mapear os POJOs para um BD (Java Persistence Metadata). Os pojos são vistos como beans de entidade(Entity Beans).
Utiliza-se o ORM(Mapeamento Objeto/Relacional) para os entity Beans possam ser portados facilmente de um fabricante para outro.
Entity: POJO, suporta herança e polimorfismo
EntityManager: Responsável pelas operações de persistência de objetos.
PersistenceContext: Área de memória que mantém os objetos que estão sendo manipulados pelos EntityManager
Provedores: Especificação para framework de persistência.
Persistence Unit: Configuração do provedor JPA para localizar o banco de dados e estabelecer conexões JDBC.
Exemplo simples:
package addressbook;
import javax.persistence.*;
@Entity
public class Person {
@Id @GeneratedValue
public Long id;
public String first;
public String middle;
public String last;
}
package addressbook;
import javax.persistence.*;
public class Main {
EntityManagerFactory factory; //Um factory por aplicação, pois é thread-safe. Mas só é importante para aplicações Web. App desktop só tem 1 usuário mesmo.
EntityManager manager; //Um manager por usuário.
public void init() {
factory = Persistence.createEntityManagerFactory("sample");//Persistence unit no persistence.xml.
manager = factory.createEntityManager();
}
private void shutdown() {
manager.close();
factory.close();
}
public static void main(String[] args) {
// TODO code application logic here
Main main = new Main();
main.init();
try {
// do some persistence stuff
} catch (RuntimeException ex) {
ex.printStackTrace();
} finally {
main.shutdown();
}
}
//Para fazer uma persistência, é só criar uma transação, criar os objetos e salvá-los
private void create() {
System.out.println("creating two people");
EntityTransaction tx = manager.getTransaction(); //Criou a Transação.
tx.begin();
try {
Person person = new Person();
person.first = "Joshua";
person.middle = "Michael";
person.last = "Marinacci";
manager.persist(person);
tx.commit();
} catch (Exception ex) {
tx.rollback();
}
System.out.println("created one person");
}
}
Chaves compostas usando @EmbeddedId
@Embeddable
public class ContactPK implements Serializable {
@Column(name = "FIRSTNAME", nullable = false)
private String firstname;
@Column(name = "LASTNAME", nullable = false)
private String lastname;
}
A chave primária da classe da Entidade é anotada com a anotação @EmbeddedId.
@Entity
public class Contact implements Serializable {
/**
* EmbeddedId primary key field
*/
@EmbeddedId
protected ContactPK contactPK;
public void hashcode(){} // tem que incluir esses dois métodos para garantir que terá só uma chave.
public void equals() {}
...
}
Persistence.xml
• Lista as classes a serem persistidas
• A conexão do Banco de Dados
• E propriedades específicas para a implementação de persistência (ex:Hibernate, Hypersonic)
• Deve ficar dentro do META-INF
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="sample" transaction-type="RESOURCE_LOCAL"> //Tem o nome da unidade, que tem que ser o mesmo recebido em Persistence.createEntityManagerFactory()
<class>addressbook.Person</class>
<properties>
<property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/>
<property name="hibernate.connection.username" value="sa"/>
<property name="hibernate.connection.password" value=""/>
<property name="hibernate.connection.url" value="jdbc:hsqldb:hsql://test"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.hbm2ddl.auto" value="update"/> //Controla como o hibernate cria e gerencia as suas tabelas
o Validate:
o Update: Cria as tabelas se elas não existirem, se adicionar novos campos, altera a tabela, deixando os dados intactos.
o Create: Cria a tabela na primeira conexão, destruindo todos os dados anteriores. Bom para teste.
o Create-drop: como o Create, mas destroy a tabela quando a conexão é fechada. Bom pra teste de unidade.
</properties>
</persistence-unit>
</persistence>
Rodar
java -classpath lib/hsqldb.jar org.hsqldb.Server //Para rodar o hypersonic
public static void main(String[] args) throws Exception {
// start hypersonic
Class.forName("org.hsqldb.jdbcDriver").newInstance();
Connection c = DriverManager.getConnection(
"jdbc:hsqldb:file:test", "sa", "");
// start persistence
Main main = new Main();
main.init();
// rest of the program....
// shutdown hypersonic
Statement stmt = c.createStatement();
stmt.execute("SHUTDOWN");
c.close();
}
Outros exemplos de Persistence.xml
http://download.oracle.com/docs/cd/B31017_01/web.1013/b28221/cfgdepds005.htm
Usado para o servidor saber qual DabaBase será usado. Nele é configurado qual engine de mapeamento Objeto/Relacional, cache para melhor performance. Ele dá a flexibilidade completa para configurar o EntityManager.
Colocar em: META-INF dentro do diretorio WEB-INF/classes ou do Jar.
OpenJPA
<?xml version="1.0"?>
<persistence>
<persistence-unit name="testjpa" transaction-type="RESOURCE_LOCAL">
<provider>
org.apache.openjpa.persistence.PersistenceProviderImpl
</provider>
<class>entidades.Cliente</class>
<properties>
<property name="openjpa.ConnectionURL" value="jdbc:postgresql://localhost:5432/jpateste"/>
<property name="openjpa.ConnectionDriverName" value="org.postgresql.Driver"/>
<property name="openjpa.ConnectionUserName" value="postgres"/>
<property name="openjpa.ConnectionPassword" value="123456"/>
<property name="openjpa.Log" value="SQL=TRACE"/>
</properties>
</persistence-unit>
</persistence>
Hibernate
<persistence>
<persistence-unit name="EmployeeService" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/DefaultDS</jta-data-source>
<properties>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name="hibernate.connection.driver_class" value="org.apache.derby.jdbc.EmbeddedDriver"/>
<property name="hibernate.connection.url" value="jdbc:derby:db; create=true"/>
<property name="hibernate.connection.autocommit" value="true"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" ou “DerbyDialect”/>
<property name="hibernate.connection.username" value="APP" />
<property name="hibernate.connection.password" value="APP" />
</properties>
</persistence-unit>
OU
<persistence>
<persistence-unit name="EmployeeService" transaction-type="RESOURCE_LOCAL">
<properties>
<property name="hibernate.connection.driver_class" value="org.apache.derby.jdbc.ClientDriver" />
<property name="hibernate.connection.url" value="jdbc:derby://localhost:1527/EmpServDB;create=true" />
<property name="hibernate.connection.username" value="APP" />
<property name="hibernate.connection.password" value="APP" />
<property name="hibernate.dialect" value="org.hibernate.dialect.DerbyDialect" />
</properties>
</persistence-unit>
</persistence>
TopLink
<persistence>
<persistence-unit name="EmployeeService" transaction-type="RESOURCE_LOCAL">
<properties>
<property name="toplink.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/>
<property name="toplink.jdbc.url" value="jdbc:derby://localhost:1527/EmpServDB;create=true"/>
<property name="toplink.jdbc.user" value="APP"/>
<property name="toplink.jdbc.password" value="APP"/>
</properties>
</persistence-unit>
</persistence>
Tabela:
create table bug (
id_bug int(11) not null auto_increment,
titulo varchar(60) not null,
data date default null,
texto text not null,
primary key (id_bug)
);
Classe POJO
@entity
@table(name=”bug”)
public class bug implements java.io.serializable {
private integer id_bug;
private string titulo;
private java.util.date data;
private string texto;
@Enumerated(EnumType.STRING) → Define que um tipo vem de um enum
@Conumn(name=”TIPO_MOEDA”, nullable=false, columnDefinition=”CHAR(1)”))
private TipoMoeda tipoMoeda;
@Transient → Valor não será gravado.
private Integer valor = new Integer();
/** creates a new instance of bug */
public bug() {}
/*a notação @generatedvalue(strategy=generationtype.sequence) informa que o id será gerado automaticamente pelo db.*/
@id
@generatedvalue(strategy=generationtype.sequence)
@column(name=”id_bug”)
public integer getid_bug() { return id_bug; }
public void setid_bug(integer id_bug) { this.id_bug = id_bug; }
@column(name=”titulo”, lenght=255, nullable=true)
public string gettitulo() { return titulo; }
public void settitulo(string titulo) { this.titulo = titulo; }
@temporal(temporaltype.date)
@column(name=”data”)
public java.util.date getdata() { return data; }
public void setdata(java.util.date data) { this.data = data; }
@column(name=”texto”)
@Lob → Define que o campo armazenará dados do tipo Long Object Binary(texto)
public string gettexto() { return texto; }
public void settexto(string texto) { this.texto = texto; }
@override
public string tostring(){ return “id: “+this.id_bug; }
}
Query
• NamedQuery
o Query predefinidaes executadas por nome.
@NamedQuery cria consulta predefinida (estática) associado com o @Entity
@Entity
@NamedQuery(name = “ConsultaPorId”, query = “SELECT f FROM Funcionarios f WHERE f.id = :id”)
public class Funcionario implements Serializable {
...
}
• Criteria
o So do Hibernate, baseado na API Criteria
• By Example
• JPAQL/ HQL / EJB3-QL
o Parecidas com SQL, mas mais objec-centric
o Suporta (Seleção de instancias, propriedades, polimorfismo), joining automático para propriedades nested.
o Confortável para quem é familiar ao SQL
o JPAQL é um subconjunto do HQL (Hibernate suporta ambos)
o Para rodar:
EntityManager.createQuery(String jpaql)
Session.createQuery(String hql)
Ex: “from Item i where i.name = “aaa”
private void search() {
EntityTransaction tx = manager.getTransaction();
tx.begin();
System.out.println("searching for people");
Query query = manager.createQuery("select p from Person p");
List<Person> results = (List<Person>)query.getResultList();
for(Person p : results) {
System.out.println("got a person: " + p.first + " " + p.last);
}
System.out.println("done searching for people");
tx.commit();
}
• Native SQL
o Session.createSQLQuery(SQL)
o EntityManager.createNativeQuery(sql)
Relacionamento
• Um para Um (@OneToOne)
@OneToOne (mapedBy = “pessoa”)
private Ramal ramal;
@OneToOne
@JoinColumn( name = “id_pessoa”)
private Pessoa pessoa;
Tabelas.
ramal pessoa
- numero:Integer - id:Integer
- pessoa_id: Integer (FK) - nome: VARCHAR(50)
• Um para Muitos(@OneToMany)´
Uma entidade possui uma coleção de outras entidades.
@OneToMany(mappedBy=”pessoa”, cascade = CascadeType.ALL)
private List<Ramal> ramais = new ArrayLIst<Ramal>();
• Muitos para um (@ManyToOne)
A entidade faz parte de uma coleção de entidades de outra entidade.
@ManyToOne(cascade=CascadeType.PERSIST)
@JoinColumn(name=”id_pessoa”)
private Pessoa pessoa;
• Muitos para muitos(@ManyToMany)
@ManyToMany
@JoinTable(name=”ramal_pessoa”,
joinColumns=(@JoinColumn(name = “id_pessoa”)),
inverseJoinColumns = (@JoinColumn(name = “id_ramal”))
)
@Column (name = “id_ramal”);
private List<Ramal> ramais = new ArrayList<Ramal>();
@ManyToMany
@JoinTable(name=”ramal_pessoa”,
joinColumns=(@JoinColumn(name = “id_ramal”)),
inverseJoinColumns = (@JoinColumn(name = “id_pessoa”))
)
@Column(name = “id_pessoa”)
private List<Ramal> pessoas= new ArrayList<Ramal>();
Tabelas:
Ramal pessoa_has_ramal pessoa
- numero:INTEGER - pessoa_id: INTEGER (FK) - id:INTEGER
- ramal_numero: INTEGER - nome: VARCHAR(50)
Características dos Relacionamentos:
• Lazy loading
o Otimização de Performance
o Itens relacionados não são carregados até que eles sejam acessados pela primeira vez. (acesso a nível de Campo)
o Limitado para trabalhar somente com a Sessão ou EntityManager que carregou o objeto pai.
Pode causar problemas em aplicações web.
• Fetch
o Fetch Mode
Lazy
Eager – desabilita o lazy loading
o Modo pode ser configurado em cada relacionamento.
o Considerar a performance e usar quando estiver configurando o fetch.
@Basic(fetch = FetchType.LAZY) //Só vai carregar o objeto quando o método for acessado.
@Lob //Permite um BLOB ou CLOB (Bit or Char Large Object transforma valores para charS ou biteS
public BufferedImage getPhoto() {
return photo;
}
• Cascading
o Fala do Hibernate o que fazer com o relacionamento nos casos de Insert, Update, Delete, All
o Cascade=PERSIST, REMOVE, MERGE, REFRESH, ALL.
• Polimorphic
o Três abordagens:
Tabela por hierarquia de classe
• Todo dado de todas as propriedades das classes na herança são guardadas na tabela.
• Requer que as colunas que representam campos na subclasses permitam NULL.
• Usa uma coluna discriminadora para determinar o tipo de objeto representado em uma tupla.
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name=”person_type”)
public class Person {
@Id @GeneratedValue(strategy=GenerationType.AUTO)
private int id = 0;
private String name;
}
@Entity @DiscriminatorValue(value=”p”
public class Patient extends Person {
private boolean insured = false;
}
@Entity @DiscriminatorValue(value=”d”)
public class Physician extends Person {
private boolean accredited;
}
create table person {
patient_id INTEGER,
person_type varchar(255) not null,
name varchar(255) not null,
insured bit
accredited bit
primary key (patient_id));
Tabela por sub-classe.
• Cada sub-classe tem a sua própria tabela.
• Campos da classe Pai estão em outra tabela.
• PK na tabela da sub-classe referem à tabela da classe pai.
• Usar configuração joined-subclass
• Também suporta o uso de discriminator
@Entity @Inheritance(strategy=InheritanceType.JOINED)
public abstract class Payment
@Id @Column(name=”payment_id”)
@GeneratedValue(strategy=GenerationType.AUTO)
private int id = 0;
}
@Entity @Table(name=”check_payment”)
@PrimaryKeyJoinColumn(name=”payment_id”)
public class CheckPayment extends Payment{
private int check;
}
@Entity @Table(name=”credit_card_payment”)
@PrimaryKeyJoinColumn(name=”payment_id”)
public class CreditCardPayment extends Payment{
@Column(nullable=false)
private String account;
}
create table payment { payment_id INTEGER, amount INTEGER, primary key(payment_id));
create table check_payment { payment_id INTEGER, check-numer INTEGER, primary key(payment_id));
create table credit_card_payment { payment_id INTEGER, account INTEGER, primary key(payment_id));
Table por classe concreta
• Cada classe na hierarquia tem a sua própria tabela.
• O campos da classe pai são duplicadas em cada tabela.
• Duas abordagens:
o Subclass Union.
Mapeia a classe pai normalmente, sem discriminador.
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
Papeia cada uma das subclasses
• Especifica o nome da tabela
• Especifica as propriedades das subclasses
o Polimorfismo Implícito
Class pai não é mapeada usando hibernate (@MappedSuperclass)
Cada subclasse é mapeada como uma clase normal.
• Mapeia todas as propriedades, inclusive as propriedades do pai.
@MappedSuperclass
public class Vehicle{ //Class não é mapeada, mas as propriedades são.
@Id @Column(name=”vehicle_id”)
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
}
@Entity
public class Car extends Vehicle{
boolean coupe;
}
@Entity
public class Truck extends Vehicle {
@Column (name=”Max_weight”)
private int maxWeight;
}
public SUV extends Truck {
@Column (name=”spinner_wheels”)
private boolean spinnerWheels;
}
create table vehicle ( vehicle_id INTEGER, coupe_ind bit, primary key(vehicle_id));
create table truck ( vehicle_id INTEGER, max_weight bit, primary key(vehicle_id));
create table suv ( vehicle_id INTEGER, max_weight bit, primary key(vehicle_id));
Sem EJB
EntityManagerFactory emf = Persistence.createEntityManagerFactory(“myapp);//O que está no persistence-unit
EntityManager em = emf.createEntityManager();
EntityTransaction et = em.getTransaction();
et.begin();
Insert: em.persist(carro);
Update: em.merge(carro);
Remove: em.remove(carro);
Busca: Carro carro = em.find(Carro.class, id);
et.commit() ou et.roolback();
Com EJB
EntityManagerFactory emf = Persistence.createEntityManagerFactory(“myapp);//O que está no persistence-unit
@PersistenceContext
EntityManager em = emf.createEntityManager();
EntityTransaction et = em.getTransaction();
et.begin();
Insert: em.persist(carro);
Update: em.merge(carro);
Remove: em.remove(carro);
Busca: Carro carro = em.find(Carro.class, id);
et.commit() ou et.roolback();
6.4.9.1 Entity Manager
• No Hibernate
o Configuration -> SessionFactoryy -> Session
o Session é o gateway para as funções de persistência.
• JPA
o Persistence -> EntityManagerFactory -> EntityManager
o EntityManager é o gateway para as funções de persistência.
Ciclo de Vida de um Objeto
Um objeto(Entity) pode ter 4 estados que indicam como eles estão conectados ao BD.
• New(transient): Objeto foi criado, mas ainda não foi persistido ou associado ao BD. Ao ser salvo com o EntityManager.persist() ele passa ao estado Managed.
• Managed(Persistent): O objeto já está associado ao BD. Mudanças no objeto vão, potencialmente gerar mudança no BD. Se necessário pode-se chamar EntityManager.flush() para sincronizar as mudanças, senão somente no commit da transação.
• Detached: O objeto já foi associado ao BD, mas não está mais. Um objeto Detached pode ser reatached usando o EntityManager.merge().
• Removed: Objeto que recebeu a operação de remoção. EntityManager.remove();
Similar ao Hibernate Session, controla o ciclo de vida das entidades.
• new() → Cria uma nova entidade
• persist() → Salva ou faz um update em uma entidade
public Order createNewOrder(Customer customer){
Order order = new Order(customer);
entityManager.persist(order);
return order; }
• refresh() → Atualiza o estado da entidade
• remove() → Marca uma entidade para remoção
public void removeOrder(Long orderId){
Order order = entityManager.find(Order.class, orderId);
entityManager.remove(order); }
• merge() → Sincroniza o estado de entidades desacopladas.
public void updateOrder(Order order){
entityManager.merge(order); }
• find(Class type, Serializeble id) – Obtém o item de um tipo pelo id
• getTransaction
◦ Prove um objeto de transação para fazer o commit e rollback.
Nenhum comentário:
Postar um comentário