Spring + Hibernate

Olá!

Gostaria de saber o que eu preciso aprender sobre Spring, pra poder usa-lo junto com Hibernate. Digo isto porque o Spring tem muitos modulos, e muita documentação…Alguém saberia me informar mais especificamente o que devo estudar?

Pretendo usar o Spring só pra me ajudar com os DAO’s e persistencia…essas coisas…nada muito avançado.

Obrigado!
Att,
Filipe Santana.

Com base no que você diz interessado em aprender, Injeção de Dependência (Dependency Injection) / Inversão de Controle uma boa direção.

gerenciamento de transações tb…Além que é preciso configurar os dois para trabalharem juntos!

Documentação oficial do Spring tem tudo que vc precisa!

Obrigado!

Estou seguindo este livro: Spring Recipes

Pelo o que vi o Spring irá me ajudar:

  1. Configuração da session do hibernate direto no Spring.

  2. Possui o HibernateTemplate/HibernateDaoSupport ou como alternativa eu posso usar o Hibernate’s contextual sessions.

Isso já ajuda bastante não é? Como eu tenho varias classes[60+] , seria um pouco demorado criar um DAO pra cada classe…O que eu poderia usar, DAO genérico? Alguém poderia indicar algum material sobre DAO genérico se for o caso.

T+,
Filipe Santana.

Posso seguir este tutorial da IBM pra implementar um DAO Genérico. Alguém usa desta forma?

http://www.ibm.com/developerworks/java/library/j-genericdao.html#icomments

Obrigado!

A apostila FJ28 da Caelum também pode auxiliar bastante nas suas necessidades (Hibernate + Spring)

Obrigado pela ajuda…

Na vdd eu preciso de mais alguma ajuda:

Seguindo este link eu consegui montar um Dao generico da forma como é mostrado no tutorial.
Ficou assim…

package genericdao;
import java.io.Serializable;

public interface GenericDao<T, PK extends Serializable> {

	/** Persist the newInstance object into database */
	PK create(T newInstance);

	/**
	 * Retrieve an object that was previously persisted to the database using
	 * the indicated id as primary key
	 */
	T read(PK id);

	/** Save changes made to a persistent object. */
	void update(T transientObject);

	/** Remove an object from persistent storage in the database */
	void delete(T persistentObject);
}
package genericdao.impl;

import genericdao.GenericDao;

import java.io.Serializable;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@Repository
public abstract class GenericDaoHibernateImpl<T, PK extends Serializable> implements
		GenericDao<T, PK> {

	private SessionFactory sessionFactory;

	@Autowired
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}
	
	public SessionFactory getSessionFactory() {
		return this.sessionFactory;
	}

	private Class<T> type;
	
	public GenericDaoHibernateImpl() {
		// TODO Auto-generated constructor stub
	}

	public GenericDaoHibernateImpl(Class<T> type) {
		this.type = type;
	}

	@Transactional
	public PK create(T o) {
		return (PK) sessionFactory.getCurrentSession().save(o);
	}

	@Transactional(readOnly = true)
	public T read(PK id) {
		return (T) sessionFactory.getCurrentSession().get(type, id);
	}

	@Transactional
	public void update(T o) {
		sessionFactory.getCurrentSession().update(o);
	}

	@Transactional
	public void delete(T o) {
		sessionFactory.getCurrentSession().delete(o);
	}

}

Ai arquivo do Spring ficou assim:

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
		<property name="configLocation" value="classpath:hibernate.cfg.xml" />
	</bean>

	<tx:annotation-driven />

	<bean id="transactionManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>

	<context:component-scan base-package="genericdao.impl" />

	<bean
		class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

	<bean id="courseDao" class="genericdao.impl.GenericDaoHibernateImpl">
		<constructor-arg>
			<value>dominio.Course</value>
		</constructor-arg>
	</bean>


</beans>

Pra usar eu faço assim:

package genericdao.teste;

import genericdao.GenericDao;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import dominio.Course;

public class Main {

