Dificuldades com Hibernate e Spring

11 respostas
5leipn1r

Olá pessoal, blz?
Depois de um tempo parado fui pegar pra fazer uns exercicios com JAVA e estou tendo umas dificuldades…
Esse pequeno projetinho que to fazendo, já tinha feito a um tempinho atrás, basicamente fui dando ctrl+c, ctrl+v em vários trechso do código e modificando e completando o que faltava…
Até onde eu vejo, está tudo certo, mas estou tendo ums erros.
Vou postar o codigo das minhas classes Usuario.java, UsuarioDecorator.java, JPADAO.java, TesteUsuRepository.java e meu applicationContext.xml Se precisar de mais alguma coisa me avisem. No final do posto segue o trace do erro.
Eu percebi que no trace diz alguma coisa sobre “No Persistence provider for EntityManager named informit” mas não consegui entender o significado disso, aparentemente tá tudo certo.
Desculpa o excesso de código, mas espero que pelo menos isso ajude alguém a me dar uma pista de onde está meu problema.

PS: Se no arquivo TesteUsuRepository.java que é um JUnit Test Case eu removo a dependencia do Spring e crio “na mão” o UsuarioDecorator e o JPADAO tudo funciona certinho, já fiz esse teste. Inclusive grava no banco de dados, tudo correto. Mas com o Spring num vai…

Agradeço dese já a atenção. Valew.


applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
	
<beans default-autowire="byName">
	
	<bean id="usuTeste" class="mitologics.model.beans.Usuario">
		<property name="login" value="usuario" />
		<property name="nome" value="Usuario Teste" />
		<property name="senha" value="teste" />
		<property name="direitos" value="ADMIN" />
		<property name="ativo" value="true" />
	</bean>
	
	<bean id="conTeste" class="mitologics.model.beans.Contato">
		<property name="nome" value="Teste" />
		<property name="apelido" value="Contato Teste" />
		<property name="contato" value="Alguem" />
		<property name="endereco" value="Rua Teste" />
		<property name="numero" value="1000" />
		<property name="bairro" value="Bairro Teste" />
		<property name="cidade" value="Testopolis" />
		<property name="uf" value="SP" />
		<property name="complemento" value="Casa" />
		<property name="referencia" value="Proximo ao outro Teste" />
		<property name="cep" value="13000000" />
		<property name="tel1" value="([telefone removido]" />
		<property name="tel2" value="([telefone removido]" />
		<property name="email1" value="[email removido]" />
		<property name="site" value="http://www.teste.com" />
		<property name="cpfcnpj" value="[telefone removido]" />
		<property name="rgie" value="22222222" />
		<property name="indicado" value="Teste2" />
	</bean>	

	<bean id="usuDAO" class="mitologics.dao.JPADAO">
		<constructor-arg value="mitologics.model.beans.Usuario" />
	</bean>
	<bean id="usuRepo" class="mitologics.model.infrastructure.UsuarioDecorator">
		<property name="dao" ref="usuDAO"/>
	</bean>
	
	<bean id="conDAO" class="mitologics.dao.JPADAO">
		<constructor-arg value="mitologics.model.beans.Contato" />
	</bean>
	<bean id="conRepo" class="mitologics.model.infrastructure.ContatoDecorator">
		<property name="dao" ref="conDAO"/>
	</bean>
	
</beans>

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
	<persistence-unit name="informit">
		<provider>org.hibernate.ejb.HibernatePersistence</provider>
		<class>mitologics.model.beans.Usuario</class>
		<class>mitologics.model.beans.Contato</class>
		<properties>
			<property name="hibernate.archive.autodetection" value="class, hbm"/>
			<property name="hibernate.show_sql" value="true"/>
			<property name="hibernate.format_sql" value="true"/>
			<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect"/>
			<property name="hibernate.connecion.driver_class" value="com.mysql.jdbc.Driver"/>
			<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/informit"/>
			<property name="hibernate.connection.username" value="mitologics"/>
			<property name="hibernate.connection.password" value="mitologics"/>
		</properties>
	</persistence-unit>
