Blog do Urubatan
msgbartop
Desenvolvedor, Arquiteto, Palestrante, Coordenador do RSJUG, Patinador e Blogger
msgbarbottom

23 Nov 06 Suporte do Spring 2.0 a JPA - ficou muito bom, ainda mais se usar um pouquinho do Spring-Annotation junto :D

O suporte do spring ao JPA ficou melhor que a enconemda :D olhem só este exemplo usando o TopLink Essentials:

Este é o meu persistence.xml

<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0"
	xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="personal_finance">
<provider>oracle.toplink.essentials.PersistenceProvider</provider>
		<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="toplink.jdbc.url" value="jdbc:mysql://localhost/personal_finance"></property>
<property name="toplink.jdbc.user" value="root"></property>
<property name="toplink.jdbc.driver" value="com.mysql.jdbc.Driver"></property>
<property name="toplink.jdbc.password" value="admin"></property>
<property name="toplink.ddl-generation" value="drop-and-create-tables"></property>
<property name="toplink.create-ddl-jdbc-file-name" value="pf.sql"></property>
<property name="toplink.ddl-generation.output-mode" value="both"></property>
<property name="toplink.target-database" value="MySQL4"></property>
		</properties>
	</persistence-unit>
</persistence>

Percebam que eu não declarei quais são as classes persistentes.
Pela especificação isto só é possivel um um container Java EE, mas o TopLink faz isto em Java SE também, ou em um container de servlets. Testei isto com o Hibernate e o Hibernate não suporta isto rodando no tomcat.
O problema do TopLink é a geração qutomatica de DDL que é bem fraquinha (pelo menos para o MySQL, pode ser que rodando com o Oracle funcione melhor)

bom, mas vamos a brincadeira, coloquei o seguinte no applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:sa="https://spring-annotation.dev.java.net/context" xmlns:jee="http://www.springframework.org/schema/jee"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
       http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.0.xsd
       https://spring-annotation.dev.java.net/context https://spring-annotation.dev.java.net/context.xsd"
	default-autowire="byName" default-lazy-init="false">
	<tx:annotation-driven transaction-manager="myTxManager"/>
	<sa:annotation-autoload jarmarkerfile="to.properties" scandirs="true"/>
	<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="personal_finance"></property>
	</bean>
	<!-- JPA annotations bean post processor -->
	<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"></bean>
	<!-- Exception translation bean post processor -->
	<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"></bean>
	<bean id="myTxManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"></property>
	</bean>
</beans>

  • O bean: myTxManager - é o gerenciador de transações do Spring a ser utilizado, este em questão, utiliza a API do JPA para controlar as transações
  • O bean: org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor - permite a tradução automática de excessões do JPA para Spring, basta para isto anotar a classe desejada com @Repository
  • O bean: org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor - faz a maior parte da mágica, quer dizer, habilita a injeção do EntityManager ou do EntityManagerFactory em qualquer bean gerenciado pelo Spring Framework, e o que é melhor, não obriga a criação do setter, ele faz injeção via campos também :D
  • O bean: entityManagerFactory - é a configuração do EntityManagerFactory que o Spring vai utilizar. é possivel a configuração de vários PersistenceContext, mas ai precisa de um pouquinho mais de XML.
  • A tag: <tx:annotation-driven transaction-manager=”myTxManager” /> - Habilita o gerenciamento de transações atravéz da anotação @Transactional
  • A tag: <sa:annotation-autoload jarMarkerFile=”to.properties” scanDirs=”true” /> - Habilita a utilização de anotações para configurar os beans do Spring Framework, é um recurso novo da próxima versão do Spring-Annotation que deve sair na semana que vem, agora com a maior parte das sugestões ja implementadas, é possivel filtrar quais pacotes serão incluidos em cada contexto, suporte a hierarquia de contextos, muitas melhorias no suporte a JSF, mas este é assunto para outro post :D

Tudo beleza, muito bonito, mas e o código java como fica?
bom, deem só uma espiadinha aqui em baixo:

package br.com.techoffice.pf.mbean;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import net.java.dev.springannotation.annotation.Bean;
import net.java.dev.springannotation.annotation.ManagedBean;
import net.java.dev.springannotation.annotation.Out;
import net.java.dev.springannotation.annotation.Scope;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import br.com.techoffice.pf.data.User;

@ManagedBean
@Bean(name = "userM", scope = Scope.REQUEST)
@Repository
public class UserMBean {
	@PersistenceContext
	private EntityManager em;
	private String userName;
	private String password;
	@Out(scope = Scope.SESSION)
	private User currentUser;
	private User user;

	public User getCurrentUser() {
		return currentUser;
	}

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	@Transactional
	public String login() {
		Query q = em.createQuery("from User u where u.userName=? and u.password=?");
		q.setParameter(0, userName);
		q.setParameter(1, password);
		user = (User) q.getSingleResult();
		if (user != null){
			currentUser = user;
			return "def:details";
		}else {
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("User Name and Password does not match, are you already registered on the server?"));
			return null;
		}
	}

	public String register() {
		user = new User();
		return "def:register";
	}

	public String save() {
		return null;
	}
}


@Transactional - especifica escopo e propriedades de uma transação
@PersistenceContext - faz a injeção do EntitManager, como se estivessemos programando em um EJB :D @ManagedBean - é uma anotação do Spring-Annotation que marca os managed beans do JSF para habilitar alguns recursos a mais
@Bean - é a anotação do Spring-Annotation que registra um bean no contexto do spring.
@Repository - é a anotação do spring que marca este bean para que seja feita tradução automática de excessões.

Bom, acho que era isto, como vocês podem ver, o código fica bem mais limpo do que fazendo manualmente, ou seja, ficar enchendo o código de:

		EntityManagerFactory emf = Persistence.createEntityManagerFactory("personal_Finance");
		EntityManager em = emf.createEntityManager();

e sendo obrigado a cuidar do ciclo de vida das transações e do entity manager manualmente …

Bom, fica a dica, qualquer duvida ou dica para melhorar este exemplo é só postar a baixo.

Se você gostou deste post, lembre-se de assinar o RSS feed do blog, para ser notificado de novos posts!

Tags: , ,

Reader's Comments

  1. |

    Meu Caro Urubatan, uso JPA e preciso setar o usuário e senha do banco pelo código, como poderia fazer utilizando o SA?

    Reply to this comment

Leave a Comment