	public static void main(String[] args) {

		ApplicationContext context = new ClassPathXmlApplicationContext(
				"beans-hibernate.xml");
		
		GenericDao dao = (GenericDao) context.getBean("courseDao");
		
		Course course = new Course();
		course.setTitle("Core DAO");
		
		dao.create(course);

	}

}

O problema com esta solução é que eu só tenho os metodos do Dao generico na interface.

Depois eu criei uma interface para incluir metodos especificos para uma determinada classe:

package genericdao;

import dominio.Course;

public interface CourseDao extends GenericDao<Course, Long> {
	Course findByTitle(String courseTitle);

}

e fiz a implementação dessa interface:

package genericdao.impl;

import org.hibernate.Query;

import genericdao.CourseDao;
import dominio.Course;

public class CoursHibernateDao extends GenericDaoHibernateImpl<Course, Long>
		implements CourseDao {

	@Override
	public Course findByTitle(String courseTitle) {

		Query q = super.getSessionFactory().getCurrentSession()
				.getNamedQuery("findByTitle");
		q.setParameter("title", courseTitle);
		return (Course) q.uniqueResult();

	}

}

Só que agora eu não sei como incluir isso no arquivo do Spring pra poder usar.

Antes eu fazia assim:

<bean id="courseDao" class="genericdao.impl.GenericDaoHibernateImpl">
		<constructor-arg>
			<value>dominio.Course</value>
		</constructor-arg>
	</bean>

Será que basta trocar o GenericDaoHibernateImpl por CourseHibernateDao? Eu acho que não preciso incluir o tipo da classe como faço no construtor acima, ou preciso? Tenho que mudar alguma coisa? Será que alguém pode me dar umas dicas?

Obrigado!

Att,
Filipe Santana.

Olá…

Eu mudei algumas coisas aqui, porém estou ganhando este erro agora:

Exception in thread "main" org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [org.springframework.dao.annotation.PersistenceException TranslationPostProcessor] for bean with name 'org.springframework.dao.annotation.PersistenceException TranslationPostProcessor#0' defined in class path resource [beans-jpa.xml]; nested exception is java.lang.ClassNotFoundException: org.springframework.dao.annotation.PersistenceException TranslationPostProcessor
	at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1250)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:576)
	at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1319)
	at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:885)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:562)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
	at test.Principal.main(Principal.java:14)
Caused by: java.lang.ClassNotFoundException: org.springframework.dao.annotation.PersistenceException TranslationPostProcessor
	at java.net.URLClassLoader$1.run(Unknown Source)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(Unknown Source)
	at java.lang.ClassLoader.loadClass(Unknown Source)
	at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
	at java.lang.ClassLoader.loadClass(Unknown Source)
	at org.springframework.util.ClassUtils.forName(ClassUtils.java:257)
	at org.springframework.beans.factory.support.AbstractBeanDefinition.resolveBeanClass(AbstractBeanDefinition.java:408)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doResolveBeanClass(AbstractBeanFactory.java:1271)
	at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1242)
	... 9 more

Meu código ta assim:

package model;

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;

@Entity
public class Pessoa implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private Integer id;
	private String nome;
	
	public Pessoa() {
		// TODO Auto-generated constructor stub
	}

	public Pessoa(String nome) {
		super();
		this.nome = nome;
	}

	@Id
	@SequenceGenerator(name = "seq", sequenceName = "pessoa_seq", allocationSize = 1)
	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq")
	public Integer getId() {
		return id;
	}

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

	public String getNome() {
		return nome;
	}

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

}
package dao;

import java.io.Serializable;
import java.util.List;

public interface Dao<T, ID extends Serializable> {
	
	public Class<T> getObjectClass();

	public void salvarOuAtualizar(T obj);

	public void excluir(T obj);

	public T bucarPorId(Integer id);

	public List<T> buscarTodos();

}
package dao.impl;

import java.io.Serializable;
import java.util.List;
import java.lang.reflect.ParameterizedType;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import dao.Dao;

@Repository("dao")
public class DaoImpl<T, ID extends Serializable> implements Dao<T, ID> {

	@PersistenceContext
	private EntityManager entityManager;

	private final Class<T> oClass;