</persistence>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
	<display-name>InforMitJPA</display-name>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath*:applicationContext*.xml</param-value>
	</context-param>

	<!-- Listeners -->
	<listener>
    	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

   <!-- Welcome file lists -->
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
		<welcome-file>index.jsp</welcome-file>
		<welcome-file>default.html</welcome-file>
		<welcome-file>default.htm</welcome-file>
		<welcome-file>default.jsp</welcome-file>
	</welcome-file-list>
</web-app>

JPADAO.java

package mitologics.dao;

import java.util.List;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.NoResultException;
import javax.persistence.Persistence;
import javax.persistence.PersistenceException;
import javax.persistence.Query;

@SuppressWarnings("unchecked")
public class JPADAO<PersistentObject, IDType> implements DAO<PersistentObject, IDType> {

	private static final String PERSISTENCE_UNIT = "informit";
	
	private Class<PersistentObject> persistentClass;
	private EntityManager em;
    private static EntityManagerFactory emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT);
	
    public JPADAO(Class<PersistentObject> clazz) {
        persistentClass = clazz;
    }
    
    protected EntityManager getEntityManager() {
        if (emf == null || !emf.isOpen()) {
            emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT);
        }

        if (em != null && em.isOpen()) {
            return em;
        }
        return emf.createEntityManager();
    }
    
	public void close() {
		if (em != null && em.isOpen())
            em.close();
	}

	public PersistentObject find(IDType id) {
		em = getEntityManager();
		return em.find(persistentClass, id);
	}

	public PersistentObject getByNamedQuery(String queryName, Map<String, Object> params) {
		em = getEntityManager();
		Query query = em.createNamedQuery(queryName);
		
		if(params != null && !params.isEmpty()){
			for(String key : params.keySet()){
				query.setParameter(key, params.get(key));
			}
		}
		PersistentObject result;
		
		try{
			result = (PersistentObject) query.getSingleResult();
		}catch(NoResultException nre){
			try {
				return persistentClass.newInstance();
			} catch (InstantiationException e) {
				throw new RuntimeException("Error in named query: "+queryName + " - InstatiationException");
			} catch (IllegalAccessException e) {
				throw new RuntimeException("Error in named query: "+queryName + " - IllegalAccessException");
			}
		}
		return result;
	}

	public List<PersistentObject> list() {
		em = getEntityManager();
		Query query = em.createQuery("SELECT obj FROM " + persistentClass.getSimpleName() + " obj");
		List<PersistentObject> list = query.getResultList();
		return list;
	}

	public List<PersistentObject> listByNamedQuery(String queryName, Map<String, Object> params) {
		em = getEntityManager();
		Query query = em.createNamedQuery(queryName);
		if(params != null && !params.isEmpty()){
			for(String key : params.keySet()){
				query.setParameter(key, params.get(key));
			}
		}
		List<PersistentObject> list = query.getResultList();
		return list;
	}

	public PersistentObject merge(PersistentObject obj) {
		em = getEntityManager();
		EntityTransaction tx = em.getTransaction();
		try{
			tx.begin();
			obj = em.merge(obj);
			tx.commit();
		}catch(PersistenceException pe){
			tx.rollback();
			pe.printStackTrace();
		}
		return obj;
	}

	@SuppressWarnings("finally")
	public PersistentObject persist(PersistentObject obj) {
		em = getEntityManager();
		EntityTransaction tx = em.getTransaction();
		try{
			tx.begin();
			em.persist(obj);
			tx.commit();
			try{
				em.refresh(obj);
			}finally{
				return obj;
			}
		}catch(PersistenceException pe){
			tx.rollback();
			pe.printStackTrace();
		}
		return obj;
	}

	public void remove(PersistentObject obj) {
		em = getEntityManager();
		EntityTransaction tx = em.getTransaction();
		try{
			tx.begin();
			obj = em.merge(obj);
			em.remove(obj);
			tx.commit();
		}catch(RuntimeException re){
			tx.rollback();
			re.printStackTrace();
			throw re;
		}
	}
}

