Prévia do material em texto
MODULO JAVA 2 BANCO DE DADOS 1 Sumário O que é banco de dados?..........................................................................3 Instalando e Configurando Ambiente......................................................5 Criando tabelas e suas características...................................................7 Criando Sequence.......................................................................................8 Criando Trigger...........................................................................................9 Comandos Padrões de DMLs.....................................................................9 Exercício.......................................................................................................9 Projeto JDBC Netbeans............................................................................10 DriverManager..........................................................................................11 PreparedStatement...................................................................................11 Exercício..................................................................................................12 JPA e Hibernate.........................................................................................12 ORM..........................................................................................................12 Porque usar ORM?.....................................................................................13 Java Persistence API (JPA)..........................................................................13 Hibernate..................................................................................................13 Criando um projeto java e incorporando JPA + Hibernate..............14 Criação do Domain Model.....................................................................17 PERSISTENCE.XML.................................................................................27 EntityManager e EntityManagerFactory............................................28 Persistindo.................................................................................................28 Consultando..............................................................................................29 Listar Dados..............................................................................................29 Atualizar dados.........................................................................................29 Remover Dados.........................................................................................30 Exercício..................................................................................................30 Design pattern Data Access Object (DAO)...........................................30 DAO: o intermediário entre os mundos.....................................................31 Abstração..................................................................................................31 Unificação do acesso a dados...................................................................31 DAO na prática..........................................................................................32 Exemplo de utilização...........................................................................33 Exercício..................................................................................................34 Referência...............................................................................................34 2 O que é banco de dados? Bancos de dados ou bases de dados, são conjuntos de arquivos relacionados entre si com registros sobre pessoas, lugares ou coisas. São coleções organizadas de dados que se relacionam de forma a criar algum sentido (Informação) e dar mais eficiência durante uma pesquisa ou estudo. Em banco de dados, utilizamos o SQL - Structured Query Language (Linguagem de Consulta Estruturada) É uma linguagem utilizada para banco de dados relacionais, baseada e inspirada em álgebra relacional. Utiliza como subconjuntos principais o DML, DDL, DCL, DTL e DQL. DDL – Data Definition Language (DDL) são usadas para definir a estrutura de banco de dados ou esquema. Alguns exemplos: CREATE- para criar objetos no banco de dados ALTER – altera a estrutura da base de dados TRUNCATE – remover todos os registros de uma tabela, incluindo todos os espaços alocados para os registros são removidos COMMENT – adicionar comentários ao dicionário de dados RENAME – para renomear um objeto DML – Data Manipulation Language (DML) são utilizados para o gerenciamento de dados dentro de objetos do banco. Alguns exemplos: SELECT- recuperar dados do banco de dados INSERT – inserir dados em uma tabela UPDATE – atualiza os dados existentes em uma tabela DELETE – exclui registros de uma tabela, CALL – chamar um subprograma PL / SQL EXPLAIN PLAN – explicar o caminho de acesso aos dados LOCK TABLE – controle de concorrência 3 DCL – Data Control Language (DCL) declarações. Alguns exemplos: GRANT – atribui privilégios de acesso do usuário a objetos do banco de dados REVOKE – remove os privilégios de acesso aos objetos obtidos com o comando GRANT TCL – Transaction Control Language – (Controle de Transações) são usados para gerenciar as mudanças feitas por instruções DML. Ele permite que as declarações a serem agrupadas em transações lógicas. COMMIT – salvar o trabalho feito SAVEPOINT – identificar um ponto em uma transação para que mais tarde você pode efetuar um ROLLBACK ROLLBACK – restaurar banco de dados ao original desde o último COMMIT Instalando e Configurando Ambiente Inicialmente temos que baixar o banco de dados Oracle Express e o SQLDeveloper: Oracle Express SQLDeveloper Oracle Express – Realizar a instalação normal, lembrando de colocar a senha do system com algo simples, tipo 12345. SQLDeveloper – Não é instalável, é necessário apenas descompactar e usar. Agora vamos para as configurações iniciais do banco de dados. 4 Com o SQLDeveloper aberto, pela primeira vez, deve ser criado uma nova conexão, com o usuário system, depois disso devemos criar um novo usuário que vamos chamar de fuctura. Para criar a conexão da system, seguimos como mostrado na imagem acima, cria um nome para a conexão System, nome do usuario system e senha 12345, as informações de acesso ao oracle, contiunuam as mesma como na imagem. Após, preenchimento dos dados, deve ser realizado o teste, no botão Testar, se estiver tudo correto a informação no campo status, vai aparecer Com Sucesso. Com a conexão criada, temos que criar um usuario para realizamos a criação de tabelas e seus dados. Na conexão system, navege ate a pasta “Outros Usuarios”, click com o botão direito e depois criar Usuário. 5 Inserir o nome do usuário “fuctura” e senha “fuctura”, depois, vai na aba “Atribuições Concedidas”, assim, deve clicar no botão “Conceder”, onde, vai selecionar toda a coluna de “Concedida”, depois, clica em aplicar. Com isso, vamos criar uma nova conexão, igual, como fazemos com o “system”, agora, passando o usuário “fuctura” e senha “fuctura”. Pronto finalizamos o acesso e a criação do novo ususario “fuctura”. 6 Criando tabelas e suas características Vamos entrar agora no usuario “fuctura”, e vamos utilizas as instruções DDL, para criar as tabelas de “ENDERECO”, “CONTA” e “PESSOA”. CREATE TABLE CONTA ( NUMERO NUMBER NOT NULL , DONO VARCHAR2(200) , LIMITE NUMBER , SALDO NUMBER NOT NULL , CONSTRAINT CONTA_PK PRIMARY KEY (NUMERO ) ENABLE ) CREATE TABLE ENDERECO ( ID_ENDERECO NUMBER NOT NULL , RUA VARCHAR2(200 BYTE) NOT NULL , NUMERO NUMBER NOT NULL , COMPLEMENTO VARCHAR2(4 BYTE) NOT NULL , CONSTRAINT ENDERECO_PK PRIMARY KEY ( ID_ENDERECO ) ENABLE ) CREATE TABLE PESSOA ( NOME VARCHAR2(200 BYTE) NOT NULL , IDADE NUMBER NOT NULL , SEXO VARCHAR2(2 BYTE) NOT NULL , CPF VARCHAR2(11 BYTE) NOT NULL , ID_ENDERECO NUMBER , NUMERO_CONTA NUMBER , CONSTRAINT PESSOA_PK PRIMARYKEY (CPF) ENABLE , CONSTRAINT CONTA_FK FOREIGN KEY (NUMERO_CONTA) REFERENCES CONTA (NUMERO) ENABLE , CONSTRAINT ENDERECO_FK FOREIGN KEY (ID_ENDERECO) REFERENCES ENDERECO (ID_ENDERECO) ENABLE ) Com as DDLs colocadas acima, criamos as nossas tabelas, lembrando que existe duas coisas importantes. 1 – Toda tabela criada deve ter por padrão um chave primaria “PRIMARY KEY”, que identifica cada registro da tabela, o tornando único. 2 – Na tabela “PESSOA”, alem da “PRIMARY KEY”, ela tem duas “FOREIGN KEY”, que são referências a chaves primarias de outras tabelas, criando uma ligação de consistencia de dados, simplificando, se os valores das colunas “ID_ENDERECO” e “NUMERO_CONTA”, estiverem preenchidos, vai existir o mesmo valor em suas tabelas respectivamente. 7 Criando Sequence No Oracle, não existe o autoincremento, assim, temos que criar uma sequence, são objetos que geram números sequenciais dentro do Oracle. Utilizamos as sequence para gerar um identificado único em uma tabela. CREATE SEQUENCE S_ID_ENDERECO INCREMENT BY 1 START WITH 1 MINVALUE 1; Essa sequence será utilizada para a coluna “ID_ENDERECO”, da tabela “ENDERECO”. Criando Trigger Já temos uma sequence, agora temos que gerar o gatilho, ação que ira ser executada quando inserir um registro na tabela. A trigger é utilizada para ações automaticas, mas conhecidas como gatinho de ação, ela vai ser executada quando for inserido algum registro a tabela. create or replace trigger T_ID_ENDERECO before insert on ENDERECO for each row begin if inserting then if :NEW.ID_ENDERECO is null then select S_ID_ENDERECO.nextval into :NEW.ID_ENDERECO from dual; end if; end if; end; Comandos Padrões de DMLs Insert into FUCTURA.CONTA (NUMERO,DONO,LIMITE,SALDO) values ('12345','Cleiton','10','0'); Insert into FUCTURA.CONTA (NUMERO,DONO,LIMITE,SALDO) values ('54321','Bruninho','30','100'); Insert into FUCTURA.CONTA (NUMERO,DONO,LIMITE,SALDO) values ('121212','Julio','20','-120'); Insert into FUCTURA.CONTA (NUMERO,DONO,LIMITE,SALDO) values ('112233','Alquem dai do lado','120','300'); UPDATE PESSOA SET CPF = '12345678910' WHERE CPF = '123123123'; DELETE FROM PESSOA WHERE CPF = '123'; SELECT P.NOME, P.CPF, P.IDADE, P.SEXO FROM PESSOA P; SELECT P.NOME, P.CPF, E.RUA, E.NUMERO FROM PESSOA P, ENDERECO E WHERE P.ID_ENDERECO = E.ID_ENDERECO 8 Exercício Inserir em suas tabelas respectivamente: 5 registros de Endereço; 5 registros de Pessoa; 5 registros de Conta; Realiza duas consultas simples e uma complexa (SELECT) que retorne as seguintes informações: 1 – Quero todas as pessoas que residem em apartamentos. 2 – Quero todas as pessoas que tenha saldo da conta MAIOR que R$100,00 3 – Quero os endereços das pessoas que não tem saldo em conta e residem em casa. Projeto JDBC Netbeans Como agora temos nossa base de dados criada no banco Oracle XE, podemos realizar o acesso direto a ele, utilizando o JDBC. Para isso, vamos criar um projeto JAVA normal. O que é JDBC? API que reúne conjuntos de classes e interfaces, escritas na linguagem Java, na qual, possibilita se conectar através de um driver específico ao banco de dados desejado. Com esse driver pode-se executar instruções SQL de qualquer tipo de banco de dados relacional. O que é DRIVER? Conjunto de classes concretas que faz a ponte entre o código que usa a API JDBC e o banco de dados. São essas classes que sabem se comunicar através do protocolo proprietário do banco de dados. Além de atuar como uma interface entre os bancos de dados e as aplicações, também, pode ser considerada como um tradutor, que ajuda na definição das mensagens binárias trocadas com um protocolo de banco. Ex: Class.forName(“oracle.jdbc.driver.OracleDriver”); O pacote JAVA.Sql, biblioteca utilizadas para manipulação e processar dados da base de dados. Classe Interface DriverManager Driver Connection 9 Statement ResultSet PreparedStatement DriverManager Responsável por se comunicar com todos os drivers que você deixou disponível. Para isso, é chamado o método estático getConnection com uma String que indica a qual banco desejamos nos conectar. Class.forName(“oracle.jdbc.driver.OracleDriver”); Connection conexao = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe"); PreparedStatement Usado para criar um objeto que representa a instrução SQL que será executada, sendo que é invocado através do objeto Connetion. Class.forName(“oracle.jdbc.driver.OracleDriver”); Connection conexao = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe"); String sql = "INSERT INTO ENDERECO (RUA, NUMERO, COMPLEMENTO) VALUES ('Alguma rua', '12345', 'AP')"; //Prepara a instrução SQL PreparedStatement ps = conexao.prepareStatement(sql); //Executa a instrução SQL ps.execute(); ps.close(); ResultSet Conjunto de resultados de uma tabela no banco de dados. Esse objeto mantém o cursor apontando para a sua linha atual de dados, sendo que seu início fica posicionado na primeira linha. Além disso, esse objeto fornece métodos getters referentes aos tipos de dados como: getInt, getString, getDouble, getFloat, getLong entre outros. String sql = “SELECT P.NOME, P.CPF, P.IDADE, P.SEXO FROM PESSOA P”; ResultSet res = stmt.executeQuery(sql); while (res.next()) { Pessoa pessoa = new Pessoa(); pessoa.setNome(res.getString(“NOME")); 10 pessoa.setIdade(res.getInt(“IDADE")); pessoa.setSexo(res.getString(“SEXO")); sout(“Pessoa: ” + pessoa.imprimir()); Exercício Crie uma aplicação com tudo que já aprendemos, com as seguintes funcionalidades: (1) Cadastrar Pessoa com Endereço (2) Alterar Pessoa e Endereço (3) Pesquisar Pessoa (4) Remover Pessoa e Endereço (5) Listar Todas as Pessoas e seu Endereço (6) Sair OBS: Pessoa tem relacionamento com Endereço, assim, removendo uma pessoa, seu endereço deve também, ser removido. JPA e Hibernate O que é persistência? Conceito fundamental no desenvolvimento de aplicações. Se um sistema de informação não preserva os dados quando ele é encerrado, o sistema não seria prático e usual. Normalmente falamos do uso de sistemas gerenciadores de banco de dados relacionais e SQL, porém existem diversas outras alternativas para persistir dados, como em arquivos XML, arquivos texto e etc. ORM Técnica de programação para conversão de dados entre banco de dados relacionais e linguagens de programação orientada a objetos. Em banco de dados, entidades são representadas por tabelas, que possuem colunas que armazenam propriedades de diversos tipos. Modelo relacional Modelo OO TABELA CLASSE LINHA OBJETO COLUNA ATRIBUTO - METODO CHAVE ESTRANGUEIRA ASSOCIAÇÃO 11 Porque usar ORM? Em um ambiente ORM, as aplicações interagem com APIs e o modelo de classes de domínio e os códigos SQL/JDBC são abstraídos. Os comandos SQL são automaticamente gerados a partir dos metadados que relacionam objetos a banco de dados. ORM abstrai sua aplicação do banco de dados e do dialeto SQL. Com JPA, você pode desenvolver um sistema usando um banco de dados e colocá-lo em produção usando diversos outros bancos de dados, sem precisar alterar códigosfontes para adequar sintaxe Java Persistence API (JPA) A Java Persistence API (JPA) é um framework para persistência em Java, que oferece uma API de mapeamento objeto-relacional e soluções para integrar, persistência com sistemas corporativos escaláveis. Com JPA, os objetos são POJO (Plain Old Java Objects), ou seja, não é necessário nada de especial para tornar os objetos persistentes. Basta adicionar algumas anotações nas classes que representam as entidades do sistema e começar a persistir ou consultar objetos. Hibernate É um framework para o mapeamento objeto-relacional escrito na linguagem Java, este framework facilita o mapeamento dos atributos entre uma base tradicional de dados relacionais e o modelo objeto de uma aplicação, mediante o uso de arquivos (XML) ou anotaçõesJava. O objetivo do Hibernate é diminuir a complexidade entre os programas Java, baseado no modelo orientado a objeto, que precisam trabalhar com um banco de dados do modelo relacional (presente na maioria dos SGBDs). Em especial, no desenvolvimento de consultas e atualizações dos dados. Download e configuração do Hibernate ORM Crie um novo projeto Java e dentro e crie uma pasta dentro dele chamada “lib”, para que possamos colocar os JARs necessários. 12 Copie todos os arquivos das pastas “required” e “jpa” para a pasta “lib” do projeto. Estas bibliotecas fazem parte da distribuição do Hibernate ORM e são obrigatórias para seu funcionamento. As demais são requeridas apenas para casos específicos. Criando um projeto java e incorporando JPA + Hibernate Criar projeto Java normal, lembrando em deixar marcado a criação da pasta .lib 13 Com o projeto criado, temos que adicionar as bibliotecas do “HIBERNATE”, “JPA” e “JDBC”, como mostrado nas imagens abaixo. Adicionado a biblioteca do Hibernate com o JPA e também, .jar do JDBC. Agora vamos criar uma conexão no netbeans com a nossa base de dados do Oracle. Clica na aba serviço, depois Banco de Dados e nova conexão. 14 Com o projetos criado, adicionado as bibliotecas, conexão no netbeans também, criada, vamos agora importar as tabelas do banco e as transforma-las em classes Java. Criação do Domain Model Em nosso ambiente temos as 3 classes Pessoa, Endereço e Conta. Assim queremos gravar e consultar os dados dessas tabelas. 15 Antes temos que criar nossos modelos de domínio para o negócio. Vamos criar as classes simples do nosso sistema JPA e Hibernate. Como hoje temos 3 classes (PESSOA, ENDERECO e CONTA), temos que mapeá-las: @Entity @Table(name = “endereco") @Id @Column(name = “nome”, length = 60, nullable = false) OBS: Para todas as classes e suas tabelas referenciadas Importando as classes das tabelas Seleciona a conexão criada e passa as tabelas que foram criadas no banco de dados “CONTA”, “ENDERECO” e “PESSOA”. 16 No campo pacote, devemos criar um pacote novo com o nome de “entidade”, onde, ficaram as entidades que espelham as tabelas, como também, deve ser desmarcado a opção “Gerar anotação JAXB”, e depois em proximo. Deve ser alterado o tipo de coleção utilizado a List e depois finaliza. 17 Finalizando a importação das classes do banco de dados, devemos realizar alguns ajustes nas classes, deixando elas dessa forma. CONTA: /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package entidades; import java.io.Serializable; import java.util.List; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.OneToMany; import javax.persistence.Table; /** * * @author Cleiton */ @Entity @Table(name = "CONTA") @NamedQueries({ @NamedQuery(name = "Conta.findAll", query = "SELECT c FROM Conta c"), @NamedQuery(name = "Conta.findByNumero", query = "SELECT c FROM Conta c WHERE c.numero = :numero"), @NamedQuery(name = "Conta.findByDono", query = "SELECT c FROM Conta c WHERE c.dono = :dono"), @NamedQuery(name = "Conta.findByLimite", query = "SELECT c FROM Conta c WHERE c.limite = :limite"), @NamedQuery(name = "Conta.findBySaldo", query = "SELECT c FROM Conta c WHERE c.saldo = :saldo")}) public class Conta implements Serializable { private static final long serialVersionUID = 1L; @Id @Column(name = "NUMERO") private Long numero; @Column(name = "DONO") 18 private String dono; @Column(name = "LIMITE") private Double limite; @Column(name = "SALDO") private Double saldo; @OneToMany(mappedBy = "conta") private List<Pessoa> pessoaList; public Conta() { } public Conta(Long numero) { this.numero = numero; } public Conta(Long numero, Double saldo) { this.numero = numero; this.saldo = saldo; } public Long getNumero() { return numero; } public void setNumero(Long numero) { this.numero = numero; } public String getDono() { return dono; } public void setDono(String dono) { this.dono = dono; } public List<Pessoa> getPessoaList() { return pessoaList; } public void setPessoaList(List<Pessoa> pessoaList) { this.pessoaList = pessoaList; } @Override public int hashCode() { int hash = 0; hash += (getNumero() != null ? getNumero().hashCode() : 0); return hash; } @Override 19 public boolean equals(Object object) { // TODO: Warning - this method won't work in the case the id fields are not set if (!(object instanceof Conta)) { return false; } Conta other = (Conta) object; if ((this.getNumero() == null && other.getNumero() != null) || (this.getNumero() != null && !this.numero.equals(other.numero))) { return false; } return true; } @Override public String toString() { return "Conta: " + this.numero + " Saldo:" + this.saldo; } } ENDERECO: /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package entidades; import java.io.Serializable; import java.util.List; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.OneToMany; import javax.persistence.Table; /** * * @author Cleiton */ @Entity @Table(name = "ENDERECO") @NamedQueries({ @NamedQuery(name = "Endereco.findAll", query = "SELECT e FROM Endereco e"), @NamedQuery(name = "Endereco.findByRua", query = "SELECT e FROM Endereco e WHERE e.rua = :rua"), @NamedQuery(name = "Endereco.findByNumero", query = "SELECT e FROM Endereco e WHERE e.numero = :numero"), @NamedQuery(name = "Endereco.findByComplemento", query = "SELECT e FROM Endereco e WHERE e.complemento = :complemento"), 20 @NamedQuery(name = "Endereco.findByIdEndereco", query = "SELECT e FROM Endereco e WHERE e.id = :idEndereco")}) public class Endereco implements Serializable { private static final long serialVersionUID = 1L; @Id @Column(name = "ID_ENDERECO") @GeneratedValue(strategy = GenerationType.IDENTITY, generator = "S_ID_ENDERECO") private Long id; @Column(name = "RUA") private String rua; @Column(name = "NUMERO") private Long numero; @Column(name = "COMPLEMENTO") private String complemento; @OneToMany(mappedBy = "endereco") private List<Pessoa> pessoaList; public Endereco() { } public Endereco(Long id) { this.id = id; } public Endereco(long id, String rua, Long numero, String complemento) { this.id = id; this.rua = rua; this.numero = numero; this.complemento = complemento; } public String getRua() { return rua; } public void setRua(String rua) { this.rua = rua; } public String getComplemento() { return complemento; } public void setComplemento(String complemento) { this.complemento = complemento; } public Long getId() { 21 return id; } public void setId(Long id) { this.id = id; } public Long getNumero() { return numero; } public void setNumero(Long numero) { this.numero = numero; } public List<Pessoa> getPessoaList() { returnpessoaList; } public void setPessoaList(List<Pessoa> pessoaList) { this.pessoaList = pessoaList; } @Override public int hashCode() { int hash = 0; hash += (id != null ? id.hashCode() : 0); return hash; } @Override public boolean equals(Object object) { // TODO: Warning - this method won't work in the case the id fields are not set if (!(object instanceof Endereco)) { return false; } Endereco other = (Endereco) object; if ((this.id == null && other.id != null) || (this.id != null && ! this.id.equals(other.id))) { return false; } return true; } @Override public String toString() { return "Endereço: " + this.rua + " Numero: " + this.numero; } } PESSOA: /* * To change this license header, choose License Headers in Project Properties. 22 * To change this template file, choose Tools | Templates * and open the template in the editor. */ package entidades; import java.io.Serializable; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.Table; /** * * @author Cleiton */ @Entity @Table(name = "PESSOA") @NamedQueries({ @NamedQuery(name = "Pessoa.findAll", query = "SELECT p FROM Pessoa p"), @NamedQuery(name = "Pessoa.findByNome", query = "SELECT p FROM Pessoa p WHERE p.nome = :nome"), @NamedQuery(name = "Pessoa.findByIdade", query = "SELECT p FROM Pessoa p WHERE p.idade = :idade"), @NamedQuery(name = "Pessoa.findBySexo", query = "SELECT p FROM Pessoa p WHERE p.sexo = :sexo"), @NamedQuery(name = "Pessoa.findByCpf", query = "SELECT p FROM Pessoa p WHERE p.cpf = :cpf")}) public class Pessoa implements Serializable { private static final long serialVersionUID = 1L; @Id @Column(name = "CPF") private String cpf; @Column(name = "NOME") private String nome; @Column(name = "IDADE") private Long idade; @Column(name = "SEXO") private String sexo; @JoinColumn(name = "ID_ENDERECO", referencedColumnName = "ID_ENDERECO") @ManyToOne(cascade = CascadeType.ALL) private Endereco endereco; @JoinColumn(name = "NUMERO_CONTA", referencedColumnName = "NUMERO") @ManyToOne(cascade = CascadeType.PERSIST) private Conta conta; 23 public Pessoa() { } public Pessoa(String cpf) { this.cpf = cpf; } public Pessoa(String cpf, String nome, Long idade, String sexo) { this.cpf = cpf; this.nome = nome; this.idade = idade; this.sexo = sexo; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public String getSexo() { return sexo; } public void setSexo(String sexo) { this.sexo = sexo; } public String getCpf() { return cpf; } public void setCpf(String cpf) { this.cpf = cpf; } public Endereco getEndereco() { return endereco; } public void setEndereco(Endereco endereco) { this.endereco = endereco; } public Conta getConta() { return conta; } public void setConta(Conta conta) { this.conta = conta; } 24 @Override public int hashCode() { int hash = 0; hash += (cpf != null ? cpf.hashCode() : 0); return hash; } @Override public boolean equals(Object object) { // TODO: Warning - this method won't work in the case the id fields are not set if (!(object instanceof Pessoa)) { return false; } Pessoa other = (Pessoa) object; if ((this.cpf == null && other.cpf != null) || (this.cpf != null && ! this.cpf.equals(other.cpf))) { return false; } return true; } @Override public String toString() { return "entidades.Pessoa[ cpf=" + cpf + " ]"; } public Long getIdade() { return idade; } public void setIdade(Long idade) { this.idade = idade; } } PERSISTENCE.XML O persistence.xml é um arquivo de configuração padrão da JPA. Ele deve ser criado no diretório META-INF da aplicação ou do módulo que contém os beans de entidade. O arquivo persistence.xml define unidades de persistência, conhecidas como persistence units. <?xml version="1.0" encoding="UTF-8"?> <persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"> <persistence-unit name=“FucturaPU"> <!-- <provider>org.hibernate.ejb.HibernatePersistence</provider> --> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <class>entidade.Endereco</class> 25 <class>entidade.Conta</class> <class>entidade.Pessoa</class> <properties> <property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:@localhost:1521:XE"/> <property name="javax.persistence.jdbc.password" value="fuctura"/> <property name="javax.persistence.jdbc.user" value="fuctura"/> <property name="javax.persistence.jdbc.driver" value="oracle.jdbc.OracleDriver"/> <property name="hibernate.show_sql" value="true" /> <property name="hibernate.format_sql" value="true" /> <property name="hibernate.hbm2ddl.auto" value="update" /> </properties> </persistence-unit> </persistence> EntityManager e EntityManagerFactory Os sistemas que usam JPA precisam de apenas uma instância de EntityManagerFactory, que pode ser criada durante a inicialização da aplicação. Esta única instância pode ser usada por qualquer código que queira obter um EntityManager. Um EntityManager é responsável por gerenciar entidades no contexto de persistência da interface. São eles: persistir, pesquisar e excluir objetos do banco de dados. EntityManagerFactory entFactory = Persistence.createEntityManagerFactory(“FucturaPA"); EntityManager ent = endFactory. createEntityManager(); Quando vamos utilizar uma conexão utilizando JPA ou Hibernate, devemos sempre utilizar o “EntityManager”, gerados pela factory. Dessa forma, vamos utilizar uma classe para fazer esse controle, JpaUtil import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; public class JpaUtil { private static EntityManagerFactory factory; static { factory = Persistence.createEntityManagerFactory("AlgaWorksPU"); } public static EntityManager getEntityManager() { return factory.createEntityManager(); } public static void close() { factory.close(); } } Com a JPAUtil, podemos fazer os seguintes códigos abaixo, para, inserir, alterar, remover e pesquisar, agilizando e facilitando o desenvolvimento. 26 Persistindo public static void main(String[] args) { EntityManager manager = JpaUtil.getEntityManager(); EntityTransaction tx = manager.getTransaction(); tx.begin(); Endereco endereco = new Endereco(); endereco.setNumero(8888l); endereco.setRua("Essa casa é longe"); endereco.setComplemento("CASA"); manager.persist(endereco); tx.commit(); manager.close(); JpaUtil.close(); } Consultando public static void main(String[] args) { EntityManager manager = JpaUtil.getEntityManager(); Endereco endereco = manager.find(Endereco.class, 1); ou Endereco endereco = manager. getReference(Endereco.class, 1); System.out.println(endereço.imprimir()); manager.close(); JpaUtil.close(); } Listar Dados public static void main(String[] args) { EntityManager manager = JpaUtil.getEntityManager(); Queryquery = manager.createQuery("from Pessoa p"); List<Pessoa> pessoas = query.getResultList(); for (Pessoa pessoa : pessoas) { System.out.println(pessoa.getCpf() + " - "+ pessoa.getNome()); } manager.close(); JpaUtil.close(); } Atualizar dados public static void main(String[] args) { EntityManager manager = JpaUtil.getEntityManager(); EntityTransaction tx = manager.getTransaction(); tx.begin(); Pessoa pessoa = manager.find(Pessoa.class, "123456789"); System.out.println("Pessoa Nome: " + pessoa.getNome()); pessoa.setNome("Cleiton de Aguiar"); 27 System.out.println("Novo Nome: " + pessoa.getNome()); tx.commit(); manager.close(); JpaUtil.close(); } Remover Dados public static void main(String[] args) { EntityManager manager = JpaUtil.getEntityManager(); EntityTransaction tx = manager.getTransaction(); tx.begin(); Pessoa pessoa = manager.find(Pessoa.class, "121212"); manager.remove(pessoa); tx.commit(); manager.close(); JpaUtil.close(); } Exercício Crie um programa que disponibilize as opções de INSERIR, ALTERAR, PESQUISAR, REMOVER e LISTAR TODOS, para a entidade de PESSOA. OBS: Utilize o WHILE e SWITCH para disponibilizar as opções. Design pattern Data Access Object (DAO) O padrão DAO é definido no livro "Core J2EE Patterns" como: "o padrão utilizado para abstrair e encapsular todos os acessos ao data source. O DAO gerencia a conexão com o data source para obter e armazenar informações.“ A implementação do padrão DAO é este encapsula operações CRUD em uma interface que deve ser implementada por uma classe concreta. 28 Desde o início da era da programação, viu-se a grande necessidade de haver um meio de armazenamento de dados. Um programa deveria saber gerenciar os dados e fazer processamentos inteligentes sobre eles, trazendo informações oportunas aos usuários. Hoje as empresas usam grandes bancos de dados que manipulam milhões de informações. Não se pode conceber um sistema moderno sem acesso a algum tipo de base de dados. Dessa forma, os nossos programas devem saber se comunicar com a base de dados. Como fazer isso de maneira adequada? Uma alternativa muito viável é usar o pattern DAO. DAO: o intermediário entre os mundos XMLs, a grosso modo, são um conjunto de tags dispostas de modo hierárquico, contendo informações estruturadas. Arquivos texto são um conjunto de caracteres. Bancos de dados relacionais são um conjunto de tabelas, colunas, e linhas. Aplicações Java são um conjunto de objetos. O DAO deve funcionar como um tradutor dos mundos. Suponha um banco relacional. O DAO deve saber buscar os dados do banco e converter em objetos para ser usado pela aplicação. Semelhantemente, deve saber como pegar os objetos, converter em instruções SQL e mandar para o banco de dados. É assim que um DAO trabalha. Abstração Devido à sua qualidade de tradutor, o DAO abstrai a origem e o modo de obtenção / gravação dos dados, de modo que o restante do sistema manipula os dados de forma transparente, sem se preocupar com o que acontece por trás dos panos. Isso ajuda muito em processos de migrações de fonte de dados e testes unitários. Unificação do acesso a dados É muito comum em códigos de programadores iniciantes vermos a base de dados sendo acessada em diversos pontos da aplicação, de maneira extremamente explícita e repetitiva. Isso é um crime contra um bom design OO. Além de não abstrair a fonte dos dados, transforma o código em um espaguete difícil de manter. O DAO também nos ajuda a resolver este problema, provendo pontos unificados de acesso a dados. Desse modo, a lógica de interação com a base de dados ficam em lugares específicos e especializados nisso, além de eliminar códigos redundantes, facilitando a manutenção e futuras migrações. 29 DAO na prática Geralmente, temos um DAO para cada objeto do domínio do sistema (Produto, Cliente, Compra, etc.), ou então para cada módulo, ou conjunto de entidades fortemente relacionadas. Cada DAO deve possuir uma interface, que especifica os métodos de manipulação de dados. Nossos códigos trabalharão apenas com as interfaces dos DAOs, desconhecendo a implementação utilizada. Isso é uma boa prática, não somente em termos de persistência, mas em vários outros pontos de uma aplicação. public interface EnderecoDAO { public void salvar(Endereco endereco); public void alterar(Endereco endereco); public void remover(Endereco endereco); public Endereco pesquisar(Long id); public List<Endereco> recuperarTodos(); } public class EnderecoDAOImpl implements EnderecoDAO{ private EntityManager em; public EnderecoDAOImpl(EntityManager em) { this.em = em; } @Override public void salvar(Endereco endereco) { EntityTransaction tx = em.getTransaction(); tx.begin(); em.persist(endereco); tx.commit(); } @Override public void alterar(Endereco endereco) { 30 EntityTransaction tx = em.getTransaction(); tx.begin(); em.merge(endereco); tx.commit(); } @Override public void remover(Endereco endereco) { EntityTransaction tx = em.getTransaction(); tx.begin(); em.remove(endereco); tx.commit(); } } @Override public Endereco pesquisar(Long id) { Endereco endereco = em.find(Endereco.class, id); return endereco; } @Override public List<Endereco> recuperarTodos() { Query query = em.createQuery("from Endereco e"); List<Endereco> enderecos = query.getResultList(); return enderecos; } } Exemplo de utilização EnderecoDAO enderecoDAO = new EnderecoDAOImpl(JpaUtil.getEntityManager()); Endereco e = enderecoDAO.pesquisar(2l); 31 System.out.println("Endereco:" + e.getRua()); List<Endereco> listaEnderecos = enderecoDAO.recuperarTodos(); for (Endereco ee : listaEnderecos) { System.out.println("End:" + ee.getRua() + " Numero: " + ee.getNumero()); } Exercício Crie um programa que tenha as funções de INSERIR, ALTERAR, REMOVER, PESQUISAR e LISTAR, para todas as entidades ENDEREÇO, CONTA e PESSOA. OBS: Utilize o while com switch para disponibilizar as opções. 32 O que é banco de dados? Instalando e Configurando Ambiente Criando tabelas e suas características Criando Sequence Criando Trigger Comandos Padrões de DMLs Exercício Projeto JDBC Netbeans DriverManager PreparedStatement Exercício JPA e Hibernate ORM Porque usar ORM? Java Persistence API (JPA) Hibernate Criando um projeto java e incorporando JPA + Hibernate Criação do Domain Model PERSISTENCE.XML EntityManager e EntityManagerFactory Persistindo Consultando Listar Dados Atualizar dados Remover Dados Exercício Design pattern Data Access Object (DAO) DAO: o intermediário entre os mundos Abstração Unificação do acesso a dados DAO na prática Exemplo de utilização Exercício