	@SuppressWarnings("unchecked")
	public DaoImpl() {
		this.oClass = (Class<T>) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];

	}

	@Override
	public Class<T> getObjectClass() {
		return this.oClass;
	}

	@Transactional
	@Override
	public void salvarOuAtualizar(T obj) {
		entityManager.merge(obj);

	}

	@Transactional
	@Override
	public void excluir(T obj) {
		entityManager.remove(obj);

	}

	@Transactional(readOnly = true)
	@Override
	public T bucarPorId(Integer id) {
		return entityManager.find(oClass, id);
	}

	@Transactional(readOnly = true)
	@SuppressWarnings("unchecked")
	@Override
	public List<T> buscarTodos() {
		Query q = entityManager.createQuery("from " + oClass.getName());
		return q.getResultList();
	}

}
package dao;

import model.Pessoa;

public interface PessoaDao extends Dao<Pessoa, Integer> {

}


package dao.impl;

import org.springframework.stereotype.Repository;

import dao.PessoaDao;
import model.Pessoa;

@Repository("pessoaDao")
public class PessoaDaoImpl extends DaoImpl<Pessoa, Integer> implements
		PessoaDao {

}
package test;

import model.Pessoa;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import dao.PessoaDao;

public class Principal {
	
	public static void main(String[] args) {
		
		ApplicationContext context = new ClassPathXmlApplicationContext("beans-jpa.xml");
		PessoaDao pessoaDao = (PessoaDao) context.getBean("pessoaDao");
		
		Pessoa pessoa = new Pessoa("Filipe");
		
		pessoaDao.salvarOuAtualizar(pessoa);
	}

}
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">


	<bean id="entityManagerFactory"
		class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
		<property name="persistenceUnitName" value="proj" />
	</bean>

	<tx:annotation-driven />

	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
		<property name="entityManagerFactory" ref="entityManagerFactory" />
	</bean>

	<context:annotation-config />

	<bean
		class="org.springframework.dao.annotation.PersistenceException
TranslationPostProcessor" />

	<context:component-scan base-package="dao.impl" />

	<bean id="pessoaDao" class="dao.impl.PessoaDaoImpl" />
	
	





</beans>

Se alguém puder me ajudar…

Obrigado!

Caused by: java.lang.ClassNotFoundException: org.springframework.dao.annotation.PersistenceException TranslationPostProcessor  

Olá rafael blz?

Então eu procurei na net por esse erro ai que você me mostrou, antes de postar aqui. Só que eu não consegui achar nada referente a isso…
Sei que pode estar faltando alguma dependencia do spring…mas eu não sei o nome dela nem como encontrar…
Se souber e puder me passar.

A propósito, você é de fortaleza? Eu to querendo mudar pra sua cidade esse ano ainda talvez…tem campo ai pra trabalhar?
Se puder me add no msn pra gente conversar… aguilar.lipe@gmail.com ou skype <aguilar.lipe>.

Abraços,
t+

Fala Filipe tudo bem?

Vc deve fazer o download do spring e colocar todos os arquivos
spring-xxxx.jar no classpath do projeto.

E sim,eu sou de Fortaleza e sim,a área está bombando :smiley:

Abs

Eu to bem :)…bom saber que ta bombando hehehehehe. Eu termino a faculdade no meio do ano, depois me mudo pra fortaleza :smiley:

Sobre o problema, eu já tenho todos os jars do spring no classpath do meu projeto…

De qualquer forma, eu mudei aqui…de jpa pro hibernate e funcionou! estranho né…

A unica coisa que tive que mudar foi classe DaoImpl. e o arquivo do spring.

package dao.impl;

import java.io.Serializable;
import java.util.List;
import java.lang.reflect.ParameterizedType;

import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import dao.Dao;

@Repository("dao")
public abstract class DaoImpl<T, ID extends Serializable> implements Dao<T, ID> {

	@Autowired
	private SessionFactory sessionFactory;

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	private final Class<T> oClass;

	@SuppressWarnings("unchecked")
	public DaoImpl() {
		this.oClass = (Class<T>) ((ParameterizedType) (getClass()
				.getGenericSuperclass())).getActualTypeArguments()[0];

	}

