Mostrando postagens com marcador jpa. Mostrar todas as postagens
Mostrando postagens com marcador jpa. Mostrar todas as postagens

sexta-feira, 28 de outubro de 2016

Tagged under: ,

JPA Hibernate – Como funciona a anotação @version?


Recentemente um colega de trabalho me perguntou qual era função da anotação @version presente nas entidades aqui do projeto. Achei interessante essa pergunta.
Para responder essa de pergunta temos que lembrar que todo banco de dados possui um controle de concorrência entre transações (se necessário solicitem nos comentários que faço um post explicando a fundo sobre isso). Para esse post só precisamos conhecer o método de controle Optimistic concurrency control (controle de concorrência otimista).
Optimistic concurrency control (OCC)
Optimistic concurrency control ou controle de concorrência otimista é um método aplicado nas transações de bancos de dados relacionais. Nesse método se acredita que a probabilidade de que duas transações utilizarem o mesmo objeto é minima, logo nada é verificado enquanto a transação está sendo executada e isso faz com que o custo dela diminua.
Normalmente essa técnica funciona bem em Frameworks ORM porque eles conseguem escalonar as transações para que ocorra pouca ou nenhuma interferência. Mas no caso de ocorrer uma interferência o que acontece? Simples, alguma transação escolhida pelo Hibernate vai ser abortada e terá que ser recomeçada pelo cliente.
A anotação @version
Agora que sabemos superficialmente o que é um controle de concorrência e o método OCC fica mais fácil compreender a importância do @version em nossas entidades. Tenha em mente que ao adicionar um atributo com essa anotação não precisamos nos preocupar em alterar seu valor porque o Hibernate fica encarregado dessa função.
Para usarmos o método de concorrência otimista só precisamos declarar um atributo com o nome version em nossa entidade. Normalmente ele é do tipo numérico e também pode ser do tipo data, mas não recomendo essa pratica e vou explicar o motivo no final deste post, abaixo temos um exemplo da classe Consulta.
  1. @Entity
  2. @Table(name = "CONSULTAS", schema = "tableless")
  3. public class Consultas{
  4. @Id
  5. @GeneratedValue(strategy = GenerationType.AUTO)
  6. @Column(name = "ID_CONSULTA")
  7. private Integer numero;
  8.  
  9. @Temporal(TemporalType.TIMESTAMP)
  10. @Column(name = "DATA_CONSULTA")
  11. private Date dataConsulta;
  12.  
  13. @ManyToOne(fetch = FetchType.LAZY)
  14. @JoinColumn(name = "PACIENTE_CODIGO")
  15. private Pacientes paciente;
  16.  
  17. @Version
  18. private Integer version;
  19.  
  20. //getter e setter
  21. }
Com esse mapeamento o Hibernate vai usar automaticamente o número da versão para verificar se o objeto utilizado na transição foi atualizado desde a ultima vez em que ele foi requisitado. Pelo código SQL a baixo podemos ver a presença do atributo version tanto no trecho do SET como na cláusula WHERE isso acontece porque o Hibernate vai buscar o objeto no banco de dados usando também o número da versão e vai incrementar esse número ao mesmo tempo.
  1. UPDATE CONSULTAS
  2. SET DATA_CONSULTA = ?, PACIENTE_CODIGO = ?, version = ?
  3. WHERE ID_CONSULTA = ?
  4. AND version = ?
@version com Data
Usar um tipo data no atributo version é uma prática que não recomendo porque no banco de dados a coluna será do tipo TIMESTAMP e isso pode acabar permitindo que duas ou mais transações possam ser executadas com o mesmo objeto ao mesmo tempo dependendo da precisão do fuso horário configurada no banco de dados, caso essa situação acabe acontecendo vamos acabar tendo uma violação de normalização. Algumas pessoas preferem utilizar o tipo data para conseguirem visualizar “quando” aquele objeto foi alterado pela ultima vez, caso essa seja sua necessidade recomendo que crie um novo atributo em sua classe ao invés de utilizar a anotação @version como data.
Por fim espero que esse post te ajude a trabalhar com controle de concorrência no Hibernate. Dúvidas, sugestões, correções, elogios nos comentários ou no meu twitter.