Usuario.java

package mitologics.model.beans;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;

@Entity
@NamedQueries( { @NamedQuery(name = "Usuario.getByLogin", query = "SELECT u FROM Usuario u WHERE u.login = :login and u.senha = :senha") })
public class Usuario implements Serializable {

	private static final long serialVersionUID = 1L;
	
	@Id
	@Column(nullable = false, unique = true)
	private String login;
	
	private String nome;
	
	@Column(nullable = false)
	private String senha;
	
	private String direitos;
	
	private boolean ativo;
	
	//Construtor padrão
	public Usuario() {
	}
	
	
	//Construtor minimo
	public Usuario(String login, String senha) {
		super();
		this.nome = login;
		this.login = login;
		this.senha = senha;
		this.ativo = false;
	}

	//Construtor completo
	public Usuario(String login, String senha,
			String nome, String direitos, boolean ativo) {
		super();

		this.direitos = direitos;
		this.login = login;
		this.nome = nome;
		this.senha = senha;
		this.ativo = ativo;
	}

	public final String getLogin() {
		return login;
	}

	public final void setLogin(String login) {
		this.login = login;
	}

	public final String getNome() {
		return nome;
	}

	public final void setNome(String nome) {
		this.nome = nome;
	}

	public final String getSenha() {
		return senha;
	}

	public final void setSenha(String senha) {
		this.senha = senha;
	}

	public final String getDireitos() {
		return direitos;
	}

	public final void setDireitos(String direitos) {
		this.direitos = direitos;
	}

	public final boolean getAtivo() {
		return ativo;
	}
	
	public final boolean isAtivo() {
		return ativo;
	}

	public final void setAtivo(boolean ativo) {
		this.ativo = ativo;
	}

	@Override
	public Usuario clone(){
		return new Usuario(this.getLogin(), this.getSenha(), this.getNome(), this.getDireitos(), this.getAtivo());
	}

	@Override
	public boolean equals(Object obj) {
		Usuario tmpUsu = (Usuario)obj;
		if (this.getLogin() == tmpUsu.getLogin())  
			return true;
		else
			return false;
	}

	@Override
	public String toString() {
		return this.login + "," + this.senha + "," + this.nome + "," + this.direitos + "," + this.ativo;
	}
}

UsuarioDecorator.java

package mitologics.model.infrastructure;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.NoResultException;
import mitologics.dao.DAO;
import mitologics.model.beans.Usuario;

public class UsuarioDecorator implements UsuarioRepository {

	private DAO<Usuario, String> dao;

	public void setDao(DAO<Usuario, String> dao) {
		this.dao = dao;
	}
	
	@Override
	public List<Usuario> allUsers() {
		return dao.list();
	}

	@Override
	public void remove(Usuario usu) {
		dao.remove(usu);
	}

	@Override
	public Usuario save(Usuario usu) {
		Usuario newUsu = usu.clone();
		if (dao.find(usu.getLogin()) != null) {
			return dao.merge(usu);
		}
		return dao.persist(newUsu);
	}

	@Override
	public Usuario userWithId(String id) {
		return dao.find(id);
	}

	@Override
	public Usuario userWithLogin(String login, String senha) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("login", login);
		params.put("senha", senha);
		try {
			return dao.getByNamedQuery("Usuario.getByLogin", params);
		} catch (NoResultException nre) {
			return null;
		}
	}
}

Testeusuario.java (JUnit4)

package mitologics.test;

