Spring + Hibernate

16 respostas
Filipe_A

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.

16 Respostas

A

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

Tiburcio_Mancha

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!

Filipe_A

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.

Filipe_A

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!

rdsilio

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

Filipe_A

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.

Filipe_A

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!

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

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… [email removido] ou skype <aguilar.lipe>.

Abraços,
t+

R

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

Filipe_A

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!!!

R

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;
Filipe_A

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,

R

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

Filipe_A

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!

Filipe_A

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+

Criado 5 de janeiro de 2011
Ultima resposta 9 de fev. de 2011
Respostas 16
Participantes 5