segunda-feira, 25 de julho de 2016

Tagged under: ,

JPA de A à Z - Por que conhecer?

Não dá pra negar que o Java é uma linguagem bastante verbosa e quando falávamos em juntar o Java com um banco de dados ai sim dava pra ver o tamanho do problema.
Se não tivéssemos cuidado era muito fácil perder o controle da complexidade de nossas entidades e consultas.

Antes de entendermos sobre a  JPA, é necessário entender que costumávamos utilizar em nossos projetos o JDBC (Java Database Connectivity) que é uma API presente no Java desde a versão 1.1 da plataforma. Mesmo sendo uma API bem antiga ela ainda continua sendo atualizada e modificada pela comunidade e pela Oracle.

Resumidamente o JDBC é o antecessor da JPA porque ela era a principal forma de executar nossas querys SQL de select, update, delete, insert e até mesmo executar funções presentes no banco de dados. Um detalhe interessante sobre o JDBC são seus Drivers de conexão, sendo cada banco de dados é responsável por desenvolver e atualizar o seu Driver. Isso facilitava muito a vida do desenvolvedor porque esses Drivers visam encapsular boa parte do código necessário para se conseguir uma conexão, então era uma preocupação a menos que tínhamos que ter.

Mas nem tudo eram flores quando usávamos o JDBC, porque além de ter que escrever códigos SQL direto no Java, tínhamos também que instanciar uma conexão, buscar a conexão com o banco de dados. Dai era preciso preparar um outro objeto para poder manipular a consulta informando os valores dos parâmetros e só então executávamos a consulta.

Acabávamos tendo um trabalho tedioso só para executar uma consulta, todavia o ciclo não acabava nisso, depois era preciso fazer um casting do retorno da consulta para com objeto que queríamos manipular e como se não fosse suficiente também era necessário lembrar de fechar as conexões com o banco de dados.
É preciso entender que estamos falando de muito tempo atrás, um tempo em que as facilidades da JPA ainda não existiam e que muita especificação que existe hoje nasceu das dificuldades do passado.

public class ProdutoDAO {

Connection dbConnection;

public ProdutoDAO(Connection con) {
this.dbConnection = con;
}

public void salva(Produto produto) throws SQLException {
String sql = "INSERT INTO PRODUTO (NOME, DESCRICAO) VALUES (?,?)";

try (PreparedStatement prStmt = dbConnection.prepareStatement(sql,
Statement.RETURN_GENERATED_KEYS)) {

prStmt.setString(1, produto.getNome());
prStmt.setString(2, produto.getDescricao());
prStmt.execute();

try (ResultSet rs = prStmt.getGeneratedKeys()) {
if (rs.next()) {
int id = rs.getInt(1);
produto.setId(id);
}
}

}
}

public List lista() throws SQLException {
List produtos = new ArrayList();

String sql = "SELECT * FROM PRODUTO";

try (PreparedStatement prStmt = dbConnection.prepareStatement(sql)) {
prStmt.execute();

converterQueryEmProdutos(produtos, prStmt);
}

return produtos;
}

public List busca(Produto produto) throws SQLException {

String sql = "SELECT * FROM PRODUTO WHERE DESCRICAO like ?";
List produtos = new ArrayList();

try (PreparedStatement prdStmt = dbConnection.prepareStatement(sql)) {
prdStmt.setString(1, produto.getDescricao);
prdStmt.execute();

converterQueryEmProdutos(produtos, prdStmt);
}

return produtos;
}

private void converterQueryEmProdutos(List produtos, PreparedStatement prdStmt) throws SQLException {

try (ResultSet rs = prdStmt.getResultSet()) {
while (rs.next()) {
int id = rs.getInt(1);
String nomeProduto = rs.getString("nome");
String descricaoProduto = rs.getString("descricao");
Produto produto = new Produto(nomeProduto, descricaoProduto);
produto.setId(id);
produtos.add(produto);
}
}
}
}