import static junit.framework.Assert.*;
import java.util.List;
import mitologics.model.beans.Usuario;
import mitologics.model.infrastructure.UsuarioDecorator;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TesteUsuario {

	private static UsuarioDecorator repo;
	private static ApplicationContext ctx;
	
	@BeforeClass
	public static void prepare() {
		ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
		repo = (UsuarioDecorator) ctx.getBean("usuRepo");
	}
	
	@Test
	public void Teste(){
		Usuario admin = repo.userWithId("admin");
		if (admin != null)
			if (admin.getLogin() != null) 
				repo.remove(admin);
		Usuario usu1 = (Usuario) ctx.getBean("usuTeste");
		usu1 = repo.save(usu1);
		assertNotNull(usu1);
		assertEquals("ADMIN",usu1.getDireitos());
		usu1.setDireitos("CLIENT");
		usu1 = repo.save(usu1);
		assertEquals("CLIENT",usu1.getDireitos());
		Usuario usu2 = new Usuario("teste", "teste123");
		assertNotNull(usu2);
		usu2.setNome("Teste 2");
		usu2 = repo.save(usu2);
		assertNotNull(usu2);
		List<Usuario> usus = repo.allUsers();
		assertEquals(2,usus.size());
		usu2 = null; 
		usu2 = repo.userWithLogin("teste", "teste456");
		assertNull(usu2.getLogin());
		usu2 = repo.userWithLogin("teste", "teste123");
		assertNotNull("teste123", usu2.getSenha());
		repo.remove(usu2);
		usus = null;
		usus = repo.allUsers();
		assertEquals(1,usus.size());
		repo.remove(usu1);
		assertNull(repo.userWithId("usuario"));
		Usuario usu3 = new Usuario("admin", "admin123", "Administrador", "ADMIN", true);
		repo.save(usu3);
		assertNotNull(repo.userWithId("admin"));
	}
}

Log de erro

Log de erro


Contato.java

package mitologics.model.beans;

import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;

@Entity
@NamedQueries( { @NamedQuery(name = "Contato.getByName", query = "SELECT c FROM Contato c WHERE c.nome = :nome") })
public class Contato implements Serializable {

	private static final long serialVersionUID = 1L;

	@Id
	@Column(nullable = false, unique = true)	
	private int id;
	
	@Column(nullable = false)
	private String nome;
	private String apelido;
	private String contato;
	private String endereco;
	private String numero;
	private String bairro;
	
	@Column(nullable = false)
	private String cidade;
	
	@Column(nullable = false)
	private String uf;
	private String complemento;
	private String referencia;
	private String cep;
	
	@Column(nullable = false)
	private String tel1;
	private String tel2;
	private String tel3;
	private String email1;
	private String email2;
	private String site;
	private String cpfcnpj;
	private String rgie;
	private String indicado;
	private Date nascimento;

	//Construtor padrão
	public Contato(){
	}

	//Construtor minimo
	public Contato(String nome, String cidade, String uf, String tel1) {
		super();
		this.nome = nome;
		this.apelido = nome;
		this.cidade = cidade;
		this.tel1 = tel1;
		this.uf = uf;
	}

	//Construtor completo
	public Contato(int id, String nome, String apelido, String contato, String endereco, 
			String numero, String complemento, String bairro, String cidade, String uf, 
			String referencia, String cep, String tel1, String tel2, String tel3,  
			String email1, String email2, String site,  String cpfcnpj, String rgie,
			String indicado, Date nascimento) {
		super();
		this.apelido = apelido;
		this.bairro = bairro;
		this.cep = cep;
		this.cidade = cidade;
		this.complemento = complemento;
		this.contato = contato;
		this.cpfcnpj = cpfcnpj;
		this.email1 = email1;
		this.email2 = email2;
		this.endereco = endereco;
		this.id = id;
		this.indicado = indicado;
		this.nascimento = nascimento;
		this.nome = nome;
		this.numero = numero;
		this.referencia = referencia;
		this.rgie = rgie;
		this.site = site;
		this.tel1 = tel1;
		this.tel2 = tel2;
		this.tel3 = tel3;
		this.uf = uf;
	}

