Category Archives: Business Português

EasyCriteria no Maven

Pessoal, bom dia.

É com muito prazer que venho anunciar que o EasyCriteria foi adicionado ao repositório do Maven.

Para utilizá-lo basta adicionar a seguinte configuração no pom do seu projeto:

<dependency>
	<groupId>uaihebert.com</groupId>
	<artifactId>EasyCriteria</artifactId>
	<version>2.1.0</version>
</dependency>

Simples e fácil. A versão 2.1.0 foi lançada para atender ao requisitos da publicação no Maven.

Espero que vocês gostem dessa novidade! [=

http://easycriteria.uaihebert.com

EasyCriteria 2.0 – JPA Criteria tem que ser simples

Olá, tudo bem?

Muito tempo se passou desde meu último post, mas não estava parado durante esse tempo.

O post de hoje vem falar sobre a nova versão do Framework chamado EasyCriteria. Ao final deste pequeno post eu conto mais o que estar por vir. [=

Infelizmente um grande problema da Criteria do JPA é sua verbosidade. Por que não facilitar? Foi pensando desse modo que nasceu o framework EasyCriteria e agora a recente versão 2.0.

Para fazer um simples select que busque todas as linhas do banco de dados, o seguinte código seria necessário:

CriteriaQuery<Person> criteriaQuery = criteriaBuilder.createQuery(Person.class);
Root<Person> root = criteriaQuery.from(Person.class);
criteriaQuery.select(root);
TypedQuery<Person> query = entityManager.createQuery(criteriaQuery);
query.getResultList();

Note quanto trabalho para apenas reproduzir a JPQL : select p from Person p.

Agora, veja como o EasyCriteria facilita a construção da mesma Criteria acima:

EasyCriteria<Person> easyCriteria = EasyCriteriaFactory.createQuery(entityManager, Person.class);
easyCriteria.getResultList();

A diferença da versão 1.0 e 2.0 está na redução de métodos e na criação de métodos genéricos que facilitem a utilização do projeto. Para comparar valores com os símbolos =, >, >=, <=, < e outro mais, basta fazer como abaixo:

easyCriteria.andGreaterThan("hairSize", 10.4f); // >

easyCriteria.andGreaterOrEqualTo("height", 11.00d); // >=

easyCriteria.andLessThan("totalBooksOwned", 30L); // <

easyCriteria.andLessOrEqualTo("firstJobDate", firstJobDate); // <=

easyCriteria.andJoinEquals("dogs", "age", 15); // =

easyCriteria.andJoinStringIn("dogs", "name", names); // value in (x, i, z, ...)

easyCriteria.andJoinStringLike("dogs", "name", "%y");

Uma ideia fixa do EasyCriteria é expor o menor número de API possível ao usuário. Visando essa ideia, a API incorporou o “OR” de uma query sem a necessidade expor outras classes.

Veja como fazer um “OR” simples:

select s from Song s where s.id = 1 or s.length = 40 or s.artist = 'Group 1 Crew'
easyCriteria.orEquals("id", 1).orEquals("length", 40).orEquals("artist", "Group 1 Crew");

E também poderia ser feito o seguinte tipo de query:

select s from Song s where (s.id = 1) or (s.id = 2) or (s.length = 40) or (s.artist = 'Group 1 Crew')
easyCriteria.orEquals("id", 1, 2).orEquals("length", 40).orEquals("artist", "Group 1 Crew");

E para casos mais complexos como a query abaixo, também é possível reproduzir com o EasyCriteria:

select s from Song s where (s.totalDownloads = 20 or s.weight = 10.00) and (s.price = 20.00 or s.type = :type)
easyCriteria.orEquals(1, "totalDownloads", 20L).orEquals(1, "weight", 10.00f).orEquals(2, "price", 20.00d).orEquals(2, "type", SongType.PRAISE);

Foi criada a ideia de índice para cada OR, ou seja, o primeiro grupo de OR é composto por totalDownloads e weight, já o seguinte grupo é price e type.

E como valor padrão o índice 1 é sempre utilizado. A criteria acima poderia ser traduzida por:

easyCriteria.orEquals("totalDownloads", 20L).orEquals("weight", 10.00f).orEquals(2, "price", 20.00d).orEquals(2, "type", SongType.PRAISE);

Para uma query que inverta esse quadro, onde AND é separado por OR basta fazer como abaixo:

select s from Song s where (s.id = 1 and s.name = 'Sing Out') or (s.id = 2 and s.name = 'Alive')
easyCriteria.addAndSeparatedByOr(1, "id", 1).addAndSeparatedByOr(1, "name", "Sing Out").addAndSeparatedByOr(2, "id", 2).addAndSeparatedByOr(2, "name", "Alive");

É isso pessoal, espero que vocês gostem da novidade. O framework está longe de se considerar pronto. E para bolar um modo de criar o OR foram queimados muitos neurônios com ajuda do João Neves (http://about.me/joaonevesfilho) e também o Sasaki (http://curriculum.rodrigosasaki.com/).

Aqui é possível ver a página oficial do framework: http://easycriteria.uaihebert.com. E o melhor, é free e open source (http://code.google.com/p/easy-criteria/).

Outra coisa legal é o fato de o projeto ter 100% de cobertura com plugin Cobertura e foi testado com OpenJPA, EclipseLink e Hibernate. É aí que eu peço a sua ajuda, pois foram encontrados bugs em todas implementações citadas. Seria possível você votar para que o bug seja resolvido?

EclipseLink: https://bugs.eclipse.org/bugs/show_bug.cgi?id=386354
OpenJPA: https://issues.apache.org/jira/browse/OPENJPA-2333
Hibernate: https://hibernate.onjira.com/browse/HHH-7985

E o que vem por aí? Em primeiro lugar eu demorei escrever um novo post, pois estou finalizando meu primeiro livro. Se Deus quiser até março ele será lançado.

E em segundo lugar estudei bastante Maven nesse tempo e pretendo lançar um próximo post de um mini livro só sobre ele contendo um básico e aplicações completas. Sim “aplicações” no plural mesmo.

Até a próxima pessoal! \o_

JPA Mini Livro – Primeiros passos e conceitos detalhados

Olá, tudo bem?

Vamos ver hoje sobre JPA: o que é JPA, para que serve o persistence.xml, criar corretamente uma entidade, como realizar desde mapeamentos simples até os mapeamentos complexos de chaves primárias, criar relacionamentos entre as entidades, modos para persistência automática e outros.

O que iremos ver hoje:

  • Página 02: Quais os motivos que levaram à criação do JPA?
  • Página 03: O que é o JPA? O que são as implementações do JPA?
  • Página 04: Para que serve o persistence.xml? E suas configurações?
  • Página 05: Definições de uma “Entity”. O que são anotações Lógicas e Físicas?
  • Página 06: Gerando Id: Definição, Id por Identity ou Sequence
  • Página 07: Gerando Id: TableGenerator e Auto
  • Página 08: Utilizando Chave Composta Simples
  • Página 09: Utilizando Chave Composta Complexa
  • Página 10: Modos para obter um EntityManager
  • Página 11: Mapeando duas ou mais tabelas em uma entidade
  • Página 12: Mapeando Heranças – MappedSuperclass
  • Página 13: Mapeando Heranças – Single Table
  • Página 14: Mapeando Heranças – Joined
  • Página 15: Mapeando Heranças – Table Per Concrete Class
  • Página 16: Prós e Contras dos mapeamentos das heranças
  • Página 17: Embedded Objects
  • Página 18: ElementCollection – Como mapear uma lista de valores em uma classe
  • Página 19: OneToOne (Um para Um) Unidirecional e Bidirecional
  • Página 20: OneToMany (um para muitos) e ManyToOne (muitos para um) Unidirecional e Bidirecional
  • Página 21: ManyToMany (muitos para muitos) Unidirecional e Bidirecional
  • Página 22: ManyToMany com campos adicionais
  • Página 23: Como funciona o Cascade? Para que serve o OrphanRemoval? Como tratar a org.hibernate.TransientObjectException
  • Página 24: Como excluir corretamente uma entidade com relacionamento. Capturar entidades relacionadas no momento da exclusão de um registro no banco de dados.
  • Página 25: Criando um EntityManagerFactory por aplicação
  • Página 26: Entendendo o Lazy/Eager Load
  • Página 27: Tratando o erro: “cannot simultaneously fetch multiple bags”

Apenas uma observação: eu não irei criar o PDF desse post. Pra produzir o material já levo horas na formatação de código, produção de imagens, ajustes do post no blog e sem falar que preciso traduzir para o inglês. Desculpe, mas não existe a possibilidade, por agora, da criação de um arquivo PDF com o conteúdo deste post.

Dois leitores gente boa criaram arquivos para quem quiser fazer o download do post. Estão nos formatos pdf, doc e odt. É possível encontrar os arquivos na última página.

Lançado EasyCriteria 1.0

Olá, tudo bem?

Este post irá mostrar as novas funcionalidades do EasyCriteria.

O EasyCriteria é uma ferramenta Open Source que facilita a utilização do Criteria do JPA independente da implementação. Atualmente o EasyCriteira tem 100% de cobertura nos testes unitários e é testado com as implementações: Hibernate, OpenJPA e EclipseLink.

Caso você queira entender o conceito do Criteria e como pode ser aplicado ao seu projeto veja esse post: EasyCriteria – Um modo simples de fazer Criteria com JPA.

As novas funcionalidades do EasyCriteria 1.0 são:

  • Condições em Join
  • Paginação de Query

Agora é possível realizar um Join e adicionar parâmetros:

EntityManager em = emf.createEntityManager();
EasyCriteria<Person> easyCriteria = EasyCriteriaFactory.createQueryCriteria(em, Person.class);

easyCriteria.innerJoin("dogs", Dog.class);
easyCriteria.whereJoinEquals("dogs", "name", "Dark");
easyCriteria.whereJoinStringNotIn("dogs", "name", names); // names is a List<String>
easyCriteria.whereJoinStringLike("dogs", "name", "M%");
easyCriteria.whereJoinListIsEmpty("dogs", "cars");
easyCriteria.whereJoinAttributeIsNull("dogs", "nickName");
easyCriteria.whereJoinStringBetween("dogs", "name", "A", "L");

A query também poderá ser paginada:

EasyCriteria<Dog> easyCriteria = EasyCriteriaFactory.createQueryCriteria(getEntityManager(), Dog.class);
easyCriteria.setFirstResult(0);
easyCriteria.setMaxResults(5);

A nova versão também conta 100% de cobertura de código nos testes unitários.

Clique aqui para fazer o download do código do post de hoje do EasyCriteria. Você poderá testar os métodos do EasyCriteria.

Na página do projeto (http://easycriteria.uaihebert.com/) é possível encontrar toda a documentação.

Qualquer dúvida basta postar abaixo.

Até a próxima! \o_

EasyCriteria – Utilizando a Criteria do JPA de um modo simples

Olá, tudo bem?

Vamos ver hoje sobre essa ferramenta que facilita o uso da Criteria do JPA que deixa o código bem limpo, fácil de utilizar e portável pelas implementações do JPA.

Ao final desse post se encontra disponível o código fonte para download.

O que é uma Criteria? É atualmente a melhor solução para consultas que são criadas de modo dinâmicos. Imagine uma tela onde se tem diversas opções de pesquisa. Pode ser por nome, por idade ou até mesmo pelos dois. Veja como ficaria a consulta caso fosse utilizado uma concatenação de String:

EntityManager em = emf.createEntityManager();
String hql = "select p from Person p where 1=1 ";

if(parameters[0].equals("name")){
	hql += " and p.name = '" + values[0] + "'";
}

if(parameters[1].equals("age")){
	hql += " and p.age = " + values[1];
}

TypedQuery<Person> query = em.createQuery(hql, Person.class);

System.out.println(query.getResultList());

Repare que no código acima é necessário fazer a concatenação de String o que pode levar ao famoso ataque hacker “SQL Injection”. A solução para evitar esse tipo de ataque seria utilizando query com parâmetros e não concatenação:

EntityManager em = emf.createEntityManager();
String hql = "select p from Person p where 1=1 ";

if(parameters.contains("name")){
	hql += " and p.name = :name";
}

if(parameters.contains("age")){
	hql += " and p.age = :age";
}

TypedQuery<Person> query = em.createQuery(hql, Person.class);

if(parameters.contains("name")){
	query.setParameter("name", values[0].toString());
}

if(parameters.contains("age")){
	query.setParameter("age", Integer.valueOf(values[1].toString()));
}

System.out.println(query.getResultList());

Note que o problema do SQL Injection foi resolvido mas agora o código deve verificar os parâmetros na hora de construir a query q na hora de popular os valores; o ato de popular os parâmetros acabam por gerar uma tarefa extra.

O pessoal da Java teve a brilhante ideia de criar o conceito de Criteria que é perfeita para esse tipo de utilização. Veja abaixo como ficaria o mesmo código utilizando a Criteria nativa do JPA:

EntityManager em = emf.createEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Person> cq = cb.createQuery(Person.class);
Root<Person> root = cq.from(Person.class);
cq.select(root);

if(parameters.contains("name")){
	Path<String> name = root.get("name");
	cq.where(cb.and(cb.equal(name, values[0])));
}

if(parameters.contains("age")){
	Path<Integer> name = root.get("age");
	cq.where(cb.and(cb.equal(name, Integer.valueOf(values[1].toString()))));
}

TypedQuery<Person> query = em.createQuery(cq);

System.out.println(query.getResultList());

Veja como ficou prático a passagem de parâmetros já com seu valor. Não existe a necessidade de concatenar string, ou muito menos de ficar populando parâmetros depois que a query estiver pronta.

Infelizmente essa api do Criteria ficou muito complexa e demasiadamente verbosa. Para fazer apenas um “select p from Person p” a criteria abaixo seria necessária:

EntityManager em = emf.createEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Person> cq = cb.createQuery(Person.class);
Root<Person> root = cq.from(Person.class);
cq.select(root);

TypedQuery<Person> query = em.createQuery(cq);
System.out.println(query.getResultList());

É muito código para uma função muito simples, listar todas as pessoas de uma tabela.

Para evitar toda essa verbosidade é que foi criado o projeto Open Source chamado EasyCriteria.

O EasyCriteria é simples, prático e tem uma abordagem de “esconder” toda a verbosidade facilitando o uso da Criteria do JPA. Utilizando o EasyCriteria a consulta acima ficaria assim:

EntityManager em = emf.createEntityManager();
EasyCriteria<Person> easyCriteria = EasyCriteriaFactory.createQueryCriteria(em, Person.class);

if(parameters.contains("name")){
	easyCriteria.whereEquals("name", values[0]);
}

if(parameters.contains("age")){
	easyCriteria.whereEquals("age", values[1]);
}

System.out.println(easyCriteria.getResultList());

Note que toda a verbosidade do JPA foi embora. Agora é possível ter um código simples para a construção de um query dinâmica. Sobre o código acima vale a pena destacar:

  • Linha 2: Uma instância do EasyCriteria é criada através de uma “factory”. Essa factory existe para abstrair todos os passos necessários para a criação de um objeto do tipo EasyCriteriaImp. Nas versões futuras virão outros tipos de EasyCriteria virão a exemplo do Tuple.

  • Linhas 5 e 9: A passagem de parâmetros ficou mais objetiva. Agora para se passar um parâmetro para comparar valores (“name = :name”) basta utilizar o método equals que espera como primeiro parâmetro o nome do atributo da classe; e como segundo o parâmetro o valor a ser comparado.

  • Linha 12: Para realizar a consulta não é mais necessário a utilização da interface Query. O próprio EasyCriteria toma conta dessa função. É possível extrair diretamente o resultado da query pelo EasyCriteria. Existem dois métodos que fazem isso atualmente o “EasyCriteria.getSingleResult()” e o “EasyCriteria.getResultList()”.

No site do EasyCriteria é possível encontrar diversos exemplos e os métodos que podem ser utilizados. Outra vantagem de se utilizar o EasyCriteria é que todos os seus comandos podem ser “linkados”:

easyCriteria.whereEquals("name", values[0]).whereEquals("age", values[1]).getResultList();

É uma bilioteca que está leve pois a única dependência é o JPA que o sistema já terá que ter configurado. Atenção: é necessário que sua aplicação já tenha o JPA rodando com alguma implementação.

Essa biblioteca foi desenvolvido utilizando JUnit e testado com Hibernate, OpenJPA e EclipseLink. O JUnit também utiliza do framework Cobertura para verificar se todo o código está sendo testado, atualmente 100% do código está coberto.

O EasyCriteria se encontra na versão beta e já tem em vista novas releases com novas funcionalidades.

Outra vantagem do EasyCriteria é que seu código não fica acoplado à alguma implementação. Hoje o Hibernate tem uma ferramenta de criteria muito boa e prática, mas você tem que ficar “preso” a ele. Com o EasyCriteria você poderá utilizar qualquer implementação. A prova disso é que os testes do EasyCriteria são realizados com as implementações citadas agora a pouco.

E EasyCriteria facilita funções como in, like, empty para a criteria do JPA. Além de realizar join (simples, sem adição de parâmetros), distinct e até order by tudo por criteria.

Aqui você encontra o EasyCriteria para download e para acesso a toda sua documentação (http://easycriteria.uaihebert.com).

Clique aqui para fazer o download do código fonte do post de hoje.

Espero que esse post/ferramenta possa te ajudar.

Qualquer dúvida/questionamento/opnião basta falar.

Até a próxima! \o_

Como testar sua JPQL / HQL sem realizar Deploy

Olá, tudo bem?

Você já teve a vontade de testar sua HQL / JPQL sem precisar realizar o deploy de sua aplicação?

A solução apresentada aqui hoje é simples e funciona para qualquer implementação do JPA: Hibernate, OpenJPA, EclipseLink dentre outras.

O código de hoje pode ser executado mesmo que você não tenha banco de dados. Ele utiliza o HSQLDB e já tem uma massa de dados pronta para ser consultada.

A fonte original desse código pode ser encontrada no livro: “Pro JPA 2: Mastering the Java™ Persistence API – Mike Keith, Merrick Schincariol“. O post de hoje acrescenta ao código original: parâmetros para as consultas e o teste de NamedQueries.

O que será apresentado no post de hoje:

  • Página 02: Classes do Modelo e Geração dos dados
  • Página 03: Classe de teste abstrata
  • Página 04: Teste de Query dinâmica
  • Página 05: Teste de NamedQuery
  • Página 06: Execução
  • Página 07: Adaptando o código para sua aplicação
  • Página 08: Sugestões

Ao final desse post se encontra o código fonte para download.

Na página 07 serão destacadas as partes dos códigos que necessitarão de alterações para que você possa aplicar o código do post de hoje ao seu projeto.

Quatro soluções para LazyInitializationException

Olá, tudo bem?

No post de hoje veremos como tratar o famoso erro LazyInitializationException. Vamos ver 4 modos de evitar que esse erro aconteça, a vantagem e a desvantagem de cada abordagem e ao final, veremos comentários sobre o modo de como o EclipseLink trata essa situação.

Para simular e tratar o LazyInitializationException iremos utilizar um projeto EJB 3 com JSF 2.

O que veremos no post de hoje:

  • Página 3: Entenda o problema, por que o erro LazyInitializationException acontece?
  • Página 4: Carregar coleção por anotação
  • Página 5: Carregar coleção por Open Session in View (Transaction View)
  • Página 6: Carregar coleção por Stateful EJB com PersistenceContextType.EXTENDED
  • Página 7: Carregar coleção por Join Query
  • Página 8: Considerações sobre EclipseLink

Ao final do post você irá encontrar o código para download.

Atenção: Para esse post foi utilizado um código bem simples, e que não utiliza padrões de projeto. O foco desse post é destacar as soluções para o LazyInitializationException.

Apesar do exemplo que é utilizado nesse post ter sido criado com JSF + EJB, as soluções aqui se aplicam para o tratamento em qualquer ferramenta web. Tanto JSF, JSP com Servlets, JSP com Struts, JSP com VRaptor, etc.

O único exemplo que não é aplicável para a tecnologia JSE (em geral definido como Desktop) é a solução do EJB.

JPA Consultas e Dicas

Olá, tudo bem?

Existem diversos tutoriais na internet e, que inclusive aqui no blog, mostram como realizar diversas tarefas com JPA.

Vejo diversas pessoas em fóruns com dúvidas sobre Queries em JPA e são necessários diversos links para mostrar uma solução sobre o assunto.

Até hoje não encontrei nenhum post que unisse um bom material sobre queries com JPA, dicas de performance/utilização, código fonte para download…
Challenge Accepted

Hoje nós veremos aqui:

  • Página 2: Classes de modelo e classe para gerar os dados do banco de dados
  • Página 3: Utilizando método find; utilizar getReference para melhor performance, exibindo parâmetros da query no console através do lo4j
  • Página 4: JPQL: Consultas com parâmetros simples ou objetos, Joins, Order By, Navegando pelos relacionamentos
  • Página 5: JPQL: Funções: AVG, COUNT, MAX, MIN, TRIM, SUM, UPPER, LOWER, MOD, LENGHT, SQRT; Utilizar HAVING, GROUP BY
  • Página 6: JPQL: Condições: LIKE, IN, DISTINCT, EMPTY, BETWEEN, NULL, MEMBER OF, EXISTS (Subqueries), ANY, ALL, SOME, CONCAT, CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP, LOCATE, SIZE, SUBSTRING
  • Página 7: JPA: NamedQuery, pesquisando com data, cuidados com getSingleResult
  • Página 8: JPA: NativeQuery, NamedNativeQuery
  • Página 9: JPA: Mapeamentos Complexos com NativeQuery
  • Página 10: JPA: Otimizar Queries com EJB
  • Página 11: JPA: Paginação
  • Página 12: JPA: Hints para Banco de Dados
  • Página 13: JPA: Criando um objeto dentro da consulta
  • Página 14: JPQL: Bulk Update e Delete
  • Página 15: JPA: Criteria

Você verá durante o decorrer desse post que o seguinte código será chamado “CodeGenerator.generateData()”. Essa classe tem apenas a função de gerar dados para as pesquisas demonstradas aqui tenham dados.

Na última página do post você irá encontrar o código fonte do projeto para download.

Nesse post iremos utilizar JPA 2.0 com Hibernate de provider. O banco de dados será o HSQLDB e já irá em anexo ao código do projeto. Você poderá baixar e executar o projeto sem a necessidade de configurações extras. Não irei mostrar como montar o ambiente com o HSQLD, pois o foco do post de hoje é apenas ver o funcionamento do JPA para consultas.

Esse post não visa demonstrar boas práticas para camadas de persistência, apenas demonstrar como são realizadas consultas e operações com o banco de dados.

Aplicação Web Completa JSF EJB JPA JAAS

Olá pessoal, bom dia.

Hoje vai ser o maior post que eu já fiz! Vamos ver uma aplicação completa. Ela será feita com tecnologias mais novas, mas darei dicas de como adaptar algumas partes para alguma tecnologia mais antiga assim que possível.

Ao final desse post você irá encontrar o código fonte para download. Pode utilizar como quiser. Basta ir para a última página e fazer o download. \o/

Caso você baixe o código e não entenda alguma parte do código, eu expliquei tudo pelo decorrer desse post. Basta você ler a parte que te interessa e tirar suas dúvidas.

A aplicação será feita das seguintes tecnologias:

  • JSF 2.0 Mojarra – Utilizando Managed Beans de Request e Session.
  • Internacionalização das mensagens – Arquivo onde são definidas todas as mensagens do sistema, com isso você poderá facilmente traduzir seu programa.
  • Arquivo CSS padrão sendo utilizado como biblioteca.
  • EJB 3 – Utilizando DAO e Facades como @Stateless.
  • Generic DAO – Um DAO Genérico que terá as funções básicas de um cadastro facilitando assim a criação de entidades.
  • JPA 2 – Para mapear nossas classes no DB.
  • JAAS – Para controlar o login e nível de acesso do usuário.
  • MVC – Utilizarei o padrão MVC com pequenas alterações.
  • Postgres como banco de dados, mas vou mostrar como configurar para o MySQL também.

Não irei aplicar JUnit para teste dos métodos da View/Façade/Model, mas no link a seguir você poderá ver a técnica utilizar para usar o JUnit para testar os ManagedBeans do JSF: JUnit com HSQLDB, JPA e Hibernate.

Ferramentas para o post de hoje:

Este post será feito em várias páginas. Essa primeira página consta apenas os detalhes técnicos que serão utilizados na aplicação.

Não irei programar o meu modelo/DAO para interface, apenas para poupar espaço. Lembre de sempre programar para interface (Design Pattern – Strategy).

Antes de avançar, tenha certeza de que você instalou o JBoss Tools e depois o JBoss 7 (nessa ordem).

JPA Uma Tabela por Classe

EXISTE UMA NOVA VERSÃO DESSE POST.
CLICK AQUI: http://uaihebert.com/?p=1622&page=14

Olá pessoal, tudo bem?

Vamos falar hoje em como criar uma tabela por classe em uma herança onde cada tabela tem apenas as colunas da sua classe. No último post foi visto como persistir toda a herança em uma tabela apenas.

Irei utilizar o mesmo exemplo do ultimo post já colocando aqui como deve ser o código correto para utilizar essa abordagem.

Ao final do post você encontrará o link para download do projeto de hoje.

Click nos links a seguir para ver o último post sobre o assunto ou qualquer outro post sobre JPA: JPA Uma tabela por herança, Ordernando listas e utilizando Map como atributo mapeado, @ManyToMany Unidirecional e Bidirecional, JPA @OneToMany e @ManyToOne Unidirecional e Bidirecional, @OneToOne Unidirecional e Bidirecional, Mapeando Duas Tabelas em uma Classe, Mapeando Datas (Date) e Enum, Chave Primária Composta, SequenceGenerator, TableGenerator – Chave Primária Simples, Auto Create Schema Script com: Ant, Hibernate 3 e JPA 2, Tutorial Hibernate 3 com JPA 2.

Veja como ficará nosso código:

package com.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;

@Entity
@Table(name="CAR")
@Inheritance(strategy=InheritanceType.JOINED)
public abstract class Car {
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	private int id;
	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}
}
package com.model;

import javax.persistence.Entity;

@Entity
public class Beetle extends Car {
	private int gasCapacity;

	public void talk(){
		System.out.println("Herbie!");
	}

	public int getGasCapacity() {
		return gasCapacity;
	}

	public void setGasCapacity(int gasCapacity) {
		this.gasCapacity = gasCapacity;
	}
}
package com.model;

import javax.persistence.Entity;

@Entity
public class Ferrari extends Car {
	private int model;

	// The newest new models will fly... some day! =P
	public void fly() {

	}

	public int getModel() {
		return model;
	}

	public void setModel(int model) {
		this.model = model;
	}
}

Após executar a classe Main, veja como nossas tabelas ficaram:

Agora para cada tabela temos os dados pertinentes a sua respectiva classe.

Gostaria de deixar apenas uma alerta.

Repare que os IDs de todas as nossas classes têm o nome “id”. Caso sua classe tenha um id diferente de sua super classe, será necessário mapear de modo diferente.

Imagine que nossa classe Beetle teria seu id como beetleId, nosso mapeamento teria que apresentar a seguinte anotação a mais:

package com.model;

import javax.persistence.Entity;
import javax.persistence.PrimaryKeyJoinColumn;

@Entity
@PrimaryKeyJoinColumn(name="beetleId")
public class Beetle extends Car {

	private int gasCapacity;

	public void talk() {
		System.out.println("Herbie!");
	}

	public int getGasCapacity() {
		return gasCapacity;
	}

	public void setGasCapacity(int gasCapacity) {
		this.gasCapacity = gasCapacity;
	}
}


Repare que a chave primária agora tem o id com nome diferente da classe Car e Ferrari.

Lembre-se: se sua classe filha tem o nome do campo de id diferente da classe pai, você terá que usar a anotação @PrimaryKeyJoinColumn onde o campo “name” indica qual a coluna a ser mapeada. E caso você queira alterar qual a coluna de ligação na classe pai, basta você utilizar o parâmetro “referencedColumnName”.

Finalizando, vejamos vantagens e desvantagens:

  • Vantagem: Você poderá ter campos not null em sua classe ao contrário da estratégia de uma tabela para toda a herança. E tem vantagens em sobre o próximo tipo mapeamento que veremos: “Uma tabela para cada Sub-Classe com todos os campos da herança”. E segundo o livro “Enterprise JavaBens 3.0” essa estratégia será melhor do que a “Uma tabela para cada Sub-Classe com todos os campos da herança” caso SQL Union não seja suportado por seu banco de dados.
  • Desvantagem: Seu desempenho é pior do que a estratégia de Uma Tabela Para toda a Herança.

Clique aqui para fazer o download do post de hoje. Não esqueça de alterar a senha de conexão e o usuário.

Espero que esse post possa te ajudar.

Qualquer dúvida/colocação basta postar.

Até! \o_