Este artigo apresenta como devemos proceder para trabalharmos com JPA em conjunto com o MySQL. Para isso, o artigo apresenta alguns conceitos importantes para o entendimento do JPA e o explica através de um conjunto de exemplos práticos.
Em que situação o tema útil
Em sistemas orientados a objetos, uma grande dificuldade é encontrada quando o assunto é persistência. A transformação de objetos em dados persistentes no espaço relacional pode ser um trabalho árduo. Neste contexto, este artigo contribui com o entendimento do JPA, que facilita e muito o trabalho do mapeamento objeto relacional.
Resumo DevMan
Até algum tempo atrás, o mapeamento objeto relacional era só um conceito para qualquer linguagem orientada a objetos. Hoje em dia, diversos frameworks implementam este conceito facilitando e muito a vida do desenvolvedor. Neste sentido, este artigo abordará o tema JPA e para dar suporte ao armazenamento dos objetivos, utilizaremos o MySQL.
Hoje em dia quase tudo se resume a dados, e por boas razões. Em um mundo cada vez mais conectado o valor dos dados é enorme e é fácil de perceber como as organizações andam na corda bamba quando se trata de dados. Por que na corda bamba? Por que muita quantidade de dados normalmente está associado a muita quantidade de dinheiro, e ter acesso aos dados pode envolver algum grau de violação de privacidade.
Além das questões de negócios, no centro do problema está uma tecnologia já bastante difundida e confiável: os bancos de dados relacionais. A informação que reside nestas bases de dados são tão importantes que elas tendem a sobreviver mais que os próprios aplicativos criados para povoá-las. Assim, um sólido conhecimento da área de banco de dados é um bom investimento para os programadores que estão ansiosos para serem mais valorizados.
Em sistemas orientados a objetos, uma grande dificuldade é encontrada quando o assunto é persistência. Pode não parecer tão problemático assim, mas a transformação de objetos em dados persistentes no espaço relacional pode ser um trabalho árduo. O grande problema nessa situação são as duas estruturas totalmente diferentes que são empregadas em cada camada do sistema. No mundo relacional são criadas tabelas e colunas para armazenar informações, enquanto no modelo orientado a objetos temos a presença de classes e objetos.
Para solucionar esse problema, há alguns anos era preciso criar instruções SQL para transformar objetos em linhas do banco de dados, porém muito tempo era perdido com essa prática. Além de o desenvolvedor precisar implementar o código para a criação do banco de dados totalmente compatível com o modelo orientado a objetos, a cada nova operação de inserção, alteração, exclusão ou pesquisa, uma quantidade imensa de código no sistema era gerada a fim de tratar essa incompatibilidade de estruturas. Em longo prazo, isso tudo se tornava um trabalho exaustivo, não reutilizável e, muitas vezes, falho.
Surge então o conceito de ORM (Object-Relational Mapping ou Mapeamento Objeto-Relacional). Ele propõe a transformação de classes e objetos em tabelas e tuplas de maneira fácil e reutilizável. Ao invés do programador ter que criar todas as instruções SQL para as operações no banco de dados, ele pode utilizar um framework capaz de fazer essas operações sem sair do paradigma orientado a objetos. Assim, todo aquele trabalho árduo de codificação e testes se resume a algumas configurações e um mínimo de código, sem manter um contato direto com o banco de dados.
Até algum tempo atrás, o mapeamento objeto relacional era só um conceito para qualquer linguagem orientada a objetos e para que esse conceito saísse do papel, em 2006 a Sun lançou a JSR 220 especificando os Enterprise JavaBeans (EJB) 3.0. Juntamente com o EJB 3.0, a Java Persistence API 1.0 foi disponibilizada ao público desenvolvedor. Mais posteriormente, em 2009, a JSR 317 foi divulgada, dessa vez contendo apenas a especificação JPA 2.0. Em suma, essa API apresenta anotações e interfaces para que os frameworks que forem desenvolvidos sigam um padrão de funcionamento. A JPA não possui grande quantidade de código. De fato ela não faz o papel de um framework ORM. Ela apenas dita como eles deverão funcionar na plataforma Java.
A plataforma Java EE fornece hoje um grande número de ferramentas úteis e práticas. Java Persistence API 2.0 (JPA 2), Enterprise JavaBeans 3.1 (EJB 3.1) e JavaServer Faces 2.0 (JSF 2) são três destas ferramentas cuja popularidade é especialmente grande. É uma popularidade merecida: JPA facilita grandemente o trabalho de lidar com persistência de dados, JSF fornece um novo padrão, mais simples e eficiente, para o desenvolvimento de aplicações web em Java e EJB é excelente, entre outras coisas, para integrar componentes de uma aplicação de maneira que reduza o acoplamento.
A Java Persistence API, chamada apenas de JPA, é uma API padrão do java para persistência que deve ser implementada por frameworks que queiram seguir o padrão. A JPA define um meio de mapeamento objeto-relacional para objetos Java simples e comuns (POJOs), denominados beans de entidade. Diversos frameworks de mapeamento objeto/relacional como o Hibernate implementam a JPA.
Neste contexto, nesta série de artigos dividida em duas partes, demonstraremos como criar uma coleção baseada no modelo JPA e como implementar isso usando o MySQL. Na parte 2, iremos focar nossos estudos em uma tecnologia cada vez mais utilizada do lado do servidor: as stored procedures. Para começar, vamos dar uma rápida olhada na diferença entre os conceitos de entity e value.
Tipos Entity e Value
Quando falamos em JPA, a associação ao Hibernate é praticamente imediata. O Hibernate faz o papel de um provedor de persistência. Um provedor de persistência geralmente é um framework ORM que implementa as especificações JPA e disponibiliza toda a programação necessária para o efetivo Mapeamento Objeto-Relacional e a persistência de dados. Mesmo o Hibernate tendo um papel tão fundamental na persistência de dados e no Mapeamento Objeto-Relacional, todo o acesso às suas funcionalidades acontece de uma maneira quase que transparente, uma vez que o programador utiliza na maior parte do tempo apenas as anotações e interfaces disponibilizadas pela JPA.
O Hibernate surgiu antes da especificação JPA e foi ele quem motivou a criação dessa especificação. Quando o Hibernate ganhou popularidade, a Sun previu que muitos outros frameworks seriam desenvolvidos e se uma maneira padronizada de mapeamento objeto-relacional não fosse criada, os desenvolvedores desses outros frameworks sairiam prejudicados caso optassem por uma migração da ferramenta. Prejudicados pelo fato de não poderem reutilizar código para persistência, configurações e mapeamentos.
É importante lembrar que existem outros provedores ORM e não apenas o Hibernate. Alguns exemplos são o EclipseLink, OJB, OpenJPA e DataNucleus. Desses exemplos, o mais notável é o EclipseLink. Ele foi o RI (Reference Implementation) do JPA 2 e hoje é um dos mais utilizados.
No Hibernate, os tipos podem ser entity ou value. Um tipo entity possui uma identidade persistente, o que significa que tem um ciclo de vida independente do banco de dados. Em outras palavras, as entidades podem ser mantidas na base de dados, lidas a partir do banco de dados, atualizadas, etc. Já um tipo value difere de um tipo entity por que ele não tem uma identidade persistente. No entanto, tipos entity e value muitas vezes tendem a ser trabalhados em conjunto.
Um típico tipo entity é um usuário, por exemplo, um usuário do sistema. O endereço postal de tal usuário pode ser modelado como um tipo value. Assim, para facilitar o entendimento da diferença entre entity e valeu, podemos pensar um tipo value como um atributo de um tipo entity. Não é nenhuma surpresa então percebermos que uma entidade pode suportar vários tipos de valores individuais, bem como coleções de tipos de valor. Além disso, uma coleção de tipos entity também é possível. Antes de conhecermos um exemplo de coleção de entitys, vamos primeiro rever as entidades básicas do modelo que consideraremos neste artigo: Person e Departament. Um departamento irá conter zero, uma, ou mais pessoas.
Definindo as entidades
Nossa primeira entidade está definida na Listagem 1. Ela se refere à classe entidade Person. Na Listagem 1, podemos observar uma definição simples de uma classe Person como sendo uma entidade como indicado pela anotação @Entity. Esta anotação descreve a classe como uma entidade persistente ou seja, uma instância dessa classe normalmente reside em uma linha no banco de dados. O resto da classe Person é composto apenas de métodos getter e setter e um método toString ().
Listagem 1. Entidade person
@Entity
@Table(name = "PERSON")
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "PERSON_ID")
private Long id;
private String lastName;
private String firstName;
private String friends;
public Person() {
}
public Long getId() {
return id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFriends() {
return friends;
}
public void setFriends(String friends) {
this.friends = friends;
}
@Override
public String toString() {
return "Person [id=" + id + ", lastName=" + lastName + ", firstName="
+ firstName + ", friends=" + friends + "]";
}
}
...