	public final int getId() {
		return id;
	}

	public final void setId(int id) {
		this.id = id;
	}

	public final String getNome() {
		return nome;
	}

	public final void setNome(String nome) {
		this.nome = nome;
	}

	public final String getApelido() {
		return apelido;
	}

	public final void setApelido(String apelido) {
		this.apelido = apelido;
	}

	public final String getContato() {
		return contato;
	}

	public final void setContato(String contato) {
		this.contato = contato;
	}

	public final String getEndereco() {
		return endereco;
	}

	public final void setEndereco(String endereco) {
		this.endereco = endereco;
	}

	public final String getNumero() {
		return numero;
	}

	public final void setNumero(String numero) {
		this.numero = numero;
	}

	public final String getBairro() {
		return bairro;
	}

	public final void setBairro(String bairro) {
		this.bairro = bairro;
	}

	public final String getCidade() {
		return cidade;
	}

	public final void setCidade(String cidade) {
		this.cidade = cidade;
	}

	public final String getUf() {
		return uf;
	}

	public final void setUf(String uf) {
		this.uf = uf;
	}

	public final String getComplemento() {
		return complemento;
	}

	public final void setComplemento(String complemento) {
		this.complemento = complemento;
	}

	public final String getReferencia() {
		return referencia;
	}

	public final void setReferencia(String referencia) {
		this.referencia = referencia;
	}

	public final String getCep() {
		return cep;
	}

	public final void setCep(String cep) {
		this.cep = cep;
	}

	public final String getTel1() {
		return tel1;
	}

	public final void setTel1(String tel1) {
		this.tel1 = tel1;
	}

	public final String getTel2() {
		return tel2;
	}

	public final void setTel2(String tel2) {
		this.tel2 = tel2;
	}

	public final String getTel3() {
		return tel3;
	}

	public final void setTel3(String tel3) {
		this.tel3 = tel3;
	}

	public final String getEmail1() {
		return email1;
	}

	public final void setEmail1(String email1) {
		this.email1 = email1;
	}

	public final String getEmail2() {
		return email2;
	}

	public final void setEmail2(String email2) {
		this.email2 = email2;
	}

	public final String getSite() {
		return site;
	}

	public final void setSite(String site) {
		this.site = site;
	}

	public final String getCpfcnpj() {
		return cpfcnpj;
	}

	public final void setCpfcnpj(String cpfcnpj) {
		this.cpfcnpj = cpfcnpj;
	}

	public final String getRgie() {
		return rgie;
	}

	public final void setRgie(String rgie) {
		this.rgie = rgie;
	}

	public final String getIndicado() {
		return indicado;
	}

	public final void setIndicado(String indicado) {
		this.indicado = indicado;
	}

	public final Date getNascimento() {
		return nascimento;
	}

	public final void setNascimento(Date nascimento) {
		this.nascimento = nascimento;
	}
}

ContatoDecorator.java

package mitologics.model.infrastructure;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.NoResultException;

import mitologics.dao.DAO;
import mitologics.model.beans.Contato;

public class ContatoDecorator implements ContatoRepository {

	private DAO<Contato, Integer> dao;

	public void setDao(DAO<Contato, Integer> dao) {
		this.dao = dao;
	}
	
	@Override
	public List<Contato> allContacts() {
		return dao.list();
	}

	@Override
	public Contato contByName(String nome) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("nome", nome);
		try {
			return dao.getByNamedQuery("Contato.getByName", params);
		} catch (NoResultException nre) {
			return null;
		}
	}

	@Override
	public Contato contWithId(int id) {
		return dao.find(id);
	}

	@Override
	public void remove(Contato con) {
		dao.remove(con);
	}

	@Override
	public Contato save(Contato con) {
		Contato tmpCon;
		if(con != null)
			if(con.getId() != 0)
				tmpCon = dao.merge(con);
	
		tmpCon = dao.persist(con);
		
		if (tmpCon.getId() != 0)
			return tmpCon;
		else	
			return contByName(tmpCon.getNome());
	}

}