Olhando pra esse código podemos passar um baita sufoco se por acaso algum dia o analista de requisitos resolva mexer nos atributos da entidadeProduto. Nessa DAO de exemplo só foi criada poucas consultas, mas vamos usar nossa criatividade e imaginar que na verdade existem 10 e o analista resolveu mudar o nome da coluna "DESCRICAO" para "TIPO_PRODUTO", uma pequena mudança de nomenclatura já é suficiente para que perdêssemos tempo refatorando boa parte de nosso código.

Foi para evitar todo esse trabalho que surgiu o conceito ORM (Object Relational Mapping) que traduzindo livremente de acordo com a minha vontade quer dizer: “Estou salvando a sua alma transformando os dados de um banco de dados que estão no paradigma relacional para o paradigma orientado a objetos que você tanto precisa”.

Junto com a ORM também surgiu o Hibernate que é o framework JPA mais famoso e utilizado no momento. Só por curiosidade saiba que a JPA surgiu por causa dele, viram que a ideia era tão boa que resolveram transformar a implementação do Hibernate em uma especificação e até hoje muita coisa que é implementada no framework posteriormente vira especificação na JPA.

Mas o que é JPA?

JPA significa Java Persistence API e como já falei ela é uma especificação que nasceu de uma JSR (Java Specification Requests) que basicamente são pedidos para mudanças na linguagem, entenda a JPA como um contrato, normas, regras ou interface e que todos os Frameworks Java que trabalham com persistência de dados devem implementa-la. Além do Hibernate também temos outros Framworks como por exemplo o OpenJPA, o Batoo e o EclipseLink.

Então basicamente a JPA é uma especificação que regulamenta ferramentas muito poderosas que utilizamos no nosso dia a dia para automatizar e economizar tempo de desenvolvimento. Essa especificação nos ajuda em todos os processos quando precisamos trabalhar com um banco de dados, sendo assim podemos usa-la para executar consultas, inserts, updates e deletes.

Lembra daquele código verboso? Como sera que ele ficaria se fosse escrito utilizando a JPA?

 
public Produto obterPorId(Produto produto) {
return manager.find(Produto.class, produto.getId());
}

@SuppressWarnings("unchecked")
public List obterTodos() {
return manager.createQuery("SELCT p FROM Produto p").getResultList();
}

Repare que no método obterPorId não foi necessário criar uma única query SQL para executar a consulta por ID, também não foi preciso fazer nenhum casting a JPA se encarregou de fazer tudo isso pra gente. Agora olhando o método obterTodos temos uma String que se parece muito com uma query SQL só que não é, a essa String damos o nome de JPQL (Java Persistence Query Language) e vamos conhecer mais sobre ela em outro momento.

Por fim espero que você nos acompanhe nos próximos posts porque vamos aprender mais sobre essa ferramenta poderosa em conjunto com boas práticas. A ideia é de que os posts não sejam muito longos e também não sejam só tutorias de JPA, aqui iremos explorar os conceitos, apresentar exemplos e colocar minha experiência em ação com as boas práticas.

sábado, 28 de junho de 2008

Tagged under: , , , , ,

ZK: Ajax sem JavaScript no NetBeans - Parte 2

Na 2a parte do nosso tutorial vamos usar o NetBeans 6.1 para criar uma tabela no JavaDB e automaticamente gerar uma classe de entidade correspondente no padrão JPA. Ao final, exibiremos as informações em uma página index.zul.

Comece abrindo o projeto ListaTafefas que criamos na parte 1. Na aba Services, do lado esquerdo, clique com o botão direito em JavaDB e escolha CreateDatabase. Chame o banco de dados de Tafefas, usuário e senha javabahia e escolha a localização do BD no seu computador. Logo abaixo, aparecerá uma linha jdbc:derby://localhost:1527/Tarefas. Clique com o botão direito e escolha Connect. Pronto! O banco está criado, porém ainda não temos nenhuma tabela.

Criando o banco de dados Tarefas no JavaDB

