Baixe o app para aproveitar ainda mais
Prévia do material em texto
Brasília-DF. AcessAndo BAnco de dAdos com JAvA Elaboração Leandro Rubim de Freitas Produção Equipe Técnica de Avaliação, Revisão Linguística e Editoração Sumário APrESEntAção .................................................................................................................................. 4 orgAnizAção do CAdErno dE EStudoS E PESquiSA ..................................................................................................................... 5 introdução ..................................................................................................................................... 7 unidAdE i ESTRUTURA DA API JAVA - JDBC .......................................................................................................... 11 CAPÍtuLo 1 O qUE é O JAVA DATABASE COnnECTIVITy (JDBC) ................................................................. 11 CAPÍtuLo 2 JDBC: ClASSES, méTODOS E PADRõES .................................................................................. 15 unidAdE ii PROGRAmAçÃO JAVA COm JDBC .................................................................................................... 18 CAPÍtuLo 1 COnnECTIOn, STATEmEnT, PREPARED STATEmEnT, RESUlT SET, InSERT, DElETE, UPDATE, SElECT . 18 CAPÍtuLo 2 COnTROlE TRAnSACIOnAl ................................................................................................... 31 CAPÍtuLo 3 DESIGn PATTERn .................................................................................................................. 34 unidAdE iii JAVA COm JPA/HIBERnATE ................................................................................................................. 42 CAPÍtuLo 1 ESTRUTURA JPA E HAnDS On ................................................................................................ 42 PArA (não) finALizAr ...................................................................................................................... 56 rEfErênCiAS .................................................................................................................................... 57 4 Apresentação Caro aluno A proposta editorial deste Caderno de Estudos e Pesquisa reúne elementos que se entendem necessários para o desenvolvimento do estudo com segurança e qualidade. Caracteriza-se pela atualidade, dinâmica e pertinência de seu conteúdo, bem como pela interatividade e modernidade de sua estrutura formal, adequadas à metodologia da Educação a Distância – EaD. Pretende-se, com este material, levá-lo à reflexão e à compreensão da pluralidade dos conhecimentos a serem oferecidos, possibilitando-lhe ampliar conceitos específicos da área e atuar de forma competente e conscienciosa, como convém ao profissional que busca a formação continuada para vencer os desafios que a evolução científico-tecnológica impõe ao mundo contemporâneo. Elaborou-se a presente publicação com a intenção de torná-la subsídio valioso, de modo a facilitar sua caminhada na trajetória a ser percorrida tanto na vida pessoal quanto na profissional. Utilize-a como instrumento para seu sucesso na carreira. Conselho Editorial 5 organização do Caderno de Estudos e Pesquisa Para facilitar seu estudo, os conteúdos são organizados em unidades, subdivididas em capítulos, de forma didática, objetiva e coerente. Eles serão abordados por meio de textos básicos, com questões para reflexão, entre outros recursos editoriais que visam a tornar sua leitura mais agradável. Ao final, serão indicadas, também, fontes de consulta, para aprofundar os estudos com leituras e pesquisas complementares. A seguir, uma breve descrição dos ícones utilizados na organização dos Cadernos de Estudos e Pesquisa. Provocação Textos que buscam instigar o aluno a refletir sobre determinado assunto antes mesmo de iniciar sua leitura ou após algum trecho pertinente para o autor conteudista. Para refletir Questões inseridas no decorrer do estudo a fim de que o aluno faça uma pausa e reflita sobre o conteúdo estudado ou temas que o ajudem em seu raciocínio. É importante que ele verifique seus conhecimentos, suas experiências e seus sentimentos. As reflexões são o ponto de partida para a construção de suas conclusões. Sugestão de estudo complementar Sugestões de leituras adicionais, filmes e sites para aprofundamento do estudo, discussões em fóruns ou encontros presenciais quando for o caso. Praticando Sugestão de atividades, no decorrer das leituras, com o objetivo didático de fortalecer o processo de aprendizagem do aluno. Atenção Chamadas para alertar detalhes/tópicos importantes que contribuam para a síntese/conclusão do assunto abordado. 6 Saiba mais Informações complementares para elucidar a construção das sínteses/conclusões sobre o assunto abordado. Sintetizando Trecho que busca resumir informações relevantes do conteúdo, facilitando o entendimento pelo aluno sobre trechos mais complexos. Exercício de fixação Atividades que buscam reforçar a assimilação e fixação dos períodos que o autor/ conteudista achar mais relevante em relação a aprendizagem de seu módulo (não há registro de menção). Avaliação Final Questionário com 10 questões objetivas, baseadas nos objetivos do curso, que visam verificar a aprendizagem do curso (há registro de menção). É a única atividade do curso que vale nota, ou seja, é a atividade que o aluno fará para saber se pode ou não receber a certificação. Para (não) finalizar Texto integrador, ao final do módulo, que motiva o aluno a continuar a aprendizagem ou estimula ponderações complementares sobre o módulo estudado. 7 introdução Todas as empresas necessitam armazenar dados e informações referentes ao seu negócio. Por exemplo, uma padaria precisa registrar as vendas efetuadas, o seu estoque e etc. Uma empresa de comércio eletrônico precisa armazenar todos os dados de seus clientes, produtos, fornecedores, vendas e etc. Atualmente, registrar as informações relevantes de uma empresa no papel não é uma boa alternativa. Recuperar a informação armazenada dessa forma é demorada e sujeita a erros, o volume de material pode ser grande, necessitando assim de grande espaço físico para o seu armazenamento, além do cuidado para não perder as informações em caso de acidentes. A solução é utilizar o computador para armazenar os dados, que podem ser armazenados em arquivos texto ou planilhas. Outra opção é utilizar sistemas especializados no armazenamento de dados que oferecem mais funcionalidades e recursos avançados, como backup e buscas mais eficientes. Esses sistemas são conhecidos como Sistemas Gerenciadores de Banco de Dados – SGBD. Um Sistema de Gerenciamento de Banco de Dados é o conjunto de programas de computador responsáveis pelo gerenciamento de uma base de dados. Seu principal objetivo é retirar da aplicação cliente a responsabilidade de gerenciar o acesso, manipulação e a organização dos dados. O SGBD disponibiliza uma interface para que seus clientes possam incluir, alterar, excluir ou consultar dados previamente armazenados. Os principais SGBDs utilizados nas empresas utilizam o Modelo Relacional para armazenar as informações e a linguagem SQL para manipular os dados armazenados nas base de dados. » Os principais SGBDs utilizados no mercado são: » Oracle Database » SQL Server » PostgreSQL » MySQL Server O Modelo Relacional é um modelo de dados baseados em entidade e relações. Entidade é um elemento caracterizado pelos dados que são recolhidos na sua identificação vulgarmente designado por tabela. Na construção da tabela identificam-se os dados da entidade. A atribuição de valores de uma entidade constrói um registro da tabela.A relação determina o modo como cada registro de cada tabela se associa a registros de outras tabelas. Figura 1 – Exemplo de tabelas. Fonte: autor jd Destacar jd Destacar jd Sublinhar 8 O exemplo acima mostra duas tabelas que armazena dados de Clientes e Produtos. Uma tabela é formada por registros (linhas) e os registros são formados por campos (colunas). A tabela Cliente armazena as informações: código, nome e cpf. Ela possui 3 registros (linhas): Thiago, Gabriela e José. A tabela produto armazena 4 informações, o código, produto, quantidade e preço. E possui 3 registros também: celular, livro e tablet. As tabelas normalmente possuem uma chave primária, que é um identificador único que garante que nenhum registro será duplicado. Assim, todo registro possui um identificador que é único na tabela. Structured Query Language SQL, ou Linguagem de Consulta Estruturada é a linguagem de pesquisa declarativa padrão para banco de dados relacional, é através dela que os principais SGBDs interagem com os bancos de dados. A linguagem SQL surgiu em 1974 e foi desenvolvida nos laboratórios da IBM como interface para o Sistema Gerenciador de Banco de Dados Relacional (SGBDR). Outras linguagens do gênero surgiram e foi criado um padrão para a SQL em 1986 pelo American National Standard Institute (ANSI) e em 1987 pela International Organization for Standards (ISSO). Alguns dos principais comandos SQL para a manipulação de dados são: INSERT (inserção), SELECT (consulta), UPDATE (atualização), DELETE (exclusão). SQL possibilita ainda a criação de tabelas, relações e controle do acesso aos dados. Neste curso, iremos abordar a linguagem SQL com mais detalhes. O curso irá propiciar a compreensão dos conceitos fundamentais de Sistemas de Informação e Banco de Dados, que convergem no alicerce de todos os sistemas computacionais. Serão abordados todos os itens da Engenharia de um Software, desde a análise das necessidades cruciais para a criação de um sistema e o armazenamento de dados em um banco de dados MySQL utilizando o JDBC com a linguagem de programação Java. objetivos » Entender os conceitos do JDBC. » Compreender a estrutura para conectar ao banco de dados e executar comandos com o JDBC. » Entender como codificar, compilar e executar programas em Java para comunicação com banco de dados. » Analisar padrões de programação. JD Destacar 9 » Compreender padrões de projetos e aplica-los na programação Java. » Compreender os princípios da criação de um sistema com acesso a banco de dados. Com o avanço da tecnologia e a arquitetura de Nuvem, bancos não relacionais estão ganhando força. São bancos chamados NoSQL, Para saber mais acesse: <http://pt.wikipedia.org/wiki/NoSQL> 10 11 unidAdE iEStruturA dA APi JAVA - JdBC CAPÍtuLo 1 o que é o Java database Connectivity (JdBC) JdBC: princípios O Java Database Connectivity é uma API (Aplication Programming Interface), ou seja, um conjunto de padrões (interfaces) criados nos primordios do Java para permitir uma padronização das diversas possíveis implementações que surgiriam para os diversos tipos distintos de banco de dados. Difícil o entendimento? Para entender melhor a importância do JDBC, vai aqui uma pequena história: O Java iniciou sua vida em meados de 1991, e devido a sua rápida ascensão no mercado de tecnologia, diversos fabricantes de banco de dados se interessaram em disponibilizar seus SGBDs (Sistema Gerenciador de Banco de Dados) ao acesso do Java. Ali, naquele momento, existia um perigo: a falta de padronização, o que complicaria e muito a vida do programador. Imagine só ter que desenvolver um sistema para acesso a um SGBD, e de repente, diante de uma necessidade de mudar ou aderir a um novo SGBD, ter que modificar todo o código? Foi ai que surgiu a ideia, criada pela então Sun Microsystems, de utilizar o conceito de Interfaces do Java para criar um conjunto de padrões a serem seguidos por todos os fabricantes de SGBDs interessados, o JDBC. O JDBC possui uma série de Interfaces, que são classes denominadas interfaces que contém as declarações de construtores, atributos e métodos representando regras/padrões a serem implementadas. Em vias de fato, supondo que a fabricante do SGBD chamado “Tatu Database” quisesse que seu SGBD fosse acessado pela linguagem de programação Java, então este simplesmente deve seguir os padrões do JDBC, implementando conforme as configuração de seu SGBD, mas seguindo os padrões e nomenclaturas do JDBC. Mas qual a grande vantagem do modelo JDBC? jd Destacar jd Destacar jd Sublinhar 12 UNIDADE I │ ESTRUTURA DA API JAVA - JDBC Simples e fácil o entendimento. Imagine que sua empresa tem um sistema em Java que acessa ao SGBD Oracle, e que devido a troca de SGBD seja necessário adaptar todo o sistema ao novo SGBD, por exemplo, ao Tatu Database. A solução é simplesmente: basta trocar as bibliotecas de acesso ao Oracle para as bibliotecas de acesso ao Tatu, pois o código em si permanecerá o mesmo. Figura 2. Estrutura JDBC. Fonte: <http://docstore.mik.ua/orelly/java-ent/servlet/figs/jsp_0902.gif> A figura acima representa a estrutura JDBC, onde é possível observar que independentemente se o acesso for realizado para a plataforma Oracle, Microsoft, Sybase, ou qualquer outro SGBD, a estrutura de classes é a mesma. Nesta estrutura, uma das poucas classes que é implementada é a DriverManager, que é responsável por identificar qual o conjunto de bibliotecas a ser utilizada: se o OracleDriver, JDBC-ODBC Driver, SybaseDriver, e assim por diante. A biblioteca OracleDriver foi produzida pela Oracle, seguindo o conjunto de interfaces criada pela Sun, assim com o SybaseDriver foi criada pela Sybase, e assim como o JDBC-ODBC Brigde criada para permitir a comunicação entre Drivers Java e Microsoft. Caso a nossa empresa exemplo, a “Tatu” desenvolva um conjunto de Bibliotecas, então desenvolveria a TatuDriver, para acesso ao Tatu Database. Conheça um pouco mais sobre os 4 tipos de JDBC disponíveis: <http://pt.wikipedia.org/wiki/JDBC> 13 ESTRUTURA DA API JAVA - JDBC │ UNIDADE I JdBC: a estrutura O Java Database Connectivity, como citado anteriormente, é uma API (Aplication Programming Interface), ou seja, um conjunto de padrões (interfaces) criados nos primordios do Java. Interface, é um contrato entre a classe e o mundo externo. Quando uma classe implementa uma interface, ela está comprometida a fornecer o comportamento publicado pela interface.. Na estrutura JDBC, como visualizada na figura 2, possui um conjunto de interfaces e poucas classes de implementação. Abaixo são descritas as principais interfaces e a classe principal que rege da a escolha do driver. Figura 3. Estrutura JDBC. Fonte: Autor As classes para manipulação de banco de dados estão no pacote java.sql. Para estabelecer uma conexão com um SGBDR é preciso solicitar do gerenciador de drivers (java.sql.DriverManager) a abertura da conexão. Se o DriverManager conseguir estabelecer a conexão com o SGBD um objeto do tipo java.sql.Connection é retornado, caso contrário uma exceção é gerada O DriverManager é responsável por encontrar o driver que será utilizado na aplicação. Quando uma implementação (driver) é carregada ela é registrada utilizando o DriverManager. A partir do DriverManager serão criadas as conexões para a base de dados utilizando o método getConnection e passando a JDBC URL para a conexão, conforme veremos mais adiante. A figura abaixo demonstra qual o papel do DriverManager: Figura 4. Papel do Drivermanager. Fonte: Autor jd Destacar 14 UNIDADE I │ ESTRUTURA DA API JAVA - JDBC A estrutura JDBC pode ser visualizada no arquivo rt.jar, contido no pacote JDK do Java. Dentro doarquivo rt.jar, é possível encontrar todas as interfaces e classes, tal como abaixo: Figura 5. Classes e Interfaces do arquivo rt.jar. Fonte: Autor 15 CAPÍtuLo 2 JdBC: classes, métodos e padrões Desenvolver sistemas com acesso a banco de dados tem alguns passos em comum, independente da linguagem de programação. Para melhor entender esses passos, basta realizarmos analogia com o processo de um telefonema. Para realizar um telefonema é necessário, primeiramente, se ter o número do destinatário. Logo após, a partir de um aparelho telefônico, discar a este número. Uma vez discado e o destinatário presente, então cria-se a conexão e posteriormente a comunicação. E ao final, é desligada a conexão, encerrando-se o processo. No processo de comunicação entre uma linguagem de programação e um banco de dados, o processo é o mesmo: 1. É necessário ter o “número” do banco de dados destinatário, considerando o endereço de IP (Internet Protocol) como endereço físico, e a porta, como endereço lógico. 2. Uma vez o banco de dados disponível, então é estabelecida a conexão, abrindo um canal de comunicação. 3. A partir da conexão, é possível enviar comandos de conversão entre a linguagem de programação e o banco de dados. O meio de comunicação universalmente utilizado e padronizado é a linguagem SQL (Structured Query Language). 4. Ao final, é desligada a conexão, encerrando-se o processo. Outra etapa do processo que é necessária ter sempre codificada é a etapa relacionada a captura de quaisquer problemas que possam ocorrer, os chamados tratamentos de erros. É uma etapa essencial pois podem ocorrer problemas na conexão, erros de comunicação, tais como numa telefonema, com a diferença que em um telefonema existe a ação direta do usuário, e na programação o próprio programa deve prever as diversas situações. A seguir é descrito um exemplo da comunicação de Java com o banco de dados. Pode-se observar que os passos são exatamente os mesmos descritos acima e que independente da ação a ser realizada, se Inserção, Consulta, Atualização ou Exclusão, este processo será o mesmo. 16 UNIDADE I │ ESTRUTURA DA API JAVA - JDBC public class ConexaoBancoDados { public static void main(String args[]) { try { Class.forName(“oracle.jdbc.driver.OracleDriver”);//registra o driver Connection conn = DriverManager.getConnection(“jdbc:oracle:thin: @192.168.60.15:1521:ORCL”,”OPS$RM99999”, “senha”);//abre a conexao System.out.println(“Conectado!”); //realiza a comunicação com SQL conn.close();//fecha a conexao }catch(ClassNotFoundException e) { // Tratamento dos erros System.err.println(“O Driver JDBC nao foi encontrado: “ + e.getMessage()); }catch(SQLException e) { System.out.println(“Nao foi possivel conectar com o SGBDR”); System.err.println(e.getMessage()); } } } Ao observarmos que existem padrões, é necessário evitar o famoso “copy & paste” de código e utilizarmos o processo de reutilização. Portanto, é viável e interessante a utilização dos conceitos de Orientação a Objetos. Por exemplo, é possível: » Criar uma classe estática somente para tratar a conexão. » Utilizar padrões de desenvolvimento, tal como o padrão Abstract Factory (que você verá mais a frente neste material) » Fazer uso de “Generics”, criando classes de acesso a dados genéricas. » Utilizar frameworks de Mapeamento de Objetos com Banco de Dados Relacional, tal como JPA/Hibernate (que você verá mais a frente neste material). 17 ESTRUTURA DA API JAVA - JDBC │ UNIDADE I Abaixo seguem dois exemplos. O primeiro de criação de uma única classe estática para tratar a conexão, e o segundo um exemplo de classe de acesso a dados genéricas. Ambas promovem reutilização de código e também otimização de processamento. public class DBManager { public static Connection obterConexaoMySQL() throws Exception { Class.forName(“com.mysql.jdbc.Driver”); return DriverManager .getConnection(“jdbc:mysql://localhost:3306/bd”,”root”,”root”); } } } public abstract class GenericDAO <T> { static EntityManagerFactory factory = null; private Class<T> classe; static { factory = Persistence.createEntityManagerFactory(“cadastro_PU”); } public T localizar(int id) { EntityManager em = factory.createEntityManager(); EntityTransaction t = em.getTransaction(); T obj = null; try { t.begin(); obj = em.find(classe, id); t.commit(); } catch (Exception e) { e.printStackTrace(); if (t.isActive()) t.rollback(); } finally { em.close(); } return obj; } 18 unidAdE iiProgrAMAção JAVA CoM JdBC CAPÍtuLo 1 ConnECtion, StAtEMEnt, PrEPArEd StAtEMEnt, rESuLt SEt, inSErt, dELEtE, uPdAtE, SELECt Neste capítulo você conhecerá a estrutura completa do JDBC, desde a conexão, passando pela comunicação, tratamentos, e realizando o CRUD (Create, Retrieve, Update, Delete). Para desenvolvimento do JDBC neste material, é possível utilizar qualquer versão do Java (acima do JDK 1.4), qualquer versão do Eclipse e qualquer SGBD, neste material será utilizado o MySQL. Lembre-se que o Java pode até ser desenvolvido em ferramentas de texto, e compilado e executado via linha de comandos, então sinta-se a vontade para escolher a forma de desenvolvimento. Dando inicio ao JDBC na prática. Como visto anteriormente, o JDBC possui diversas interfaces e classes. Uma vez sabendo o banco de dados de acesso, a primeira atitude é realizar o download do driver que contém a implementação, para posteriormente adicionar ao projeto. Abaixo você encontrará um passo a passo que trará exemplo de onde realizar os respectivos downloads. Antes de efetuar o exemplo, vamos entender um pouco cada parte do processo de desenvolvimento. o que é driverManager? É a classe gerente do JDBC. Ela lê e estabelece qual driver de conexão será usado. Funciona como ponte entre o JDBC e o driver escolhido. Isso é feito através de uma chamada ao método Class.forName (“localização do driver”), passando como parâmetro a classe (e seu pacote) principal da biblioteca do driver. Esta informação deve ser obtida diretamente do site do fabricante e documentos informativos. Nas versões atuais do Java não é necessário mais realizar este processo, pois a partir da String de conexão a própria JVM já reconhece qual o driver a ser acessado. jd Destacar jd Destacar jd Destacar jd Retângulo 19 PROGRAMAçÃO JAVA COM JDBC │ UNIDADE II O Class.forName tem a mesma funcionalidade da instanciação de uma classe, ou seja, uma comando “new”, com a diferença que o Class.forName gera o objeto em memória e não associa a nenhuma variável de referência. Connection Após o registro do driver deve-se inicializar a variável que representa a conexão propriamente dita. Isso é feito através de uma chamada ao método getConnection da classe DriverManager, passando como parâmetro a URL de conexão, URL esta estabelecida também pelo fabricante do SGBD, mas seguindo o padrão JDBC. Exemplo: DriverManager.getConnection(“URL”) onde a URL segue o padrão textual “jdbc: <subprotocolo>:<driver>” Para acessar o Oracle, escreve-se: jdbc:oracle:thin:@192.168.60.15:1521:ORCL Para acessar o MySQL, escreve-se: jdbc:mysql://localhost:3306/estatistica Para acessar um driver ODBC, escreve-se: jdbc:odbc:nomeODBC Comunicação via SqL Para a comunicação efetiva entre o Java e o Banco de Dados, utiliza-se a linguagem estrutura SQL. Existem 3 implementações que podem ser utilizadas via Java, são elas: Statement, PreparedStatement e CallableStatement. Os principais métodos destas implementações são: » executeUpdate: Executa um comando SQL(INSERT, UPDATE, DELETE) e retornao números de linhas afetadas. » executeQuery: Executa um comando SQL(SELECT) e retorna o(s) resultado(s) num objeto do tipo ResultSet Exemplos: » Inclusão: Statement stmt = conn.createStatement(); jd Destacar jd Destacar jd Destacar jd Sublinhar jd Sublinhar jd Sublinhar jd Destacar jd Destacar JD Destacar JD Retângulo JD Destacar 20 UNIDADE II │ PROGRAMAçÃO JAVA COM JDBC stmt.executeUpdate(“INSERT INTO TB_CLIENTE(ID_CLIENTE, NOME, CPF) values (SQ_CLIENTE.NEXTVAL, ‘Felix’, ‘0123547 8222’)”); » Alteração: Statement stmt = conn.createStatement(); stmt.executeUpdate(“UPDATE TB_CLIENTE SET DDD = 11 WHERE DDD is null”); » Exclusão: Statement stmt = conn.createStatement(); stmt.executeUpdate(“DELETE FROM TB_CLIENTE WHERE NOME = ‘Felix’”); » Seleção: Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(“SELECT * FROM TB_CLIE NTE”); Para melhor aproveitamento de cada implementação em suas respectivas otimizações, afirma-se: Statement: Usado para passagem de declarações SQL simples. (SELECT * FROM votacao) Prepared Statement: Usado quando a declaração SQL tiver um ou mais parâmetros que podem ser enviados em conjunto. (SELECT * FROM votacao WHERE total_votos > ?) Callable Statement: Usado para execução de funções do tipo Stored Procedures declaradas em alguns tipos de bancos. CallableStatement cstmt = conn.prepareCall(“{ call proc2 }”); resultSet A classe ResultSet é responsável pelo tratamento dos dados retornados do banco de dados, a partir de uma declaração SELECT. Representa um conjunto de registros que retornam de uma SQL (SELECT). Os registros só podem ser acessados sequencialmente - cada chamada ao método next move o cursor para o próximo registro. Inicialmente o cursor está posicionado antes do primeiro registro. O método next retorna true se for capaz de posicionar na próxima linha. As colunas do registro podem ser acessadas através de um índice inteiro – onde 1 é o número da primeira coluna – ou através do nome da coluna. JD Destacar JD Destacar JD Destacar JD Destacar JD Destacar JD Destacar JD Retângulo JD Retângulo 21 PROGRAMAçÃO JAVA COM JDBC │ UNIDADE II Principais métodos: » next: Move o cursor para a próxima linha » getInt: Retorna o dados da coluna designada como um int do Java » getString: Retorna o dados da coluna designada como uma String do Java » getBoolean: Retorna o dados da coluna designada como um boolean do Java » getDouble: Retorna o dados da coluna designada como um double do Java Exemplo Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(“SELECT * FROM tb_cliente”); System.out.println(“Registros:”); while (rs.next()) {//enquanto houver registro... //pega o valor da coluna e coloca numa variavel Integer id = rs.getInt(“ID_CLIENTE”); String nome = rs.getString(“Nome”); Boolean ativo = rs.getBoolean(“Ativo”); Double valorUltimaCompra = rs.getDouble(“Valor_Ultima_Compra”); //exibe o registro System.out.println(“\t[“ + id + “, “ + nome + “, “ + ativo + “, “ + valorUltimaCompra + “]”); } Metadados do banco de dados Pesquise sobre as interfaces DatabaseMetaData e ResultSetMetaData. Elas permitem obter informações do banco de dados e de suas respectivas tabelas. É possível obter, por exemplo: o número total de colunas, nomes e tipos de dados das colunas de uma determinada tabela, etc. 22 UNIDADE II │ PROGRAMAçÃO JAVA COM JDBC Primeiro exemplo – agora sim! download do MySqL Para realizar o download do MySQL, acesse http://dev.mysql.com/downloads/, escolha a versão de seu desejo. O MySQL possui a versão Server (principal) e a versão Workbench. Faça o download e ambos, e acesso normalmente, tal como qualquer outro banco de dados. Criação das tabelas Para este primeiro exemplo iremos criar um modelo bem simples de sistema, que armazena e consulta dados estatísticos contendo o questionário e o leque de resposta para cada questão. Para tanto, pede-se criar a seguinte estrutura de tabelas: TB_QUESTAO { id_questao integer PK auto, descricao varchar(100) } TB_RESPOSTA { id_resposta integer PK auto, id_questao FK integer, descrição_resposta varchar (100) } Antes de partir para o próximo passo do material, “brinque” dentro do MySQL ou do seu SGBD de escolha. Realize comandos de INSERT, UPDATE, DELETE e SELECT. Criação do Projeto Java A partir do Eclipse, crie um novo projeto como “Java Project”. Figura 6. Criação do Projeto Java. Fonte: Autor 23 PROGRAMAçÃO JAVA COM JDBC │ UNIDADE II Criação da classe de Conexão ao Banco de dados Figura 7. Classe de Conexão ao Banco de Dados. Fonte: Autor Note que foi utilizada a URL de conexão para o MySQL, onde é passada a localização do MySQL (host), porta de conexão e nome do banco de dados, além do usuário e senha. Neste modelo também foi criada a classe com o método estático, já dentro dos padrões de desenvolvimento, além de possuir os tratamentos de erros adequados. Criação dos JavaBeans mapeados com as tabelas Figura 8. Classe de JavaBean: questao.java. Fonte: Autor 24 UNIDADE II │ PROGRAMAçÃO JAVA COM JDBC Figura 9. Classe de JavaBean: Resposta.java. Fonte: Autor Observe que a criação destas classes é de suma importância, visto que elas fazem analogia total com as tabelas, o que facilita o processo de passagem de dados do banco de dados para os objetos do Java e vice-versa. Criação da classe de acesso aos dados Esta é a classe principal a ser criada, que contém o código principal de acesso aos dados e já está seguindo o padrão PatternDAO de desenvolvimento. Figura 10. Classe EstatisticaDAO: estrutura. Fonte: Autor 25 PROGRAMAçÃO JAVA COM JDBC │ UNIDADE II Primeiramente, você deve criar a classe com a estrutura de imports das interfaces do JDBC, e também com as demais classes do projeto a serem utilizadas.Esta classe devo possuir também as implementações especificas para o MySQL, e os métodos CRUD, conforme segue: Figura 11. Classe EstatisticaDAO: método de inclusão. Fonte: Autor Note no código acima que o método criarQuestao recebe o objeto do tipo Questao, que já virá totalmente preenchido com a questão a ser inserida e também todas as possíveis respostas. Note também que ocorre um processo transacional, onde inicialmente é inserida a questão, posteriormente obtido o ID gerado automaticamente pelo banco de dados, e por último inseridas as respostas referentes aquela questão. O método a seguir é o método que lista todas as questão do banco de dados, inclusive com as respostas de cada questão. Observe que durante a leitura de cada questão, é acionado o método obterRespostas, que seleciona todas as respostas referente a questão em leitura. 26 UNIDADE II │ PROGRAMAçÃO JAVA COM JDBC Figura 12. Classe EstatisticaDAO: método de consulta. Fonte: Autor 27 PROGRAMAçÃO JAVA COM JDBC │ UNIDADE II E para finalizar esta classe, segue abaixo um método que excluir todas as questões e suas respectivas respostas. Figura 13. Classe EstatisticaDAO: método de exclusão. Fonte: Autor Criação da classe de negócios Figura 14. Classe EstatisticaBO: classe de negócios. Fonte: Autor 28 UNIDADE II │ PROGRAMAçÃO JAVA COM JDBC A criação de classes de negócios é essencial no mundo corporativo, pois favorece que diversas camadas de negócios se associem entre si. Seguindo este modelo, segue abaixo a classe de negócios, onde é possível inserir quaisquer regras específicas de negócio. Criação da classe de teste Figura 15. Classe de Teste Fonte: Autor Note na criação da classe acima que o objetivo é simular a criação de questõese respostas, testando o funcionamento da estrutura JDBC criada. 29 PROGRAMAçÃO JAVA COM JDBC │ UNIDADE II Vinculação da biblioteca (driver) ao projeto O último passo antes da execução do teste é a configuração da biblioteca do DriverMySQL junto ao projeto. Para isso é necessário realizar o download do driver através do link: https://www.mysql.com/ products/connector/. Observe que a Oracle (detentora do MySQL) disponibiliza diversos conectores a diversas linguagens de programação. No nosso caso, basta efetuar o download para Java. Copie o arquivo com extensão JAR e cole diretamente no projeto, conforme figura abaixo: Figura 17. Estrutura do projeto. Fonte: Autor Clique com o botão direito no driver e adicione ao classpath do projeto, para que durante a execução seja registrado o driver. Figura 18. Configurar classpath. Fonte: Autor realizar o teste final Reta final! Vamos testar! Antes de testar, tenha certeza que o banco de dados esteja criado e que os dados de usuário e senha estejam também alinhados. Feito isso, a partir da classe de Testes, executa como Java Application. 30 UNIDADE II │ PROGRAMAçÃO JAVA COM JDBC Figura 19. Teste. Fonte: Autor Pronto! Seu primeiro projeto JDBC foi executado! O JDBC não é tão complicado o quanto se imagina. Mas é um pouco trabalhoso, pois além de programar em Java é necessário também utilizar a linguagem SQL. Ainda muitos dos sistemas criados e já existentes utilizam essa estrutura de JAVA + SQL. Mas será que existem processos mais otimizados, tal como JPA/Hibernate? Os chamados MOR (Mapeamento Objeto- Relacional) são essenciais para maior produtividade. 31 CAPÍtuLo 2 Controle transacional Toda comunicação com banco de dados requer cuidados com acessos paralelos e integridade dos dados. Para isso, todo SGBD e toda linguagem de programação contém tratamento específico para permitir a segurança e integridade dos dados. No JDBC não é diferente. o que é trAnSAção ? É uma unidade que preserva a consistência no banco de dados. Transações são unidades atômicas de operações: “Em ciência da computação, uma transação atômica é uma operação, ou conjunto de operações, em uma base de dados, ou em qualquer outro sistema computacional, que deve ser executada completamente em caso de sucesso, ou ser abortada completamente em caso de erro.” Figura 20. Processo transacional. Fonte: Autor O exemplo clássico para a necessidade de uma “transação atômica” é aquele da transferência entre duas contas bancárias. No momento de uma transferência de valores de uma conta “A” para uma conta “B”, que envolve pelo menos uma operação de ajuste no saldo para cada conta, se o computador responsável pela operação é desligado por falta de energia, é esperado que o saldo de ambas as contas não tenha se alterado. Neste caso são utilizados sistemas que suportam transações atômicas. Figura 21. Exemplo de Transação Atômica. Fonte: Autor JD Destacar 32 UNIDADE II │ PROGRAMAçÃO JAVA COM JDBC Uma transação pode ser representada pela sigla ACID: » Atomicity (Atomicidade): atômico, tudo (commit) ou nada (rollback) » Consistency (Consistência): toda transação executada deve seguir as regras de integridade do banco de dados, mantendo o banco de dados consistente. » Isolation (Isolamento): transações executadas de forma isolada. Ex: transação A altera o saldo da conta B transação B altera o saldo da conta B » Durability (Durabilidade): as alterações efetuadas pelas transações são permanentes, mesmo em caso de falhas. As operações possíveis para o controle transacional, são: COMMIT ou ROLLBACK COMMIT: Todas operações envolvidas em uma unidade de processo executam com sucesso; ROLLBACK: Uma ou mais operações envolvidas em uma unidade de processo não executam corretamente; Por padrão, toda conexão com JDBC está com AutoCommit igual a true, ou seja, qualquer comando SQL enviado é um comando executado no banco de dados; Para desabilitar, após obter uma instância de Connection, utilize o método: connection. setAutoCommit(false); Exemplo: try { con.setAutoCommit(false); PreparedStatement updateSales = con.prepareStatement( “UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ?”); updateSales.setInt(1, 50); updateSales.setString(2, “Colombian”); updateSales.executeUpdate(); PreparedStatement updateTotal = con.prepareStatement( “UPDATE COFFEES SET TOTAL = TOTAL + ? WHERE COF_NAME LIKE ?”); updateTotal.setInt(1, 50); updateTotal.setString(2, “Colombian”); updateTotal.executeUpdate(); con.commit(); con.setAutoCommit(true); } catch(Exception e){ con.rollback(); } JD Destacar JD Sublinhar JD Destacar JD Destacar JD Retângulo 33 PROGRAMAçÃO JAVA COM JDBC │ UNIDADE II No exemplo acima é possível observar que o controle manual foi ativado logo no inicio (con. setAutoCommit(false)). Com isso, todo e qualquer comando de atualização, inclusão e excluão de dados só será efetivado caso o comando COMMIT seja efetuado, tal como é realizado ao final do processo. Assim sendo, ambas instruções UPDATEs do exemplo só serão efetivadas caso não ocorram erros. É possível observar também que caso algum erro ocorra, toda a transação é desfeita, através do comando ROLLBACK. Ao final do processo o controle manual é desativado, através do comando con.setAutoCommit(true) tornando o processo novamente automático. É importante sempre fechar a conexão após o uso. Os objetos de manipulação de dados também devem ser fechados (Statement, Prepared Statement). OBS: A maior parte dos problemas de performance e consumo de recursos do servidores tem relação com gerenciamento de conexões. Ao contrário do que se pensa é muito frequente a abertura e não fechamento da conexão. Atente-se sempre neste problema, pois uma má programação pode causar danos enormes nos sistemas das corporações. Para complementar o estudo de Controle Transacional, vale a pena assistir ao vídeo em: <http://www.youtube.com/watch?v=g6NRJH1IFqs> 34 CAPÍtuLo 3 design Pattern A programação exige um nível de excelência no código, evitando retrabalhos e adaptações mais rápidos, devido a grande velocidade que os modelos de negócios exigem. Com o objetivo desta otimização e da universalidade da programação, padrões de desenvolvimento são essenciais. Desta maneira, um código desenvolvido nos Estados Unidos podem ser reconhecidos facilmente no Brasil, na França, na China, ou seja, em qualquer lugar do mundo. Para o JDBC não é diferente. Constantes mudanças de SGBDs nas empresas provocam grandes alterações estruturais e também de programação. Uma vez padronizados, estes trabalhos se tornam menores ou inexistentes. Alguns padrões são essenciais, tais como o padrão Singleton, TO, PatternDAO, FactoryMethod e AbstractFactory, entre outros, descritos na sequência. Um Design Pattern (padrão de projeto, padrão arquitetural) é uma solução comum para um problema comum encontrado no desenvolvimento de software. Não está vinculado à nenhuma linguagem OO específica. A sedimentação deste conceito veio com o lançamento do livro: Design Patterns: Elements of Reusable Object-Oriented Software. A utilização destes padrões usualmente implica em algumas vantagens: » Facilidade de comunicação - Os padrões possuem nomes, os quais resumem uma solução que deve ser de conhecimento comum entre equipes de desenvolvimento. » Credibilidade - A implementação estará utilizando soluções amplamente testadas e aprovadas. » Facilidade de manutenção - Padrões tendem a reduzir o acoplamento entre componentes, o que implica num sistema de fácil manutenção. Importante: a utilização de Design Pattern não implica em códigos “mais enxutos”,mas sim na otimização do código. data Access object (dAo) Este Pattern abstrai e encapsula todos os acessos à base de dados. O DAO gerencia a conexão com a fonte de dados para obter e armazenar os dados. Vários níveis de flexibilidade/complexidade diferentes podem ser aplicados em um projeto. A ideia básica é separar totalmente o mecanismo de acesso a dados do resto da aplicação. 35 PROGRAMAçÃO JAVA COM JDBC │ UNIDADE II Assim, cria-se um objeto DAO para cada uma das entidades do projeto encapsulando nele os métodos de manipulação dos dados CRUD (Create, Read, Updade e Delete), conforme figura abaixo – estrutura 1: Figura 22: Pattern DAO – estrutura 1. Fonte: <http://www.oracle.com/technetwork/java/dataaccessobject-138824.html> Abaixo um exemplo a partir de um sistema de biblioteca. A classe LivroDAO simplesmente centraliza todos os métodos de acesso a dados. A classe de negócios exemplifica como é feito o acesso a classe DAO centralizadora, ou seja, o acesso é feito a partir de uma simples instanciação. 36 UNIDADE II │ PROGRAMAçÃO JAVA COM JDBC Outra estrutura e mais completa no quesito Orientação a Objetos é a estrutura com a inclusão de interfaces. Como pode ser observado, o uso de interface estabelece um padrão para a DAO, permitindo que implementações distintas possam ser realizadas. Figura 23: Pattern DAO – estrutura 2. Fonte: <http://www.oracle.com/technetwork/java/dataaccessobject-138824.html> Abaixo um exemplo a partir de um sistema de biblioteca. A classe LivroDAO simplesmente centraliza todos os métodos de acesso a dados. 37 PROGRAMAçÃO JAVA COM JDBC │ UNIDADE II dAo factory Este Pattern é utilizado quando o repositório de dados não está sujeito a mudanças frequentes. Trata-se de uma fábrica de DAOs para um tipo específico de repositório de dados. Cenário de exemplo: Determinada instituição utiliza somente banco de dados MySQL e não existe previsão de mudança. Não é conveniente criar uma estrutura complexa, somente pela possibilidade de suportar diversos tipos de banco de dados, tendo em vista que não há previsão de mudança do atual Figura 24: DAO Factory. Fonte: <http://www.oracle.com/technetwork/java/dataaccessobject-138824.html> Abaixo segue um exemplo de implementação. Note que no sistema de biblioteca agora temos duas DAOs: CategoriaDAO e LivroDAO, com suas respectivas implementações. A grande sacada no modelo DAOFactory é que a distribuição de todas as DAO está centralizada em um única classe abstrata com métodos estáticos, do qual chamamos no exemplo de DAOFactory (Fábrica de DAO). Para utilizar a DAOFactory basta acessar estaticamente o método do qual se deseja obter o objeto de acesso. 38 UNIDADE II │ PROGRAMAçÃO JAVA COM JDBC Abstract factory Ao contrário do DAO Factory este padrão é usado quando o repositório de dados está sujeito a mudanças frequentes. Permite criar implementações de fábricas diferentes que criam DAOs para diferentes repositórios de dados. Cenários de exemplo: » Determina instituição utiliza banco de dados Oracle e SQL Server e já está em processo de compra o banco de dados DB2 para suportar um determinado pacote comprado. Neste cenário é justificada a criação de uma estrutura para suportar os diversos tipos de banco existentes e principalmente estar preparado para suportar novos tipos. » Determinado software é capaz de persistir os dados tanto num SGBDR corporativo como em arquivos do tipo XML, localizados no computador local. Neste cenário é justificada a criação de uma estrutura para suportar os diferentes tipos de repositórios de dados. Figura 25: Abstract Factory. Fonte: Autor Abaixo segue um exemplo de implementação. Note que no sistema de biblioteca continuamos a ter duas DAOs, a CategoriaDAO e a LivroDAO. Mas note que a LivroDAO possui duas implementações, um implementação via MySQL e outra via XML, mas ambas seguindo a mesma estrutura da interface LivroDAO. O padrão Abstract Factory facilita o manuseio quando trabalha com mais de um meio de armazenamento, por isso a centralização neste padrão se dá na distribuição das fábricas, através da classe DAOFactory. Para utilizar a DAOFactory basta acessar estaticamente o método do qual se deseja obter o objeto de acesso. JD Destacar 39 PROGRAMAçÃO JAVA COM JDBC │ UNIDADE II 40 UNIDADE II │ PROGRAMAçÃO JAVA COM JDBC Resume-se que a diferença entre os 3 padrões explicados anteriormente da seguinte maneira: PatternDAO: centraliza-se o acesso aos dados por categoria. DAOFactory: centraliza-se a distribuição dos DAOs AbstractFactory: centraliza-se a distribuição da fábrica de DAOs Singleton O objetivo é gerar SOMENTE UMA instância da classe. Essa classe deve possuir: » Apenas uma instância da classe – Um único construtor privado – Um método que retorne a instância da classe Figura 26: Padrão Singleton. Fonte: Autor Abaixo segue um exemplo de implementação. A classe ConnectionManager é uma classe normal, mas que possui uma variável privada e estática que referencia ela mesma, além de possui um construtor padrão privado. Estas duas características remetem que somente a própria classe pode gerar objetos a partir dela, ou seja, o controle da geração de seus objetos (suas instâncias) está sob o poder da própria classe. Este controle é efetuado a partir do método estático getInstance, do qual valida se existe somente uma instância do objeto em memória. Caso o objeto já exista, então o objetivo é utilizar este objeto. Caso não exista, então um novo objeto é criado e referenciado. Esta lógica permite que somente um objeto em memória esteja ativo, otimizando espaço de memória e também processamento. JD Destacar JD Sublinhar JD Sublinhar JD Sublinhar JD Destacar JD Destacar JD Destacar JD Destacar 41 PROGRAMAçÃO JAVA COM JDBC │ UNIDADE II Este controle é efetuado a partir do método estático getInstance, do qual valida se. Note na figura anterior que para utilizar este padrão, é necessário acessar o método estático getInstance, pois não é possível gerar (ou utilizar) objetos desta classe desta outra maneira, garantindo a otimização do processo. 42 unidAdE iiiJAVA CoM JPA/ HiBErnAtE CAPÍtuLo 1 Estrutura JPA e HAndS on Neste capítulo você conhecerá sobre a estrutura de Mapeamento Objeto-Relacional (MOR). O MOR tem o objetivo de melhorar a produtividade e também o processamento no que tange a relação entre objetos (da Orientação a Objetos) e tabelas (de Banco de Dados Relacional), conforme ilustrado na figura abaixo. Nesta analogia, cada Classe é mapeada para cada Tabela, cada atributo da Classe mapeado com cada coluna da Tabela e cada objeto gerado pela Classe é associado um registro da Tabela. Figura 27: mapeamento Objeto-Relacional (mOR). Fonte: Autor Como pode ser observado nos capítulos anteriores, é altamente necessária a analogia entre classes e tabelas, apesar da formas diferentes de implementação, onde as tabelas se comunicam via chaves estrangeiras, enquanto as classes de comunicam entre as referências das classes. Na programação via JDBC, este processo de manipulação de dados das tabelas para as classes e vice-versa se torna bastante manual e requer bastante programação, o que onera a produtividade tão necessária ao mercado de desenvolvimento. Com o objetivo de melhorar a otimização de tempo e também a melhora no consumo de processamento, alguns modelos surgiram, tal como Hibernate, iBatis, JDO, entre outros. O grande objetivo destes modelos é o de retirar toda a linguagem SQL do Java e centralizá-la em outro local. JD Destacar JD Sublinhar JD Destacar JD Destacar JD Destacar 43 JAVA COM JPA/HIBERNATE │ UNIDADEIII O antigo framework iBatis, hoje convertido para MyBatis, por exemplo, permite que todo o código SQL seja implementado em arquivos XML ou ainda através de Anotações (veja mais em http:// pt.wikipedia.org/wiki/Annotation_(java)). Desta forma, o programa de acesso a dados passa a conter somente código em Java e que fica diretamente mapeado a seus respectivos acessos agora centralizados. Já o Hibernate Framework, certamente o mais utilizado pelos desenvolvedores, surgiu com o propósito de realizar o mapeamento efetivo entre classes e tabelas já diretamente na programação. Em suas primeiras versões eram utilizados arquivos XML para cada relação classe-tabela, realizando um processo de de-para, onde é sintetizado que a classe X possui relação com a tabela X, e que o atributo Y da classe X, possui relação com a coluna Y da tabela X, e assim sussecivamente. Este processo permitiu que as características maiores de Banco de Dados Relacional, tais como associações, chaves primárias e secundárias, sequence, mapeamentos relacionais (um-para-um, um-para-muitos, muitos-para-um e muitos-para-muitos), passassem a ser realizados em XML. No exemplo abaixo é possível perceber o quanto o XML relacionava classes de tabelas. Figura 28: Hibernate via Xml. Fonte: Autor Já em suas versões seguintes, o Hibernate passou a utilizar Anotações, ou seja, uma meta-programação (programação dentro da programação), eliminando assim a necessidade de se trabalhar com tantos arquivos XML. Desta maneira, o que já era bom ficou ainda melhor, conforme exemplo abaixo: 44 UNIDADE III │ JAVA COM JPA/HIBERNATE Note que as Anotações @Entity, @Table, @Id, @GeneratedValue, @Column e @OneToMany, permitem que o mapeamento seja realizado e que configurações usuais de banco de dados sejam efetivados a partir da própria classe. Estrutura JPA Mas de fato, o que é o JPA? É o mesmo que MOR? É o mesmo que Hibernate? Para todas as questões a resposta é NÃO. O JPA (Java Persistence API) é nada mais do que uma especificação que padroniza o mecanismo de persistência MOR e pode ser implementada por diversos fabricantes de MOR. O Hibernate, por exemplo, é uma implementação de JPA. Outra implementação bastante utilizada no mercado é o EclipseLink. Com a estrutura JPA, as implementações se tornam padronizadas, evitando que o programador tenha que alterar código caso o framework seja alterado. Mas para que isso de fato ocorra, é importante que a programação seja feita pelos comandos JPA. Quando citado em comandos JPA, significa a utilização de métodos da API e da linguagem de consulta específica chamada JP-QL (Java Persistence Query Language). Isso mesmo! Ao invés de utilizar o SQL universal, é utilizada uma extensão “javanesa” do SQL, permitindo que queries complexas sejam desenvolvidas a partir do próprio Java. O JPA contém a seguinte estrutura: » Entity Manager: Unidade central para gerenciamento de entidades na JPA através de uma API padronizada. Responsável pela criação, atualização, remoção e consulta às entidades (CRUD), pelo controle de transações e pelo gerenciamento de cache. » Unidade de Persistência: conjunto fixo de classes mapeadas para o banco de dados e registradas no arquivo persistence.xml. » Contexto de Persistência: conjunto de instâncias de entidades gerenciadas de um Entity Manager; » Entidade Gerenciadas: quando entidades estão associadas a um contexto de persistência. As alterações no estado das entidades são sincronizadas com o banco de dados. Ao fechar um contexto de persistência, todas suas instâncias de entidades associadas tornam-se não gerenciadas; » Entidade Não Gerenciadas: entidades não associadas a um contexto de persistência (por exemplo quando são instanciadas). As alterações nas entidades não se refletem no banco de dados. » Estados da entidade, que pode ser compreendido pela figura a seguir: » new: instância da entidade criada em memória mas não associada a um contexto de persistência e não possui id equivalente no banco de dados; JD Destacar JD Sublinhar JD Destacar JD Sublinhar 45 JAVA COM JPA/HIBERNATE │ UNIDADE III » managed: tem um id no banco de dados e está associada a um contexto de persistência; » detached: tem um id no bando de dados mas não está associada ao contexto de persistência; » removed: instância da entidade associada a um contexto de persistência mas está programada para ser removida do banco de dados. Figura 29: Diagrama de Estados Entidade. Fonte: Autor HAndS on com implementação HiBErnAtE O JPA possui diversas implementações, dentre as quais a mais utilizada é o Hibernate. Como toda grande estrutura, o JPA/Hibernate possui vantagens e desvantagens, são elas: Vantagens: » Contempla modelo natural de programação OO; » Aceleração do desenvolvimento (poupa trabalho manual de conversão de dados relacionais para objetos); » Transparência de banco de dados; » Performance (cache); » Simplicidade; » Compatibilidade com os principais bancos de dados de mercado Desvantagens: » Não é a melhor opção para todos os tipos de aplicação. Sistemas que fazem uso extensivo de stored procedures, triggers ou que implementam a maior parte da 46 UNIDADE III │ JAVA COM JPA/HIBERNATE lógica de negócio no banco de dados (modelo pobre) não vai se beneficiar com o uso do Hibernate. Ele é indicado para sistemas que contam com um modelo rico, onde a maior parte da lógica de negócios fica na própria aplicação dependendo pouco de funções específicas do banco de dados; » Consultas muito complexas e extensas exigem grau avançado de conhecimento da API (ajustes finos). Uma das grandes vantagens do JPA/Hibernate, além da produtividade, é trabalhar com níveis de cache, representados na figura abaixo. Uma vez podendo trabalhar com informações em cache, e mais do que isso, configurar quando e como as informações ficam em cache, permite a economia de processamento junto ao banco de dados o que gera impacto direto na velocidade que o usuário final tem no acesso ao sistema. O cache de primeiro nível é o cache básico de sessão, mas que já permite grandes otimizações via processos de FETCH LAZY e FETCH EAGER, onde o processo LAZY, cujo tradução é “preguiçoso”, realiza o armazenamento das informações somente quando solicitada a consulta ao banco de dados. Já o processo EAGER, cuja tradução é “ansioso”, realiza o armazenamento das informações completas em memória, não necessitando nova consulta diretamente ao banco de dados e sim somente em memória. O cache de segundo nível é cache configurável, onde é possível, dentre tantas opções, configurar o tempo de permanência em memória das informações, a quantidade de dados a serem armazenados, processos transacionais. Todas estas possibilidades permitem um acesso mais performático ao banco de dados, refletindo diretamente em economia de tempo par ao usuário final, como citado anteriormente. Para implementar cache de segundo nível, existem bibliotecas disponíveis, tais como EhCache, OSCache, Jboss Cache, entre outros provedores de cache. Note que nem sempre é viável utilizar o processo de armazenamento em cache. Imagine o processo de compra de e-commerce. É melhor termos as informações totalmente atualizadas em tempo real do banco de dados ou tê-las previamente armazenadas? Qual a melhor opção? Figura 30: Cache. Fonte: Autor 47 JAVA COM JPA/HIBERNATE │ UNIDADE III Passo a passo - inicial Para realizar o passo a passo de instalação e execução da dupla JPA/Hibernate, siga o conteúdo anexo na plataforma. Para auxiliar no Passo a Passo e nas suas demais interações com o framework ORM, segue abaixo a “Cartilha” necessária para este entendimento. Para iniciar, vamos entender as principaisAnnotations, localizada no pacote javax.persistence e suas respectivas funções: Localizadas no pacote javax.persistence ; @Entity: especifica que uma classe é uma entidade. Exemplo: @Entity public class ClienteEntity { private int id; private String nome; // métodos get e set } @Table: especifica a tabela associada à entidade no banco de dados. Caso não definido assume-se que a tabela terá o mesmo nome da classe da entidade; Exemplo: @Entity @Table(name=“TAB_CLIENTE”) public class ClienteEntity { private int id; private String nome; // métodos get e set } @Column: especifica o campo associada ao atributo da entidade. Caso não definido assume-se que o campo terá o mesmo nome do atributo. Parâmetros: Name: nome do campo; Unique (default false): não permite duplicidade; Nullable (default false): não permite valores nulos; Insertable (default true): atributo utilizado em operações de INSERT; Updatable (default false): atributo utilizado em operações de UPDATE; JD Destacar JD Destacar JD Destacar 48 UNIDADE III │ JAVA COM JPA/HIBERNATE Exemplo: @Entity @Table(name=“TAB_CLIENTE”) public class ClienteEntity { @Column(name=“COD_CLIENTE”) private int id; @Column(name=“NOM_CLIENTE”, nullable=false) private String nome; // métodos get e set } @Id: atributo que identificará unicamente as instâncias da entidade. Deve-se sempre definir o atributo que representará a chave primária. Exemplo: @Entity @Table(name=“TAB_CLIENTE”) public class ClienteEntity { @Id @Column(name=“COD_CLIENTE”) private int id; @Column(name=“NOM_CLIENTE”, nullable=false) private String nome; // métodos get e set } @GeneratedValue: especifica a estratégia de geração de valores para atributos que são chave primária. Parâmetros: Strategy: indica o tipo de estratégia utilizada; Generator: nome do gerador de chaves; Tipos mais comuns: GeneratorType.SEQUENCE: baseado em sequence; GeneratorType.IDENTITY: campos identidade; @SequenceGenerator: define um gerador de chave primária baseado em sequence de banco de dados. Possui uma associação com o @GeneratedValue. Parâmetros: Name: nome a ser referenciado pelo @GeneratedValue ; sequenceName: nome da sequence de banco de dados; allocationSize (default 50): incremento JD Destacar JD Retângulo JD Destacar JD Destacar 49 JAVA COM JPA/HIBERNATE │ UNIDADE III Exemplo: @Entity @SequeceGenerator(name=“cliente”, sequenceName=“SEQ_CLIENTE”, allocationSize=1) @Table(name=“TAB_CLIENTE”) public class ClienteEntity { @Id @GeneratedValue(strategy=GeneratorType.SEQUENCE, generator=“cliente”) @Column(name=“COD_CLIENTE”) private int id; @Column(name=“NOM_CLIENTE”, nullable=false) private String nome; // métodos get e set } @Transient: Indica que determinado atributo não deve ser persistido. Exemplo: @Entity @Table(name=“TAB_CLIENTE”) public class ClienteEntity { @Id @Column(name=“COD_CLIENTE”) private int id; @Column(name=“NOM_CLIENTE”, nullable=false) private String nome; @Transient private int chaveAcesso; } @Temporal: Especifica o tipo de dado a ser armazenado em atributos do tipo Date e Calendar. Parâmetros: value: » TemporalType.TIMESTAMP: data e hora; » TemporalType.DATE: somente data; » TemporalType.TIME: somente hora; @Entity @Table(name=“TAB_CLIENTE”) public class Cliente { @Id 50 UNIDADE III │ JAVA COM JPA/HIBERNATE @Column(name=“COD_CLIENTE”) private int id; @Column(name=“DAT_NASCIMENTO”) @Temporal(value=Temporaltype.DATE) private Date dataNascimento; // ... Métodos get / set } @PersistenceContext: utilizar a anotação @PersistenceContext para obter, via injeção de dependência, uma instância que implemente a interface EntityManager. Exemplo: public class ClienteBean ... { @PersistenceContext EntityManager manager = null; } Mapeamentos @OneToMany: utilizar a anotação @OneToMany no atributo que representa a associação. Utilizar o atributo cascade para indicar: CascadeType.ALL: todas as operações na entidade pai serão refletidas na(s) filho(s); CascadeType.MERGE: somente operação de merge será refletida; CascadeType.PERSIST: somente operação de persist será refletida; CascadeType.REFRESH: somente operação refresh será refletida; CascadeType.REMOVE: somente operação remove será refletida; Pode-se combinar vários tipos: @OneToMany(cascade={CascadeType.MERGE, CascadeType.REMOVE}) Utilizar a anotação @JoinColumn em conjunto com @OneToMany para indicar o nome da coluna que representa a chave estrangeira na tabela filho. Pode ser utilizada em uma associação unidirecional; Exemplo: public class NFEntity { ... @OneToMany(cascade=CascadeType.ALL) @JoinColumn(name=“COD_NF”) private Collection<NFItemEntity> itens; ... } JD Destacar JD Destacar JD Destacar 51 JAVA COM JPA/HIBERNATE │ UNIDADE III public class NFItemEntity { ... } A anotação @ManyToOne pode ser utilizada para indicar que uma associação bidirecional. Nas associações bidirecionais existe uma referência tanto do pai para o filho quanto do filho para o pai. Na entidade pai utilizar o atributo mappedBy para indicar o nome do atributo no filho que representa a ligação com o pai. Dispensa o uso de @JoinColumn na entidade pai, uma vez que a mesma é definida na entidade filho. public class NFEntity { ... @OneToMany(cascade=CascadeType.ALL, mappedBy=“nf”) private Collection<NFItemEntity> itens; ... } public class NFItemEntity { ... @ManyToOne @JoinColumn(name=“COD_NF”) private NFEntity nf; ... } @ManyToMany: utilizada para representar associações M:N. Possui o mesmo atributo cascade da anotação @OneToMany. Utilizar a anotação @JoinTable associada para referenciar a tabela associativa e os campos de chave estrangeira: name: nome da tabela associativa; joinColumns: colunas de chave estrangeira que referenciam a entidade diretamente. inverseJoinColumns: colunas de chave estrangeira que referenciam a entidade no outro lado da relação. Utiliza-se a anotação @JoinColumn para definir as referências diretas e inversas: name: nome da coluna de chave estrangeira; public class CursoEntity { ... @ManyToMany @JoinTable(name=“TAB_ALUNO_CURSO”, joinColumns=@JoinColumn(name=“COD_CURSO”), inverseJoinColumns=@JoinColumn(name=“COD_ALUNO”)) private Collection<AlunoEntity> alunos; ... } JD Destacar JD Sublinhar JD Destacar JD Destacar JD Destacar 52 UNIDADE III │ JAVA COM JPA/HIBERNATE Chaves compostas podem ser representadas através de uma classe com a anotação @Embeddable. A classe de chave primária deve ser utilizada como se fosse um @Id , só que com a anotação @EmbeddedId. Esta classe deve ser serializable. Deve implementar os métodos equals(Object) e hashCode(). @Embeddable public class MatriculaID implements Serializable { @ManyToOne @JoinColumn(name=”COD_ALUNO”) private Aluno aluno; @ManyToOne @JoinColumn(name=”COD_CURSO”) private Curso curso; public MatriculaID(){ } public MatriculaID(Aluno aluno, Curso curso){ this.aluno = aluno; this.curso = curso; } // get e set @Override public boolean equals(Object arg0) { return super.equals(arg0); } @Override public int hashCode() { return super.hashCode(); } } @Entity @Table(name=”TAB_ALUNO_CURSO”) public class Matricula { @EmbeddedId private MatriculaID id; @column(name=“DAT_MATRICULA”) private Date data; // get e set } JD Destacar JD Destacar 53 JAVA COM JPA/HIBERNATE │ UNIDADE III APi EntitYMAnAgEr Abaixo são apresentados todos os métodos do EntityManager, responsáveis pelos processos transacionais. São eles: persist (Object entity): enfileira entidade para ser inserida uma entidade no banco de dados e a torna gerenciada; Exemplo: VeiculoEntity veiculo = new VeiculoEntity(); veiculo.setPlaca(“DHZ-5678”); veiculo.setModelo(“Fusca”); manager.persist(veiculo); merge (Object entidade): atualiza uma entidade não gerenciada no contexto de persistência. Caso já exista uma entiade gerenciada com o mesmo id realiza uma operação de UPDATE. Caso contrário realiza uma operação de INSERT; A entidade torna-se gerenciada; Exemplo: VeiculoEntity veiculo = new VeiculoEntity(); veiculo.setPlaca(“DHZ-5678”); veiculo.setModelo(“Fusca”); manager.merge(veiculo); refresh (Object entidade): atualiza dados da entidade com base no banco de dados. Valores não persistidos são descartados. A entidade torna-se gerenciada. Exemplo: VeiculoEntity veiculo = new VeiculoEntity(); veiculo = manager.find(VeiculoEntity.class, 1); veiculo.setPlaca(“DHZ-5678”); veiculo.setModelo(“Fusca”); manager.refresh(veiculo); find (Class classeEntidade, Object PK): localiza uma entidade através de sua chave primária (PK). Retorna null caso a entidade não seja localizada. Uma entidade localizada torna-se automaticamente gerenciada. Exemplo: // Busca veiculo com id igual a 10 VeiculoEntity veiculo = manager.find(VeiculoEntity.class, 10); veiculo.setPlaca(“HHH-7777”); JD Destacar JD Destacar JD Destacar JD Destacar JD Destacar JD Destacar 54 UNIDADE III │ JAVA COM JPA/HIBERNATE remove (Object entidade): remove uma entidade acoplada. Para excluir entidades desacopladas primeiro deve-se localizá-la através do método find ou getReference; Exemplo: VeiculoEntity veiculo = manager.find(VeiculoEntity.class, 10); manager.remove(veiculo); Para operações mais exatas existem a possibilidade da utilização da linguagem de consulta específica para JPA, chamada JP-QL (Java Persistence – Query Language). O JP-QL define todas as operações necessárias para se criar consultas. Permite também efetuar operação como delete e update. Para se construir uma consulta, utilizar método createQuery da interface EntityManager: ... EntityManager manager = ... Query q = manager.createQuery(“SELECT c FROM ClienteBean c”); List<ClienteBean> clientes = q.getResultList(); ... Para se definir parâmetros em uma consulta deve-se utilizar o método setParameter da interface Query. Os parâmetros na consulta deve ser identificado por “:”; ... EntityManager manager = ... Query q = manager.createQuery(“SELECT c FROM ClienteBean c WHERE c.nome like :nome”); q.setParameter(“nome”, “João”); List<ClienteBean> clientes = q.getResultList(); ... onde: getResultList(): retorna uma lista com os resultados da execução da consulta; getSingleResult(): retorna um único objeto (para querys que retornam apenas uma linha); setMaxResults(int max): número máximo de registros a serem recuperados; setParameter(String nome, Object valor): define o parâmetro chamado nome com o valor especificado; setParameter(String nome, Date data, Temporaltype tipo): define o parâmetro chamado nome com uma data; Consultas podem ser definidas junto aos entity beans e posteriormente referenciadas pelo nome. Utilizar a anotação @NamedQuery : name: nome de identificação da consulta; query: consulta em si; 55 JAVA COM JPA/HIBERNATE │ UNIDADE III ... @Entity @NamedQuery (name = “qCliente”, query = “SELECT c FROM ClienteBean WHERE c.nome like :nome”) 56 Para (não) finalizar As diversas implementações de acesso a banco de dados A busca por conhecimento nunca cessa. Diversos modelos computacionais surgem a cada dia, mas o core continua sendo o mesmo, onde comandos, instruções e processos devem ser seguidos. Neste material foi facilmente percebido que desde os princípios de JDBC até a produtividade de JPA/Hibernate, algumas atividades nunca mudam, como: abrir conexão, realizar a comunicação (conversar com o banco de dados) e fechar, gerantindo a persistência do processo. O que vem sendo modificado no decorrer dos anos é a otimização na produção, onde uma seqüência grande de instruções é resumida a pequenos componentes, ou seja, funções antes longas e repetitivas passam a ser centralizadas e componentizadas. Mediante a este cenário, faz-se uma reflexão: o programador de hoje deverá ter o mesmo conhecimento do programador de amanhã? E os sistemas já existentes e construídos em tantos diferentes modelos, serão adaptados a novos modelos produtivos ou a famosa frase: “Time que está ganhando não se mexe” deve ser efetivada? Eis o futuro. Eis alguns dos vários questionamentos que a programação também requer atenção. Navegue nestas e em outras questões próprias e entenda como sua participação pode ser importante nesta evolução. 57 referências BAUER, Christian; KING, Gavin. Hibernate in Action. USA: Manning Publications, 2004. BAUER, Christian; KING, Gavin. Java Persistence with Hibernate. USA: Manning Publications, 2006. BEGIN, Clinton; GOODIN, Brandon; MEADORS, Larry. Ibatis in Action. USA: Manning Publications, 2006. FISHER, Maydene; ELLIS, Jon; BRUCE, Jonathan. JDBC API Tutorial and Reference. USA: Addison-Wesley Professional, 2003. KEITH, Mike; SCHINCARIOL, Merrick. Pro EJB 3 – Java Persistence API. Apress, 2006. REESE, George. Database Programming With JDBC and Java. USA: O’Reilly, 2000. SPEEGLE, Gregory D. JDBC: Practical Guide for Java Programmers (The Practical Guides). USA: Paperback, 2001. WILLIAMSON; ALAN Moran. Java Database Programming: Servlets & JDBC. São Paulo: Pearson, 2000.
Compartilhar