TesteContato.java (Junit4)

package mitologics.test;

import static junit.framework.Assert.*;
import mitologics.model.beans.Contato;
import mitologics.model.infrastructure.ContatoDecorator;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TesteContato {

	private static ContatoDecorator repo;
	private static ApplicationContext ctx;
	
	@BeforeClass
	public static void prepare() {
		ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
		repo = (ContatoDecorator) ctx.getBean("conRepo");
	}

	@Test
	public void Teste() {
		Contato mitologics = repo.contByName("Mitologics");
		if (mitologics != null)
			if (mitologics.getId() != 0) 
				repo.remove(mitologics);
		Contato con1 = (Contato) ctx.getBean("conTeste");
		con1 = repo.save(con1);
		assertNotNull(con1);
		System.out.println("Id do Contato gravado: " + con1.getId());
		assertEquals(7, con1.getId());
	}
}

11 Respostas

wariows

tá faltando a configuração da persistence unit (persistence.xml) e do entitymanager no applicationContext.xml

Este link pode te ajudar: http://icoloma.blogspot.com/2006/11/jpa-and-spring-fucking-cooltm_26.html

5leipn1r

wariows, brigado pela força, mas olhando o site que vc passou só fiquei mais confuso do que já estava. Pq tenho certeza que esse método que eu usei funciona pq já tinha usado em outro projeto. Só não sei exatamente onde estou errando.
Tenho quase certeza que tem alguma coisa a ver com isso:

INFO: Could not find any META-INF/persistence.xml file in the classpath

ou isso:

Caused by: javax.persistence.PersistenceException: No Persistence provider for EntityManager named informit

Eu tentei adaptar algumas linhas do que tinha naquele site que vc passou para o meu applicationContext.xml mas acabei me perdendo no meio do caminho e desfiz e deixei como estava.

Eu disse no post que eu minha pasta META-INF estava no classpath, mas eu não tenho certeza disso, talvez seja esse o problema. Eu criei ela dentro da pasta src, é um dinamic web project. Quando eu coloquei o applicationConext.xml lá dentro a aplicação não reconheceu ele de cara, tive que ir no Build Path, Lybraries, e Add Class Folder, pq caso contrario tinha que deixar meu applicationContext.xml dentro da paasta META-INF/classes dentro da pasta WebContent. Mas após adicionar o Class Folder passou a reconhecer. Mas parece que o persistence.xml que tá lá dentro não está sendo reconhecido pelo Spring, mas se eu não usar o ctx = new ClassPathXmlApplicationContext(“applicationContext.xml”); repo = (UsuarioDecorator) ctx.getBean(“repoTeste”); e criar manualmente o repositorie e o dao, aí funciona. Mas eu queria que funcionasse com o Spring.

Mais alguma dica?

5leipn1r

Não sei se considerarei esse problema como resolvido ainda pq gostaria de uma opnião se o que eu fiz está certo.

Percebi que no Build Path da minha aplicação, na aba source, onde tinha a minha pasta src, estava dizendo que minha pasta META-INF dentro de src estava como exclude. Então eu editei isso e tirei de lá. deu conflito porque eu tinha colocado a pasta META-INF como uma Class Folder, então eu exclui ela da aba Libraries. Mas aí a aplicação não achava mais o applicationContext.xml, então movi o arquivo para a pasta WebContent/WEB-INF e adicionei essa pasta na aba Libraries como uma Class Folder. Aí a aplicação funcionou.

Queria saber se essa solução não acabou violando nada e se não é uma gambiarra ou coisa do tipo, ou se o que eu fiz está mesmo certo. Pelo menos consigo rodar o JUnit e fazer o teste com sucesso da minha classe.

wariows

o persistence.xml fica numa pasta META-INF dentro do src, e o applicationContext.xml fica dentro da pasta WebContent/WEB-INF