Clique com o botão direito no folder Tables e escolha Execute Command. Na área de edição, será aberta uma aba que permite a execução de comandos SQL. Copie e cole o comando a seguir e mande executar (Ctrl+Shift+E):
create table TAREFA(
ID INTEGER GENERATED ALWAYS AS IDENTITY not null primary key,
NOME VARCHAR(50),
PRIORIDADE INTEGER,
DATA_TAREFA DATE);
INSERT INTO Tarefa(NOME,PRIORIDADE,DATA_TAREFA) VALUES ('Comprar passagens', 1, '07/10/2008');
INSERT INTO Tarefa(NOME,PRIORIDADE,DATA_TAREFA) VALUES ('Reservar hotel', 2, '07/15/2008');
INSERT INTO Tarefa(NOME,PRIORIDADE,DATA_TAREFA) VALUES ('Alugar carro', 3, '07/25/2008');
INSERT INTO Tarefa(NOME,PRIORIDADE,DATA_TAREFA) VALUES ('Arrumar bagagens', 3, '07/30/2008');
INSERT INTO Tarefa(NOME,PRIORIDADE,DATA_TAREFA) VALUES ('Tirar férias', 1, '09/01/2008')
Será criada uma tabela com 4 campos, tendo o ID como chave primária, gerada automaticamente. Também serão adicionados 4 registros, para utilizarmos na hora de listá-los (observe que as datas estão no formato MM/DD/AAAA). Agora vamos aprender a usar o Java Persistence API, que provê um padrão para mapeamento objeto relacional. Na árvore do projeto, clique com o botão direito em Source Packages e escolha New -> Entity Classes from Database. Abra a combo em Data Source e escolha New. Informe jdbc/tarefas no campo JDNI Name e jdbc:derby://localhost:1527/Tarefas em Data Base Connection. Após clicar em OK a tabela TAREFA aparecerá disponível na lista. Selecione-a e clique em Add e em seguida Next.

Criando Entity Classes a partir de um banco de dados

Na tela seguinte, informe javabahia.beans no campo Package e clique no botão Create Persistente Unit. Aceite os valores default (será usado o TopLink como provider, mas você poderia escolher outro de sua preferência, como Hibernate ou OpenJPA) e clique em Create para gerar a ListaTarefasPU. De volta a tela anterior, clique em Finish e será criada a classe Tarefa, já com todas as anotações no padrão JPA, e o arquivo persistence.xml com as definições da Persistence Unit. Abra Tarefa.java e adicione @GeneratedValue(strategy=GenerationType.IDENTITY) logo abaixo de @Id, o que provocará a geração automática da chave primária da tabela. Adicione também o método public String getDataTarefaAsString() { return new SimpleDateFormat("dd/MM/yyyy").format(dataTarefa); }, que será utilizado mais à frente para obter a data da tarefa no formato dia/mês/ano. Execute um Fix Imports (Ctrl+Shift+I) para não dar erro de compilação. Na pasta Configuration Files, dê um duplo clique em persistence.xml e desmarque a opção Include All Entity Classes in "ListaTarefas" Module. Clique no botão Add Class e inclua javabahia.beans.Tarefa.

Editando a classe Tarefa.java, criada automaticamente pelo NetBeans

Agora já podemos editar o arquivo index.zul para acessar as informações no nosso banco de dados. Altere-o para o conteúdo listado a seguir. Observe que dentro da tag zscript escrevemos puramente código Java. Usamos a classe JpaUtil para obter um EntityManager referenciando pelo nome a Persistence Unit criada anteriormente. Com a tag listitem o atributo forEach realiza as iterações na lista de tarefas já obtida. Em listcell usamos Expression Language (EL) para obter o conteúdo de cada campo. Viu como é fácil?
<?xml version="1.0" encoding="UTF-8"?>
<window title="Lista de Tarefas" width="800px" border="normal">
<zscript>
import javabahia.beans.Tarefa;
import java.util.ArrayList;
import javax.persistence.EntityManager;
import org.zkoss.zkplus.jpa.JpaUtil;