	@Override
	public Class<T> getObjectClass() {
		return this.oClass;
	}

	@Transactional
	@Override
	public void salvarOuAtualizar(T obj) {
		sessionFactory.getCurrentSession().saveOrUpdate(obj);

	}

	@Transactional
	@Override
	public void excluir(T obj) {
		sessionFactory.getCurrentSession().delete(obj);

	}

	@SuppressWarnings("unchecked")
	@Transactional(readOnly = true)
	@Override
	public T bucarPorId(Integer id) {
		return (T) sessionFactory.getCurrentSession().get(oClass, id);
	}

	@SuppressWarnings("unchecked")
	@Transactional(readOnly = true)
	@Override
	public List<T> buscarTodos() {
		Query q = sessionFactory.getCurrentSession().createQuery(
				"from " + oClass.getName());
		return q.list();
	}

}
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">


	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
		<property name="configLocation" value="classpath:hibernate.cfg.xml" />
	</bean>

	<tx:annotation-driven />

	<bean id="transactionManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>

	<bean
		class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

	<context:component-scan base-package="dao.impl" />
	
	<bean id="pessoaDao" class="dao.impl.PessoaDaoImpl" />

</beans>

Então, eu tava pegando um erro ainda [Caused by: java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType], mas ai eu mudei a classe DaoImpl pra abstract ai funcionou!!!

Parece que agora ta tudo ok! to testando os metodos :slight_smile:

Flw, daqui uns dia a gente se vê ai em fortaleza ahuehaeuhaue
Valeu!!!

Legal que deu certo!

Só mais uma dica:
Em vez de ter que definir todos os beans da aplicação:

&lt;bean id="pessoaDao" class="dao.impl.PessoaDaoImpl" /&gt;  

Vc pode usar o trecho abaixo que ‘escaneia’ a aplicação procurando por anotações do Spring.

&lt;context:component-scan base-package="*"/&gt;

Obrigado pela dica! Eu já mudei aqui…

Agora basta eu fazer a anotação nos beans como eu fiz neste:

@Repository("pessoaDao")
public class PessoaDaoImpl extends DaoImpl<Pessoa, Integer> implements
		PessoaDao {

...

Ai eu chamo pelo nome(“pessoaDao”/…XxXDao) acima né :stuck_out_tongue:

Deu certo!!!
Abs,

pode deixar só @Repository,não precisa mais passar o nome do componente

Tá certo. O Spring já dá um nome né pro bean, Ele pega o nome da classe começanco com letra minuscula…Deu certo!

Ah!! Sobre o Dao com JPA eu consegui, tava errado o nome deste bean:

<bean
		class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

Eu arrumei, funcionou certinho agora! Tanto o Dao com Hibernate como o com Jpa. É melhor usar o Jpa né?

Valeu!

Olá Pessoal, Boa noite!

Preciso de ajuda pra dar continuação nisso.

Bom a parte do Dao+Spring+Hibernate ta pronta! Quero agora usar isso no JSF!

A minha aplicação como foi mostrada anteriormente, funciona assim:

main... {

ApplicationContext context = new ClassPathXmlApplicationContext("beans-hibernate.xml");
 
XxXDao dao = (XxXDao) context.getBean("XxXDaoImpl");

XxX x = new XxX();

dao.salvarOuAtualizar(x) ou dao.excluir(x) ou qualquer outra...


}

Só que isso funciona no main, fiz só pra testar. Agora eu quero usar isso no JSF! Tenho que mudar algo pra funcinar?

A primeira coisa que vem em minha cabeça, é que eu tenho que adicionar a anotação @ManegedBean do JSF 2.0 em todas em minhas classes XxXDaoImpl.

Que ficaria assim:

@ManegedBean
@SessionScoped // as duas anotações novas que pensei.

@Repository("XxXDaoImpl")
public class XxXDaoImpl extends DaoImpl<XxX, Long> implements
        XxXDao {

}

Sendo assim eu poderia usar esse bean na view do JSF.Será que é mesmo?

Obrigado!
t+