Desde o surgimento da linguagem Java foram criadas diversas APIs para fazer a interface do código Java com um SGBD (Sistema Gerenciador de Banco de Dados). Uma das primeiras bibliotecas com esse intuito foi o JDBC (Java Database Connectivity), que surgiu no fim dos anos 90 e ainda é muito utilizado.
No JDBC, o acesso ao banco de dados é feito através de comandos (Statements) escritos na linguagem SQL (Structured Query Language), que é a linguagem padrão dos gerenciadores de banco de dados.
Em seguida surgiram as tecnologias de mapeamento objeto-relacional, conhecidas por ORM (Object-Relational Mapping). Tais tecnologias estabelecem uma “ponte” entre esses dois modelos de dados: o modelo orientado a objetos, utilizado em linguagens de programação como o Java, e o modelo relacional, utilizado pela maioria dos SGBDs.
Deste modo, foram sendo desenvolvidas APIs que realizam esse mapeamento em Java. O Hibernate foi uma das primeiras bibliotecas criadas com esse intuito. Com essas ferramentas, é possível fazer tanto a geração de código Java a partir das tabelas da base de dados, como a geração de scripts de criação de banco de dados (em SQL) a partir das classes Java.
Com intuito de padronizar as implementações de ORM em Java, foi elaborada a especificação JPA, como parte da plataforma Java EE 5. A versão atual do JPA é a 2.1 e ela é suportada por todos os servidores aderentes ao padrão Java EE existentes no mercado (JBoss, GlassFish, WebSphere, etc.).
Além destas, existem também algumas implementações do JPA de código aberto, como por exemplo, a EclipseLink, que usaremos no estudo de caso que será apresentado.
Neste artigo, abordaremos um exemplo simples para ilustrar o funcionamento do JPA. Criaremos um modelo de dados com três objetos (Aluno, Disciplina e Professor), simulando um banco de dados de uma faculdade ou de um colégio. No exemplo, veremos o código em Java das entidades JPA que representam esses três objetos do nosso modelo.
Também iremos implementar o código que fará a inserção de alguns dados de testes, para popular o nosso banco de dados. Por fim, implementaremos algumas consultas para extrair relatórios a partir dos dados armazenados.
Criando entidades para representar os dados
No JPA, as classes Java que representam os dados a serem armazenados no SGBD são chamadas de Entidades (Entity). Elas são classes comuns que contêm apenas atributos e métodos getters (que recuperam o valor dos atributos) e setters (que modificam o valor dos atributos).
O que torna essa classe uma entidade é a presença da anotação (Annotation) @javax.persistence.Entity. Tal anotação faz com que o JPA associe a classe Java em questão a uma tabela do banco de dados.
A própria implementação do JPA se encarregará de criar a tabela automaticamente no banco de dados relacional.
No código Java, basta criar as instâncias das entidades, preenchendo-as com os dados desejados e depois salvar no banco de dados. Cada entidade, quando persistida, corresponderá a um registro na tabela do banco de dados. Mais adiante veremos como persistir as entidades, quando falarmos do EntityManager.
Na Listagem 1 temos o código da nossa primeira entidade, de nome Aluno, com os atributos matricula, nome e curso. Como pode ser observado, não existe nada de complexo neste código.
package br.com.disciplinas.jpa.model; import javax.persistence.Entity; import javax.persistence.Id; @Entity public class Aluno { @Id private int matricula; private String nome; private String curso; public int getMatricula() { return matricula; } public void setMatricula(int matricula) { this.matricula = matricula; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public String getCurso() { return curso; } public void setCurso(String curso) { this.curso = curso; } }
A declaração da classe, como vimos, deve ter a anotação @Entity, indicando para o JPA que essa classe é uma entidade. Por padrão, toda entidade deve ter um construtor sem argumentos. Neste caso, ele foi omitido por ser o construtor default em Java.
Caso algum construtor com parâmetros seja definido, no entanto, deve-se definir também a versão sem parâmetros, senão a implementação do JPA apresentará uma exceção em tempo de execução.
Outra característica obrigatória de uma Entidade é ...