private static EntityManager em = JpaUtil.getEntityManager(
"ListaTarefasPU");
List listaTarefas = em.createQuery(
"SELECT t FROM Tarefa t").getResultList();
</zscript>
<listbox id="box" multiple="true" rows="4">
<listhead>
<listheader label="Tarefa" />
<listheader label="Prioridade" width="90px" />
<listheader label="Data" width="90px" />
</listhead>
<listitem forEach="${listaTarefas}" value="${each}">
<listcell label="${each.nome}"/>
<listcell label="${each.prioridade}"/>
<listcell label="${each.dataTarefaAsString}"/>
</listitem>
</listbox>
</window>
Execute a aplicação o NetBeans se encarregará de compilar tudo, efetivar o deploy no Glassfish e abrir o navegador padrão na página da aplicação. Você verá tabela listando todos os itens previamente cadastrados no banco de dados. No próximo post iremos melhorar este exemplo, criando uma aplicação totalmente funcional. Novamente lembramos que esse é um exemplo adaptado de um tutorial da página oficial do ZK, então você já tem uma boa referência para incrementar já sua Lista de Tarefas.

Usando ZK com JPA para listar as Tarefas armazenadas no JavaDB

domingo, 15 de junho de 2008

Tagged under: , , , , , ,

ZK: Ajax sem JavaScript no NetBeans - Parte 1

Em um dos posts sobre o JavaOne comentei ter visto um framework impressionante chamado ZK. Conversei alguns minutos com Henri Chen, autor de um livro sobre o assunto, e prometi a mim mesmo que arranjaria um tempo para conhecer melhor a solução, pois fiquei bastante curioso.


Henri Chen e seu livro sobre ZK

O principal objetivo do ZK é permitir que aplicações web tenham a mesma interatividade e riqueza encontradas desktop, só que isso deve ser o mais fácil possível para o desenvolvedor. Ele inclui um Ajax-based event-driven engine, um conjunto rico de componentes XUL e XHTML e uma linguagem de marcação (markup language). Para ter uma noção do que é possível sugiro dar uma olhada no live demo e uma navegada na página do projeto em zkoss.org.

Para experimentar o ZK eu precisava de uma aplicação exemplo. Resolvi me basear num Lista de Tarefas (Todo list) criada em um Tutorial Passo a Passo para iniciantes do ZK, em português (Veja ao vivo). Como não tenho colocado a mão na massa com desenvolvimento Web ultimamente, procurei facilitar minha vida e encontrei no SourceForge o REM - A NetBeans Module for ZK, ou seja, um plugin ZK para o NetBeans.

Nessa 1a parte, vamos aprender a instalar o plugin e criar um projeto usando o ZK. Na 2a criaremos uma tabela no JavaDB, a classe de entidade correspondente usando JPA e exibiremos as informações em uma página. Na 3a parte vamos implementar a inclusão, exclusão e alteração de informações, chegando a uma aplicação 100% funcional.

Primeiro baixe a versão 1.5.0 (um arquivo ZIP), e adicione o plugin ao NetBeans 6.1 (Para isso, vá no menu Tools -> Plugins, aba Downloaded, clique em Add Plugins e selecione o arquivo net-sf-rem.nbm na pasta onde você descompactou o arquivo baixado. Clique em Install e siga confirmando até concluir).

Instalando o REM NetBeans Module for ZK

Agora crie um projeto para ver como usar o ZK no NetBeans. Escolha File -> New Project -> Web / Web Application e clique em Next. Chame o projeto de ListaTarefas e escolha Next. Escolha o Server de sua preferência (estou usando o Glassfish V2) e siga em frente. A última tela pedirá para escolher os frameworks que você deseja usar na aplicação. Selecione ZK 3.0.1 e clique em Finish.

Criando um projeto Web no NetBeans usando o ZK

Será criado um projeto Java/Web com toda a estrutura de pastas e prontas para deploy. Em Web Pages, Observe o arquivo principal index.zul, contendo apenas o trecho código:
<?xml version="1.0" encoding="UTF-8"?>
<window>
My ZK application
</window>
Se você clicar em Run terá uma aplicação funcional, mostrando uma página com o texto My ZK application.

Aplicação ZK básica feita no NetBeans

Temos nosso ponto de partida, então você já pode começar a desenvolver para Web usando o ZK. Se não quiser aguardar o próximo post, sugiro fazer umas experiências alterando o código da index.zul com base em demos ou tutoriais da página do ZK. Até breve!