• Nenhum resultado encontrado

IntroduçãoJPA

N/A
N/A
Protected

Academic year: 2021

Share "IntroduçãoJPA"

Copied!
107
0
0

Texto

(1)

Introdução ao JPA

Prof. Bruno Ferreira

(2)

Mapeamento Objeto Relacional

(ORM)

(3)

Mapeamento Objeto Relacional

(ORM)

(4)

Mapeamento Objeto Relacional

(ORM)

(5)

Mapeamento Objeto Relacional

(ORM)

(6)

Mapeamento Objeto Relacional

(ORM)

(7)

Download do Hibernate

(8)

Instalando o Hibernate

1) Descompacte os arquivo baixado

2) Dentro do Eclipse crie uma variável de usuário na opção de preferências. 3) Adicione todos os arquivos .jar dos diretórios “required” e “jpa”

(9)

Download do JDBC-MySql

(10)

Instalando o JDBC-MySql

1) Descompacte os arquivo baixado

2) Dentro do Eclipse defina um novo na opção de preferências. 3) Adicione o arquivo .jar referente ao driver

(11)

Salvando o primeiro objeto no Banco

de Dados

CREATE TABLE cliente (

codigo BIGINT NOT NULL AUTO_INCREMENT, nome VARCHAR(100) NOT NULL,

idade INTEGER,

sexo VARCHAR(1) NOT NULL, profissao VARCHAR(30),

Nome do BD: cadastro01

profissao VARCHAR(30), PRIMARY KEY (codigo) );

CREATE TABLE conta_corrente (

codigo BIGINT NOT NULL AUTO_INCREMENT, numero VARCHAR(12) NOT NULL,

saldo DECIMAL,

codigo_cliente BIGINT NOT NULL, PRIMARY KEY (codigo),

FOREIGN KEY (codigo_cliente) REFERENCES cliente (codigo) );

(12)

Salvando o primeiro objeto no Banco

de Dados

1) Crie um novo projeto java e informe o nome do projeto. 2) Na aba Libraries, clique no botão “Add Library...”

(13)

Salvando o primeiro objeto no Banco

de Dados

1) Ainda na aba Libraries, clique no botão “Add Library...” 2) Escolha o item “User Library” e clique em Next

(14)

Salvando o primeiro objeto no Banco

de Dados

1) Crie uma estrutura de diretórios similar a figura abaixo

2) Na pasta META-INF crie o arquivo de configuração do Hibernate “persistence.xml” 3) Configure o arquivo xml como descrito abaixo.

(15)

Salvando o primeiro objeto no Banco

de Dados

Outro exemplo de persistence.xml:

....

<persistence-unitname="financeiroPU" transaction-type="RESOURCE_LOCAL"> <properties>

<propertyname="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/financeiro" /> <propertyname="javax.persistence.jdbc.user" value="root" />

<propertyname="javax.persistence.jdbc.password" value="root" />

<propertyname="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />

Estrutura de diretórios no Netbeans

<propertyname="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />

<propertyname="javax.persistence.schema-generation.database.action" value="drop-and-create" /> <propertyname="javax.persistence.schema-generation.create-source" value="metadata" />

<propertyname="javax.persistence.schema-generation.drop-source" value="metadata" />

<propertyname="javax.persistence.sql-load-script-source" value="META-INF/sql/carregar-dados.sql"/> <propertyname="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />

<propertyname="hibernate.show_sql" value="true" /> <propertyname="hibernate.format_sql" value="true" /> </properties>

</persistence-unit> ....

(16)

Salvando o primeiro objeto no Banco

de Dados

1) Crie a classe Cliente com as propriedades necessários e gere os métodos gets and sets; 2) Faça as anotações conforme mostra a imagem.

import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id;

public class Cliente implements Serializable { @Id

@GeneratedValue(strategy=GenerationType.IDENTITY) private Long codigo;

private String nome; private Integer idade; private String sexo;

private String profissao; gets e sets....

construtor sem parâmetro... }

(17)

Salvando o primeiro objeto no Banco

de Dados

1) Crie a classe Principal do sistema com o seguinte método main public class Principal {

public static void main(String[] args) { EntityManagerFactory emf =

Persistence.createEntityManagerFactory("cadastro01PU"); EntityManager em = emf.createEntityManager();

EntityManager em = emf.createEntityManager(); Cliente cliente = new Cliente();

cliente.setNome("Tião Jeferson"); cliente.setIdade(20); cliente.setProfissao("Estudante"); cliente.setSexo("M"); em.getTransaction().begin(); em.persist(cliente); em.getTransaction().commit(); }

(18)

Consultando o primeiro objeto no

Banco de Dados

1) Insira o código abaixo no final do método main public class Principal {

public static void main(String[] args) { ....

//---Cliente retorno = em.find(//---Cliente.class, 3L); Cliente retorno = em.find(Cliente.class, 3L);

if (retorno != null) {

System.out.println("Nome: " + retorno.getNome()); System.out.println("Idade: " + retorno.getIdade()); } else {

System.out.println("Cliente não encontrado."); }

(19)

Removendo o primeiro objeto no

Banco de Dados

1) Insira o código abaixo no final do método main public class Principal {

public static void main(String[] args) { ....

//---Cliente cliente = em.find(//---Cliente.class, 2L);

Funciona??

Cliente cliente = Cliente(); cliente.setCodigo(2);

Erro: Not detached

Cliente cliente = em.find(Cliente.class, 2L); em.getTransaction().begin();

em.remove(cliente);

em.getTransaction().commit();

System.out.println("Objeto removido com sucesso!"); }

(20)

Atualizando o primeiro objeto no

Banco de Dados

1) Insira o código abaixo no final do método main public class Principal {

public static void main(String[] args) { ....

//---Cliente retorno = em.find(//---Cliente.class, 3L); Cliente retorno = em.find(Cliente.class, 3L);

if (retorno != null) {

em.getTransaction().begin();

retorno.setNome(“Tião da Silva”); em.getTransaction().commit(); } else {

System.out.println("Cliente não encontrado."); }

(21)

Exercício

1) Fazendo seu primeiro CRUD

a) Crie um modelo como o mostrado na classe abaixo.

Dica: Para o mapeamento utilize @Temporal(TemporalType.TIMESTAMP) para o atributo do tipo data (java.util.Date).

b) Crie uma classe chamada CrudAgenda que deve ter os seguintes métodos: Salvar, Consultar, Atualizar e Remover.