vc não precisar adicionar nenhum deles como class folder!

Quanto a configuração para que o spring tome conta das instancias da EntityManager e injete elas nos DAO’s pra você, normalmente faço assim:

persistence.xml

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
    version="1.0">
    <persistence-unit name="punit">
       //Minhas configurações vão no applicationContext.xml
       //Se eu quiser posso adicionar configurações aqui tbm
    </persistence-unit>
</persistence>

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-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/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

    <bean
        class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="jpaVendorAdapter">
            <bean
                class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="database" value="POSTGRESQL" />
                <property name="showSql" value="true" />
            </bean>
        </property>
    </bean>

    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="org.postgresql.Driver" />
		<property name="url" value="jdbc:postgresql://localhost:5432/meubanco" />
		<property name="username" value="meuusuario" />
		<property name="password" value="minhasenha" />
    </bean>
  
    //Minha configuração de transação (se eu quiser que o spring faça o controle transacional)

    //Meus DAO's
</beans>

[]'s

5leipn1r

wariows, mais uma vez, obrigado.
Não sei porque, mas se eu não adicionar a pasta Web-Content/WEB-INF como Class Folder o JUnit não reconhece o ApplicationContext lá dentro. Mas tudo bem, sem problemas, pelo menos está funcionando.
Outra coisa. Mesmo com a sua tentativa de me explicar mais detalhadamente o que eu tenho que fazer no ApplicationContext.xml e no persistence.xml pra ficar “politicamente correto” rsrs a injeção de dependencias do Hibernate, eu não consegui entender o que exatamente eu preciso mudar, até onde eu enxergo parece que está ok do jeito que eu fiz, provavelmente por eu ser meio leigo e iniciante no Spring e mais ainda no Hibernate. Mas tudo bem tb, pq afinal de contas até que tá funcionando…
Porém, encontrei um problema muito bizzaro na aplicação, vou ver se consigo detalhar o problema e a “gambiarra” que eu tive que fazer pra funcionar, na experança de uma solução melhor do que a que eu improvisei…
Para isso vou atualizar no post principal os arquivos necessários e postar os novos para referencia.
Segue a explicação no proximo post logo abaixo.

5leipn1r

Eu suspeito que o meu problema seja devido a falta de alguma anotation do Hybernate, ou algo do tipo. Eu estou usando o MySQL como banco de dados. Detalhes da conexão podem ser vistos no persistence.xml.
O problema está nesse trechode código do meu JPADAO.java (Original, antes das modificações que o deixaram como no post mais acima)

public PersistentObject persist(PersistentObject obj) {
	em = getEntityManager();
	EntityTransaction tx = em.getTransaction();
	try{
		tx.begin();
		em.persist(obj);
		tx.commit();
		em.refresh(obj);
		return obj;
	}catch(PersistenceException pe){
		tx.rollback();
		pe.printStackTrace();
	}
	return obj;
}

O problema está no comando em.refresh(obj) quando eu tento salvar um contato novo. Inicialmente o contato não tem um Id, o iD é “0” (zero), mas após o comando em.persist(obj) e o tx.commit() quando vai fazer o refresh ele diz que não pode encontrar um registro com id “0”. Não sei pq ele procura com id “0”, não consigo entender. E então dá um erro e aborta o JUnit no meio com o seguinte trace:

O erro de transaction not active é pq ao tentar dar o refresh cauxa uma exception, jogando para o catch do bloco que tenta fazer um rollback, e não consegue pq a transaction já foi fechada pelo commit anteriormente.

Outra gambiarra que tive que fazer também foi no arquivo ContatoDecorator.java, no seguinte trecho de código:

@Override
	public Contato save(Contato con) {
		Contato tmpCon;
		if(con != null)
			if(con.getId() != 0)
				tmpCon = dao.merge(con);
	
		tmpCon = dao.persist(con);
		
		if (tmpCon.getId() != 0)
			return tmpCon;
		else	
			return contByName(tmpCon.getNome());
	}