(22)

Entendendo um pouco mais da

transação

Double valorTransferencia = entrada.nextDouble(); Double valorTransferencia = entrada.nextDouble(); em.getTransaction().begin();

conta1.setSaldo(conta1.getSaldo() - valorTransferencia); conta2.setSaldo(conta2.getSaldo() + valorTransferencia); if (conta1.getSaldo() > 0) {

em.getTransaction().commit();

System.out.println("Transferência realizada com sucesso!"); }

else {

em.getTransaction().rollback();

System.err.println("Transferência não realizada, saldo insuficiente!"); }

(23)

A Java Persistence Query Language

(JPQL)

(24)

Primeiro contato com o JPQL

1) Insira o código abaixo no final do método main public class Principal {

public static void main(String[] args) { ....

//---List<Cliente> clientes =

List<Cliente> clientes =

em.createQuery("from Cliente where sexo = 'M'", Cliente.class) .getResultList(); for (Cliente cliente : clientes) {

System.out.println("Código: " + cliente.getCodigo()); System.out.println("Nome: " + cliente.getNome()); System.out.println("Sexo: " + cliente.getSexo()); System.out.println("---"); } }

(25)

Fechando o Entity Manager

1) Quanto você fecha o EntityManager todos os objetos não são mais gerenciados. public class Principal {

public static void main(String[] args) {

EntityManagerFactory emf = Persistence.createEntityManagerFactory("exemploPU"); EntityManager em = emf.createEntityManager();

Cliente cliente = new Cliente(); cliente.setNome(“Tião"); em.getTransaction().begin(); em.persist(cliente); em.getTransaction().commit(); em.close(); em = emf.createEntityManager(); em.merge(cliente);

//<agora você pode trabalhar com o cliente pois ele volta a ser gerenciado>

(26)
(27)
(28)

Cadastrando o primeiro objeto

(29)

Fabricante - Modelo

import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @Entity @Entity

public class Fabricante {

@Id

@GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name=“id”)

private Long codigo; private String nome; //gerar os gets e o sets }

(30)
(31)

Fabricante - Modelo

Implemente os métodos equals() e hashcode()!

(32)

Fabricante - DAO

public class FabricanteDAO implements Serializable { private EntityManager em;

public void salvar(Fabricante fabricante) { //não esqueça de criar o em!

em.getTransaction().begin(); em.persist(fabricante);

em.persist(fabricante);

em.getTransaction().commit(); } public List<Fabricante> buscarTodos() {

return em.createQuery("from Fabricante").getResultList(); } public void excluir(Fabricante fabricante) throws NegocioException {

Fabricante fabricanteTemp = em.find(Fabricante.class, fabricante.getCodigo()); //inicie e confirme a transação!

em.remove(fabricanteTemp);

em.flush(); //executa a instrução nesse momento. } }

(33)

Fabricante - DAO

public class FabricanteDAO implements Serializable { ....

public Fabricante buscarPeloCodigo(Long codigo) { return em.find(Fabricante.class, codigo);

} }}

(34)

Fabricante - Service

public class CadastroFabricanteService implements Serializable { private FabricanteDAO fabricanteDAO;

public void salvar(Fabricante fabricante) throws NegocioException { //instancie o fabricanteDAO!

//instancie o fabricanteDAO!

if (fabricante.getNome() == null || fabricante.getNome().trim().equals("")) { throw new NegocioException("O nome do fabricante é obrigatório"); }

this.fabricanteDAO.salvar(fabricante); }

(35)

Relacionamento Muitos-Para-Um

import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.ManyToOne; @Entity

public class ModeloCarro {

@Id

@GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name=“id”)

private Long codigo; private String descricao;

@ManyToOne

private Fabricante fabricante; //gerar os gets e o sets}

Você pode mudar o nome do relacionamento no banco de dados inserindo a anotação:

(36)
(37)

Relacionamento Muitos-Para-Muitos

@Entity

public class Carro {

@Id

@GeneratedValue(strategy=GenerationType.IDENTITY)

private Long codigo; private String placa; private String placa; private String cor; private String chassi;

private BigDecimal valorDiaria;

@ManyToOne

@JoinColumn(name="codigo_modelo")

private ModeloCarro modelo;

@ManyToMany

private List<Acessorio> acessorios; //gerar os gets e o sets

}

(38)

Relacionamento Muitos-Para-Muitos

Customizando o relacionamento

-"Name" irá definir o nome da tabela que faz o relacionamento.

-A propriedade "joinColumns" recebe um array de @JoinColumn, pois se

-A propriedade "joinColumns" recebe um array de @JoinColumn, pois se

tivermos um relacionamento com chaves compostas, teríamos que usar mais

de uma @JoinColumn.

-A propriedades "inverseJoinColumns", que também recebe um array de

@JoinColumn

irá configurar a propriedade no sentido inverso, ou seja para

Acessório.

(39)

Relacionamento Um-Para-Um

@Entity

@Table(name="apolice_seguro")

public class ApoliceSeguro {

@Id

@GeneratedValue(strategy=GenerationType.IDENTITY) @GeneratedValue(strategy=GenerationType.IDENTITY)

private Long codigo;

private BigDecimal valorFranquia; private Boolean protecaoTerceiro;

private Boolean protecaoCausasNaturais; private Boolean protecaoRoubo;

//gerar os gets e o sets }

(40)

Relacionamento Um-Para-Um

@Entity

public class Aluguel {

@Id

@GeneratedValue(strategy=GenerationType.IDENTITY) Optamos por não @GeneratedValue(strategy=GenerationType.IDENTITY)

private Long codigo;

private BigDecimal valorTotal;

@ManyToOne

@JoinColumn(name="codigo_carro")

private Carro carro;

@OneToOne(cascade=CascadeType.ALL)

@JoinColumn(name="codigo_apolice_seguro")

private ApoliceSeguro apoliceSeguro; //gerar os gets e o sets

}

Optamos por não construir um DAO para

Apólice, assim a classe Aluguel deve propagar

a operação para o relacionamento 1-to-1

(41)
(42)

Relacionamento Um-Para-Muitos

@Entity

public class Carro { ...

@OneToMany(mapedBy=“carro”)

private List<Aluguel> alugueis; ...

... }

Deve-se informar que o mapeamento foi

feito pela

propriedade “carro” na classe Aluguel

(43)

Inicialização Tardia (lazy-loading) e

Ansiosa (eager-loading)

• Eager-loading – ao carregar os dados de um carro, todos os

acessórios também serão recuperados.

@ManyToMany(fetch=FetchType.EAGER)

private List<Acessorio> acessorios;

Lazy-loading – carregue os acessórios somente quando

Lazy-loading – carregue os acessórios somente quando

precisar, ou seja, quando chamar o “getAcessorios”

@ManyToMany(fetch=FetchType.LAZY)

(44)

Mapeando enumerações

public enumCategoria {

HATCH_COMPACTO, HATCH_MEDIO, SEDAN_COMPACTO, SEDAN_MEDIO, SEDAN_GRANDE, MINIVAN, ESPORTIVO, UTILITARIO_COMERCIAL }

@Entity

public class ModeloCarro { public class ModeloCarro {

@Id

@GeneratedValue(strategy=GenerationType.IDENTITY)

private Long codigo; private String descricao;

@ManyToOne

@JoinColumn(name="codigo_fabricante")

private Fabricante fabricante;

@Enumerated(EnumType.STRING) ou (EnumType.ORDINAL)

private Categoria categoria \\ gets e sets...}

(45)

Mapeando datas

@Entity

public class Aluguel {

@GeneratedValue(strategy=GenerationType.IDENTITY)

...

@Temporal(TemporalType.DATE)

private Calendar dataPedido;

@Temporal(TemporalType.TIMESTAMP) @Temporal(TemporalType.TIMESTAMP)

private Date dataEntrega;

@Temporal(TemporalType.TIMESTAMP)

private Date dataDevolucao; ...

(46)

Mapeando herança com tabela única

@Entity

@Inheritance(strategy=InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name="TIPO_PESSOA“,

discriminatorType=DiscriminatorType.STRING)

public abstract class Pessoa {

@Id

@GeneratedValue(strategy=GenerationType.IDENTITY)

private Long codigo; private Long codigo; private String nome;

@Temporal(TemporalType.DATE)

private Date dataNascimento; private String cpf

\\ gets e sets... }

(47)

Mapeando herança com tabela única

@Entity

@DiscriminatorValue(“MOTORISTA“)

public Motorista extends Pessoa { private String numeroCNH;

public String getNumeroCNH() { return numeroCNH;

return numeroCNH; }

public void setNumeroCNH(String numeroCNH) { this.numeroCNH = numeroCNH;

} }

(48)

Mapeando herança com Join

@Entity

@Inheritance(strategy=InheritanceType.JOINED) @DiscriminatorColumn(name="TIPO_PESSOA“,

discriminatorType=DiscriminatorType.INTEGER)

public abstract class Pessoa { ...

}

@Entity

@DiscriminatorValue("1")

public class Motorista extends Pessoa { ...

}

- Nesta estratégia cada entidade terá sua própria tabela.

- A tabela "pessoa" tem código, cpf, data_nascimento e nome. A tabela "motorista" tem o numeroCNH e um código.

- Essa opção pode deixar a manipulação mais lenta, pois as instruções são mais complexas para o JPA gerenciar.

(49)

Introdução a Java Persistence Query

Language (JPQL)

(50)

Introdução a Java Persistence Query

Language (JPQL)

public void static main (String[] args) { ....

EntityManager em = emf.createEntityManager(); List<String> nomesDosFabricantes =

em.createQuery("select f.nome from Fabricante f", String.class) .getResultList(); for (String nome : nomesDosFabricantes) { System.out.println("Nome: " + nome); } for (String nome : nomesDosFabricantes) { System.out.println("Nome: " + nome); } List<Fabricantes> fabricantes =

em.createQuery("from Fabricante where codigo > 4", Fabricante.class) .getResultList(); for (Fabricante f : fabricantes) { System.out.println("Nome: " + f.getNome() ); }

(51)

Selecionando uma entidade de uma

entidade

public void static main (String[] args) { ....

// Consulta fabricantes pelo modelo do carro

List<String> nomesDosFabricantes =

em.createQuery(“select mc.fabricante.nome from ModeloCarro mc",

String.class) .getResultList(); for (String nome : nomesDosFabricantes) { System.out.println("Nome: " + nome); } for (String nome : nomesDosFabricantes) { System.out.println("Nome: " + nome); } }

(52)

Filtrando resultados

public void static main (String[] args) { ....

// Consulta modelos filtrados por um determinado fabricante

List<String> nomesDosModelos =

em.createQuery(“select mc.descricao from ModeloCarro mc “+

“where mc.fabricante.nome = ‘Honda’“, String.class) .getResultList(); for (String nome : nomesDosModelos) { System.out.println("Nome: " + nome); }

for (String nome : nomesDosModelos) { System.out.println("Nome: " + nome); }

// Consulta os modelos, de um fabricante que pertença a algumas categorias específicas

List<String> nomesDosModelos =

em.createQuery(“select mc.descricao from ModeloCarro mc “+ “where mc.fabricante.nome = ‘Honda’ and“+

“mc.categoria in (‘MINIVAN,’ESPORTIVO’) “, String.class) .getResultList(); for (String nome : nomesDosModelos) { System.out.println("Nome: " + nome); }

(53)

Filtrando resultados

public void static main (String[] args) { ....

// Uso do like

// Consulta os modelos, de um fabricante que pertença a algumas categorias específicas

List<String> nomesDosModelos =

em.createQuery(“select mc.descricao from ModeloCarro mc “+ “where mc.fabricante.nome = ‘Honda’ and“+

“mc.categoria like ‘HATCH%’“, String.class) .getResultList(); “mc.categoria like ‘HATCH%’“, String.class) .getResultList(); for (String nome : nomesDosModelos) { System.out.println("Nome: " + nome); } }

(54)

Trabalhando com projeções

public void static main (String[] args) { ....

// Consulta somente a descrição dos modelos de carros

List<Object[]> resultados =

Estamos usando o método com um parâmetro

List<Object[]> resultados =

em.createQuery(“select mc.descricao, mc.categoria from ModeloCarro mc“) .getResultList();

for (Object[] obj : resultados) { System.out.println(obj[0]+" " + obj[1]); } }

Estamos buscamos Estamos buscamos

apenas alguns campos do objeto

(55)

Fazendo Join entre entidades

public void static main (String[] args) { ....

// Dado um modelos de carro vamos buscar todos os acessórios vinculados a eles // Tabelas: ModeloDeCarros >> Carros >> Acessorios (n-to-n)

List<String> acessorios =

em.createQuery(“select a.descricao from Carro c “+ “JOIN c.acessorios a “+

“where c.modelo.descricao = ‘Cruze’ “, “where c.modelo.descricao = ‘Cruze’ “, String.class) .getResultList();

for (String acessorio : acessorios) { System.out.println(" Acessorio: " + acessorio); } }

(56)

Queries agregadas

public void static main (String[] args) { ....

// Recuperar o maior valor, a qtde e a média de alugueis // para os carros com mais de um aluguel

List<Object[]> acessorios =

em.createQuery(“select c, count(a), max(a.valorTotal), avg(a.valorTotal) “+ “from Carro c JOIN c.alugueis a “+

“group by c “+ “group by c “+

“having count(a) > 1”) .getResultList(); for (Object[] obj : resultados) {

System.out.println( ((Carro)obj[0]).getModelo().getDescricao() +" " + obj[1]) +" " +

obj[2]) +" " + obj[1]); }

(57)

Novos tipos de retorno

Vamos melhorar o tipo de retorno do slide anterior criando um

novo objeto na hora da consulta com os valores do select.

Cria a classe abaixo dentro de um pacote chamado “info”.

public class AluguelCarroInfo { private Carro carro;

private Long totalAlugueis; private Long totalAlugueis;

private BigDecimal valorMaximo; private BigDecimal valorMedio;

public AluguelCarroInfo(Carro carro, Long totalAlugueis, Number valorMaximo, Number valorMedio) {

this.carro = carro;

this.totalAlugueis = totalAlugueis;

this.valorMaximo = BigDecimal.valueOf(valorMaximo.doubleValue()); this.valorMedio = BigDecimal.valueOf(valorMedio.doubleValue()); } //omitido os gets e sets dos métodos

(58)

Queries agregadas e tipos de retorno

public void static main (String[] args) { ....

// Recuperar o maior valor, a qtde e a média de alugueis // para os carros com mais de um aluguel

List< AluguelCarroInfo> resultados =

em.createQuery(“select NEW br.ifmg.modelo.AluguelCarroInfo “+ “( c, count(a), max(a.valorTotal), avg(a.valorTotal) )“+ “from Carro c JOIN c.alugueis a “+

“from Carro c JOIN c.alugueis a “+ “group by c “+

“having count(a) > 1”) .getResultList(); for (AluguelCarroInfo aci : resultados) {

System.out.println("Modelo: " + aci.getCarro().getModelo().getDescricao()); System.out.println("Quantidade de alugueis: " + aci.getTotalAlugueis());

System.out.println("Valor máximo: " + aci.getValorMaximo());

System.out.println("Valor médio: " + aci.getValorMedio()); System.out.println(); }

(59)

Passando parâmetros para queries

public void static main (String[] args) { ....

// Recuperar os modelos de carros para um determinado nome de fabricante

String modelo = JOptionPane.showInputDialog(null,”Entre com o nome do fabricante.”); String jpql = "select mc.descricao from ModeloCarro mc " +

"where mc.fabricante.nome = :modelo"; List<String> modelos = em.createQuery(jpql, String.class)

.setParameter("modelo", modelo) .getResultList();

for (String m : modelos) { System.out.println(m); } }

OBS: Existe uma outra maneira de passagem de parâmetro:

-Ao invés de dar nomes para os parâmetro, você pode usar o caracter ‘?’ mais um número de identificação. Ex: where (codigo = ?1) and (cep = ?2). -Para informar os valores use o método setParameter da seguinte forma: .setParameter(1, 1000).setParameter(2, “3550-000”)

(60)

Passando parâmetros para queries

(Datas)

public void static main (String[] args) { ....

// Recuperar quantos alugueis foram feitos em um determinado período

String jpql = "select count(a) from Aluguel a " +

"where a.dataDevolucao BETWEEN :inicio AND :fim"; Calendar inicioCalendar = Calendar.getInstance();

inicioCalendar.set(2013, 0, 28, 7, 0); // 24 de Janeiro de 2013 7:00 horas

inicioCalendar.set(2013, 0, 28, 7, 0); // 24 de Janeiro de 2013 7:00 horas

Date inicio = inicioCalendar.getTime();

Calendar fimCalendar = Calendar.getInstance();

fimCalendar.set(2013, 11, 30, 18, 0); // 25 de Dezembro de 2013 18:00 horas

Date fim = fimCalendar.getTime();

Long quantidade = em.createQuery(jpql, Long.class)

.setParameter("inicio", inicio, TemporalType.TIMESTAMP) .setParameter(“fim", fim, TemporalType.TIMESTAMP) .getSingleResult();

System.out.println("Quantidade de devoluções: " + quantidade); }

(61)

Named Query

São consultas JPQL prontas que recebem nomes únicos.

Elas são definidas nas classes de modelos.

@Entity

@NamedQueries({

@NamedQuery(name="buscarTodosCarros", query="select c from Carro c"), @NamedQuery(name="buscarCarroComAcessorios",

query="select c from Carro c JOIN c.acessorios a " + query="select c from Carro c JOIN c.acessorios a " +

" where c.codigo = :codigo") })

public class Carro { ... }

public void static main (String[] args) { ....

// Recuperar todos os carros

List< Carro> resultados = em.createNamedQuery(“buscarTodosCarros").getResultList();

// Recuperar os acessórios de um determinado carros

Carro car = em.createNamedQuery(“buscarCarroComAcessorios", Carro.class) .setParameter("codigo", codigo) .getSingleResult();

(62)

Named Queries em arquivos externos

1. Crie o arquivo com as Named Queries:

<?xmlversion="1.0" encoding="UTF-8"?>

<entity-mappingsxmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm

http://xmlns.jcp.org/xml/ns/persistence/orm_2_1.xsd"

version="2.1">

<named-queryname="Lancamento.descricoesQueContem"> <named-queryname="Lancamento.descricoesQueContem">

<query>

SELECT distinct descricao FROM Lancamento WHERE upper(descricao) like upper(:descricao) </query>

</named-query>

<named-queryname="Lancamento.todos"> <query> FROM Lancamento l </query> </named-query> </entity-mappings>

(63)

Named Queries em arquivos externos

2. Indique no “persistence.xml” aonde estão salvos os arquivos:

<persistence-unit name="financeiroPU" transaction-type="RESOURCE_LOCAL"> <mapping-file>META-INF/consultas/pessoas.xml</mapping-file>

<mapping-file>META-INF/consultas/lancamentos.xml</mapping-file> ...

3. Utilize as Named Queries normalmente:

...

return em.createNamedQuery("Lancamento.descricoesQueContem", String.class) .setParameter("descricao", "%água%")

(64)
(65)

Exercício - Movendo os objetos pelo

ciclo de vida

criar um objeto, para o EntityManager ele estará no estado "new“.

passar o objeto para o estado "managed“ (métodos persit ou merge).

O objeto foi salvo, mas continua no estado "managed“, vamos desconectar

esse objeto do EntityManager.

(66)

Exercício - Movendo os objetos pelo

ciclo de vida

(67)

Exercício - Movendo os objetos pelo

ciclo de vida

Colocar o objeto gerenciado novamente (método merge find)

(68)

Exercício - Movendo os objetos pelo

ciclo de vida

Reconectar o objeto removido com o método merge. Repare um detalhe

muito importante desse método: ele devolve um outro objeto!

Isso significa que se você fizer a alteração no cliente1, nada será alterado no

banco de dados! Agora, se fizer as alterações no objeto retornado, as

alterações irão para o banco. Veja o código abaixo:

(69)

Ciclo de vida e Estados dos objetos

Chamando funções de Callback

@Entity

public class Carro { ....

@Temporal(TemporalType.TIMESTAMP)

private Date dataCriacao; private Date dataCriacao;

@Temporal(TemporalType.TIMESTAMP)

private Date dataModificacao;

@PrePersist @PreUpdate

public void configuraDatasCriacaoAlteracao() { this.dataModificacao = new Date();

if (this.dataCriacao == null) {

this.dataCriacao = new Date(); } }

//gerar os gets e o sets para essas duas propriedades }

(70)

Criteria - básico

public static void main(String[] args) { ...

// JPQL: from Cliente

CriteriaBuilder builder = em.getCriteriaBuilder();

CriteriaQuery<Cliente> criteriaQuery = builder.createQuery(Cliente.class); criteriaQuery.from(Cliente.class);

List<Cliente> = em.createQuery(criteriaQuery).getResultList(); for (Cliente cliente : clientes) {

System.out.println("Código: " + cliente.getCodigo()); System.out.println("Nome: " + cliente.getNome()); } ....

(71)

Criteria - básico

public static void main(String[] args) { ...

// JPQL: select c from Cliente where c.nome like = 'Fernando%'

CriteriaBuilder builder = em.getCriteriaBuilder();

CriteriaQuery<Cliente> criteriaQuery = builder.createQuery(Cliente.class); Root<Cliente> c = criteriaQuery.from(Cliente.class);

criteriaQuery.select(c); criteriaQuery.select(c);

criteriaQuery.where( builder.like(c.<String>get("nome"), "Fernando%") ); List<Cliente> = em.createQuery(criteriaQuery).getResultList();

for (Cliente cliente : clientes) {

System.out.println("Código: " + cliente.getCodigo()); System.out.println("Nome: " + cliente.getNome()); } ....

(72)

Gravação em cascata

Se tentarmos incluir um carro com um modelo novo, ou seja, ainda

não persistido. O JPA retornaria um erro. Para que isso funcione

temos que configurar o “cascate” do relacionamento entre

carro/modelo.

public class Carro { public class Carro { ....

@ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.MERGE) @JoinColumn(name="codigo_modelo")

private ModeloCarro modelo; ....

(73)

Exclusão em cascata

Se quisermos apagar um carro que tenha alugueis feitos. Ou seja,

fazer a exclusão em cascata com relacionamentos n-to-n

@Entity

public class Carro { ....

....

@ManyToOne

@JoinColumn(name="codigo_modelo")

private ModeloCarro modelo;

@OneToMany(mapedby=“carro”, cascade=CascadeType.REMOVE)

private List<Aluguel> alugueis; ...

(74)

Exclusão de objetos órfãos

Se quisermos apagar um determinado aluguel diretamente na

entidade carro. Exemplo:

public static void main(String[] args) { ...

Carro car1 = em.find(Carro.class, 1L);

Nesse caso, a exclusão não aconteceria, pois a configuração feita no slide anterior só acontece quando

public class Carro {

.... // Para excluir objetos órfãos existe uma anotação própria

@OneToMany(mapedby=“carro”, cascade=CascadeType.PERSIST, orphanRemoval=true)

private List<Aluguel> alugueis; ... } em.getTransaction().begin(); car1.getAlugueis().remove(0); em.getTransaction().commit(); .... }

anterior só acontece quando excluímos toda a entidade,

aqui, o objeto do

(75)

Mapeando chaves compostas

Exemplo: para identificar um veículo unicamente é necessário o

número da placa e a cidade.

1. Crie uma classe com os campos da chave composta.

@Embeddable

public class VeiculoID implements Serializable{ public class VeiculoID implements Serializable{ private String placa;

private String cidade; public VeiculoId() { }

...

(76)

Mapeando chaves compostas

2. Crie a classe que tem a chave composta.

@Entity

public class Veiculo implements Serializable{

@EmbeddedId

private VeiculoId codigo; private VeiculoId codigo; private String fabricante; private String modelo; public Veiculo() {

} ...

(77)

Mapeando chaves compostas

3. Inserindo um objeto com chave composta.

public class ExemploChaveComposta { public static void main(String[] args) {

...

Veiculo veiculo = new Veiculo(); Veiculo veiculo = new Veiculo();

veiculo.setCodigo(new VeiculoId("ABC-1235", "Ouro Preto")); veiculo.setFabricante("Volks"); veiculo.setModelo("Gol"); em.getTransaction().begin(); em.persist(veiculo); em.getTransaction().commit(); em.close(); } }

(78)

Mapeando chaves compostas

3. Pesquisando um objeto com chave composta.

public class ExemploChaveComposta { public static void main(String[] args) {

...

VeiculoId codigo = new VeiculoId("ABC-1234", "Rio Claro"); Veiculo v = em.find(Veiculo.class, codigo);

System.out.println("Veiculo " + v.getCodigo().getPlaca() + " - " + v.getCodigo().getCidade() + " - Fabricante: " + v.getFabricante()); em.close(); } }

(79)

Mapeando objetos embutidos

Talvez, você opte por criar uma tabela grande, ao invés de usar

joins, mas ainda deseja separar os objetos seguindo os princípios de

orientação a objetos.

Exemplo: teremos uma classe chamada Proprietário que estará

dentro da classe Veiculo (criada no slide anterior)

@Embeddable @Embeddable

public class Proprietario implements Serializable{ ....

@Column(name="nome_proprietario")

private String nome; private String telefone; private String email; public Proprietario() { }

...

(80)

Mapeando objetos embutidos

@Entity

public class Veiculo implements Serializable{ ....

@Embedded

private Proprietario proprietario; ...

} //crie o get e set

public class ExemploChaveComposta { public static void main(String[] args) {

...

Veiculo veiculo = new Veiculo();

veiculo.setCodigo(new VeiculoId("ABC-1223", “Belo Horizonte")); veiculo.setFabricante("Volks");

veiculo.setModelo("Gol");

veiculo.setProprietario(new Proprietario(“João”, ”123-9876”, ”john@hit.com”) ); em.getTransaction().begin();

em.persist(veiculo);

(81)

Propriedades transientes

Informar que uma propriedade ou método não seja mapeando para

o banco de dados.

Exemplo: criar um método “getInfo” que retorne os dados do

objeto imitando o toString.

@Entity @Entity

public class Veiculo implements Serializable{ ...

@Transient

Public String getInfo() {

return "Placa: " + getCodigo().getPlaca() + ". Fabricante: " + getFabricante() + ". Modelo: " + getModelo();

} ... }

(82)

Coleções de tipos básicos

Podemos simular uma entidade fraca através de uma lista. Assim o

mapeamento pode ser feito da seguinte forma:

@Entity

A entidade fraca terá a chave estrangeira chamada

‘cod_proprietario’ e o campo ‘numero_telefone’ @Entity

public class Proprietario implements Serializable{ ...

@ElementCollection

@CollectionTable(name="proprietario_telefones",

joinColumns=@JoinColumn(name="cod_proprietario")) @Column(name="numero_telefone")

private List<String> telefones = new ArrayList<>(); ...

} //crie os gets e sets, além do equal e o hashcode e um construtor sem parâmetro

(83)

Coleções de tipos básicos

Cadastro e consulta

public class ExemploColecoes {

public static void main(String[] args) { ...

em.getTransaction().begin();

Proprietario proprietario = new Proprietario(); proprietario.setNome("João"); proprietario.getTelefones().add("(34) 1234-5678"); proprietario.getTelefones().add("(34) 1234-5678"); proprietario.getTelefones().add("(11) 9876-5432"); em.persist(proprietario); em.getTransaction().commit();

Proprietario proprietario = em.find(Proprietario.class, 1L); System.out.println("Nome: " + proprietario.getNome()); for (String telefone : proprietario.getTelefones()) {

System.out.println("Telefone: " + telefone); }

em.close(); } }

(84)

Coleções com objetos embutidos

@Embeddable

public class Telefone implements Serializable{ ...

private String prefixo; private String numero; private String ramal; ...

} //crie os gets e sets, além do equal e o hashcode e um construtor sem parâmetro

Entidade fraca

public class Proprietario implements Serializable{ ... @ElementCollection @CollectionTable(name="proprietario_telefones", joinColumns=@JoinColumn(name="cod_proprietario")) @AttributeOverrides({@AttributeOverride(name="numero", column=@Column(name="num_telefone"))})

private List<Telefone> telefones = new ArrayList<>(); ...

} //crie os gets e sets, além do equal e o hashcode e um construtor sem parâmetro

Configura a chave estrangeira da entidade fraca e o nome de

uma coluna

(85)

Coleções com objetos embutidos

Cadastro e consulta

public class ExemploColecoesDeEntidades { public static void main(String[] args) {

...

em.getTransaction().begin();

Proprietario proprietario = new Proprietario(); proprietario.setNome("João"); proprietario.getTelefones().add(new Telefone("34", "1234-5678", "104")); proprietario.getTelefones().add(new Telefone("34", "1234-5678", "104")); proprietario.getTelefones().add(new Telefone("33", “4321-5678", "")); em.persist(proprietario); em.getTransaction().commit();

Proprietario proprietario = em.find(Proprietario.class, 1L); System.out.println("Nome: " + proprietario.getNome()); for (Telefone tel : proprietario.getTelefones()) {

System.out.println("Telefone: " + tel.getPrefixo() + “ “ + tel.getNumero() ); }

em.close(); } }

(86)

Objetos grandes

public class Carro { ....

@Lob

private byte[] foto;

.... } //get and set para a propriedade foto

Para salvar uma imagem no banco de dados basta mapear uma

propriedade como Lob (large object):

.... } //get and set para a propriedade foto

public class CarroDAO { ....

public byte[] imagemEmArray(String pathImage) throws IOException{ BufferedImage imagem = ImageIO.read(new File(pathImage)); ByteArrayOutputStream baos = new ByteArrayOutputStream();

ImageIO.write(imagem, "png", baos); return baos.toByteArray();}

.... }

(87)

Objetos grandes

public class CarroDAO { ....

public ImageIcon buscaFoto(Long codigo) throws IOException { Carro carro = em.find(Carro.class, codigo);

if (carro.getFoto() != null) {

BufferedImage img = ImageIO.read(new ByteArrayInputStream(carro.getFoto()));

Para exibir uma imagem, converta o array de bytes em uma imagem

BufferedImage img = ImageIO.read(new ByteArrayInputStream(carro.getFoto())); return new ImageIcon(img);

} else

return null; }

.... }

Use o objeto ImageIcon como desejar:

public static void main(String[] args) {

... JOptionPane.showMessageDialog(null, new JLabel( carroDAO.buscaFoto(3L) ));... }

(88)

Mais detalhes de @Column

@Entity

public class Aluguel { ... @Column(name=”dtPedido”, nullable=true, unique=false, insertable=true, insertable=true, updatable=true)

private Calendar dataPedido;

@Column(lenght=100)

private String nome ...

(89)

Problema n+1

Lembre-se que a propriedade ‘ModeloCarro’ é FetchType.LAZY na

entidade carro. Agora imagine os passos abaixo:

– Ao executar um query (‘createquery’ ), uma consulta é feita.

– Mas para cada chamada do método ‘getModeloCarro’, mais uma consulta é executada! Isso não é eficiente!!

Exemplo:

Exemplo:

List<Carro> carros = em.createQuery("from Carro", Carro.class).getResultList(); for (Carro carro : carros) {

System.out.println(carro.getPlaca() + " - " +

carro.getModeloCarro().getDescricao()); }

(90)

Problema n+1

Observe as consultas para dois

carros cadastros no BD:

(91)

Problema n+1 - Resolvido

List<Carro> carros =

em.createQuery("from Carro c inner join fetch c.modeloCarro",

Carro.class).getResultList(); for (Carro carro : carros) {

System.out.println(carro.getPlaca() + " - " +

carro.getModeloCarro().getDescricao()); carro.getModeloCarro().getDescricao()); }

(92)

Cache de primeiro nível

Cache padrão – enquanto não fechar o EntityManager os dados

ficam armazenados em memória.

List<Carro> carros = em.createQuery("from Carro", Carro.class).getResultList(); for (Carro carro : carros)

for (Carro carro : carros)

System.out.println(carro.getPlaca() ); System.out.println("---"); Carro carro = em.find(Carro.class, 3L);

System.out.println(carro.getCodigo());

(93)

Cache de primeiro nível

Quanto o EntityManager for fechado o cache é limpo

List<Carro> carros =

em.createQuery("from Carro", Carro.class).

getResultList(); for (Carro carro : carros)

for (Carro carro : carros)

System.out.println(carro.getPlaca() ); em.close();

System.out.println("---"); em = FabricaEntity.getEntityManager(); Carro carro = em.find(Carro.class, 3L); System.out.println(carro.getCodigo());

(94)

Consultas nativas

....

List<Carro> carros =

em.createNativeQuery("select * from Carro", Carro.class). getResultList();

Usado para consultas que não podem ser representadas pela JPQL e

Criteria. Deve ser evitado pois não representam o mundo OO.

em.createNativeQuery("select * from Carro", Carro.class). getResultList(); for (Carro carro : carros) {

System.out.println(carro.getPlaca() ); }

(95)
(96)
(97)

Tipos de cache do Hibernate

(98)

Tipos de cache do Hibernate

Coloca os objetos na memória RAM independente do EntityManager

Cache de 2º nível e de query

Existem pacotes para gerenciar o cache de forma

Para habilitar o cache de 2º nível no hibernate, basta configurar o

percistence.xml:

<property name="hibernate.cache.use_second_level_cache" value="true"/> <property name="hibernate.cache.region.factory_class"

value="org.hibernate.testing.cache.CachingRegionFactory"/>

cache de forma mais profissional.

(99)

Tipos de cache do Hibernate

Exemplo: .... @Entity @Table(name = "cidade") @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)

public class Cidade implements Serializable { public class Cidade implements Serializable { ...

}

@Entity

@Table(name = “estado")

@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)

public class Estado implements Serializable { ...

}

NONSTRICT_READ_WRITE – atualizações feitas eventualmente READ _ONLY – não haverá atualizações

(100)

O pattern DAO

(101)

Criando um DAO Genérico

public interface GenericDAO<T, ID extends Serializable> { public T buscarPeloCodigo(ID id);

public void salvar(T entidade); }

import java.lang.reflect.ParameterizedType;

1º Passo) Criar uma interface:

2º Passo) Criar uma classe que implemente a interface do Passo 1: import java.lang.reflect.ParameterizedType;

public class HibernateGenericDAO<T, ID extends Serializable> implements GenericDAO<T, ID> { private EntityManager em;

private Class<T> classeEntidade; public HibernateGenericDAO() {

em = FabricaEntity.getEntityManager();

this.classeEntidade = (Class<T>) ((ParameterizedType)

getClass().getGenericSuperclass()) .getActualTypeArguments()[0]; }

(102)

Criando um DAO Genérico

...

@Override

public T buscarPeloCodigo(ID id) { return em.find(classeEntidade, id); }

@Override

public void salvar(T entidade) { public void salvar(T entidade) {

em.getTransaction().begin(); em.merge(entidade);

em.getTransaction().commit(); }

protected EntityManager getEntityManager() { return em;

} }

(103)

Criando um DAO Genérico

public class PedidoDAO extends HibernateGenericDAO<Pedido, Long> implements

Serializable { public List<ValorTotalVendaDoDia> buscarValorTotalVendaDoDia() {

return getEntityManager().createQuery("select "

+ "NEW ifmg.ValorTotalVendaDoDia(p.dataVenda, sum(p.valorTotal)) " +

3º Passo) Crie uma classe que estende HibernateGenericDAO:

+ "NEW ifmg.ValorTotalVendaDoDia(p.dataVenda, sum(p.valorTotal)) " + "from Pedido p " +

"group by p.dataVenda", ValorTotalVendaDoDia.class) .getResultList(); }

}

4º Passo) Use a classe genérica à vontade:

PedidoDAO pedDAO = new PedidoDAO(); pedDAO. Salvar(pedido);

(104)

Trabalhando com procedures

create table pedido (

codigo bigint primary key auto_increment, valor decimal(10,2),

status varchar(50) );

create table devolucao (

codigo bigint primary key auto_increment, codigo bigint primary key auto_increment, codigo_pedido bigint,

status varchar(50) );

create table entrega (

codigo bigint primary key auto_increment, codigo_pedido bigint,

previsao date );

(105)

Trabalhando com procedures

DELIMITER $$

CREATE PROCEDURE analisar (vCodigo bigint, OUT vAnalise varchar(50)) BEGIN

DECLARE vStatus varchar(50);

select status into vStatus from pedido where codigo = vCodigo; START TRANSACTION;

START TRANSACTION;

if vStatus = 'CANCELADO' then

insert into devolucao (codigo_pedido, status) values (vCodigo, 'PENDENTE'); set vAnalise = 'DEVOLUCAO';

elseif vStatus = 'APROVADO' then

insert into entrega (codigo_pedido, previsao) values (vCodigo, now()); set vAnalise = 'ENTREGA';

end if;

COMMIT; END $$

(106)

Trabalhando com procedures

public static void main(String[] args) { ....

StoredProcedureQuery sp = em.createStoredProcedureQuery("analisar");

sp.registerStoredProcedureParameter(" vCodigo ", Long.class, ParameterMode.IN); sp.setParameter(" vCodigo ", 1L);

sp.registerStoredProcedureParameter("analise", String.class, ParameterMode.OUT); sp.execute();

String analise = (String) sp.getOutputParameterValue("analise"); System.out.println("A análise foi: " + analise);

(107)

Referências

Caelum - Java para Desenvolvimento Web – link:

https://www.caelum.com.br/apostila-java-web/

• Hébert Coelho - JPA Eficaz As melhores práticas

de persistência de dados em Java

Hébert Coelho - JPA Eficaz As melhores práticas

de persistência de dados em Java

• Normandes JPA e Hibernate além do básico

-um projeto completo – link:

Referências

Documentos relacionados

A PROVA DE REDAÇÃO compreende uma produção textual em um dos gêneros (comentários em blog, crônicas jornalísticas, narração escolar, relato autobiográfico) e tem por

milesi no período de 28 dias, em porcentagem...41 Tabela X: Siparuna guianensis: Capacidade dos Grupos (G) obtidos do fracionamento da fase hexânica do extrato etanólico da folha

• uma entidade adquirida possui uma patente de tecnologia. Ela tem licença de uso exclusivo fora dos Estados Unidos, em troca deste uso a entidade recebe um percentual

O Secretário Geral da OTM-CS fez este pronunciamento durante a cerimónia de abertura da IV Sessão Ordinária do Conselho Nacional do SNEB, realizada em finais de

O LAVI vem sendo montado gradativamente, com recursos provenientes do FDA (Fundo de Desenvolvimento Acadêmico) e LABGRAD (Programa de Apoio aos Laboratórios de

A jurisprudência do Supremo Tribunal Federal entende que, quando há deliberação de PEC que seja contrária a uma das chamadas “cláusulas pétreas” da Constituição Federal

Based on the theory that the muscle strength of elderly in- dividuals responds differently to an activity program, ac- cording to the presence or absence of a medical diagnosis

This retrospective study assessed early, clinical and X-ray outcomes using this technique and the total metal-on-metal resurfacing prosthesis3. MATERIALS