Onde tenho que buscar o contato novamente no banco de dados com o contByName caso a id seja “0” após o save (indicando que deu erro pra dar o refresh).

Gente, tem que ter uma solução melhor pra isso do que o que eu fiz.
Alguma sugestão?
Se precisar que eu envie mais algum trecho de código, ou os scripts de criação das tabelas ou qualquer outra coisa é só falar.
Muito obrigado por enquanto pela ajuda.

5leipn1r

Acho que consegui resolver o problema, adicionando a seguinte anotation hibernate no Contato.class

@GeneratedValue(strategy = GenerationType.AUTO) private int id;
Aparentemente o problema está resolvido, mas qualquer sugestão será muito bem-vinda.

wariows

De cara duas coisas que percebi que podem ser melhoradas:

  1. O controle transacional não deve ser feito nos DAO’s… Imagine uma operação simples como uma transferência bancária, imagine que você a invoque através de um controlador que recupere as contas do(s) repositórios(s) e invoque as operações sacar(valor) em uma delas e depositar(valor) na outra (temos aqui 2 instâncias de uma classe quualquer Conta), daí o próximo passo seria avisar aos repositórios que aquelas contas mudaram através de um put(conta). Se você fizer o controle transacional dentro dos DAO’s, teriamos aqui duas transações, uma para a primeira conta, e outra para a segunda conta (percebe isso?)… Imagine que ocorra algum problema no depósito (a operação de sacar foi bem sucedida) e precisa ser feito um rollback da operação de transferência inteira, o que não é possível, pois a operação de sacar já foi commitada!!

Solução:

1º) Fazer o controle transacional na fachada.
2º) Utilizar AOP (O Spring pode utilizar AOP e cuidar do controle transacional pra você!)

  1. Se você fizer do jeito que expliquei acima, o spring poderá injetar o Entity Manager nos seus DAO’s.
    Assim o seu DAO ficaria assim:
public class JPADAO {

     @PersistenceContext
     protected EntityManager entityManager;

}
5leipn1r

Não consigo fazer a aplicação encontrar o ApplicationContext.xml (DINOVO)!
Criei os servlets pra começar minha aplicação, e na hora de rodar no tomcat, adivinha…

meu arquivo applicationContext.xml está na pasta WEB-INF que está na pasta WebContent.
Não sei mais o que fazer, to ficando irritado, já fucei em tudo e num vai!

Abaixo segue uma listagem das minhas libs:

PS: Se eu criar um package chamado resources por exemplo, e colocar o applicationContext.xml lá dentro e no comando chamar indicando o package funciona:

ApplicationContext ctx = new ClassPathXmlApplicationContext("resources/applicationContext.xml"); UsuarioDecorator repo = (UsuarioDecorator) ctx.getBean("usuRepo");

Mas eu não queria deixar assim, eu queria que ele ficasse no META-INF ou no WebContent/WEB-INF. Como eu faço isso?

wariows

Você tá criando o aplication context na mão? Isso é pra usar no JUnit é?

5leipn1r

Sim, criei o applicationContext na mão, quando eu fui usar com o JUnit eu colocava a pasta WEB-INF no class path e funcionava, mas no Servlet não funciona nem colocando no class path, nem colocando no meta-inf.
A forma que eu encontrei foi colocar ele no META-INF e pra carregar ele eu chamo ele assim:

ApplicationContext ctx = new ClassPathXmlApplicationContext("WEB-INF/applicationContext.xml"); UsuarioDecorator repo = (UsuarioDecorator) ctx.getBean("usuRepo");
E tive que especificar no web.xml tb onde se encontra o applicationContext, senão a aplicação nem iniciava.
Não sei se é a forma correta de fazer… mas ainda estou meio confuso…

Criado 20 de setembro de 2008
Ultima resposta 23 de set. de 2008
Respostas 11
Participantes 2