Integrando Spring 3.0 com Hibernate Annotation 3

Senhores boa noite!

Estou tentando integrar meu sistema com o Spring Framework para utilizar DI e controle de transações.

Anteriormente eu tinha o hibernate.cfg.xml com as configurações de banco de dados e as classes devidamente mapeadas (As classes estão anotadas. Não uso hbms.).

Sempre funcionou legal mas em cada operação com o Banco de Dados eu tinha que fazer:

    Session sessao = HibernateUtil.getSession();

para poder trabalhar com o mysql.

O que quero saber é o que preciso para injetar essa sessão nas minhas DAOs e deixar o spring gerenciar a transação com o openSessionInView?

Seguem meus arquivos para verificação.

hibernate.cfg.xml

<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>

	<session-factory>

        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost/xxx</property>
        <property name="connection.username">root</property>
        <property name="connection.password">xxx</property>
        <property name="connection.pool_size">xxx</property> 
			
		
	<property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
	<property name="c3p0.max_size">100</property>
	<property name="c3p0.min_size">1</property>
	<property name="c3p0.idle_test_period">30</property>
		
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>

        <property name="show_sql">false</property>
        <property name="format_sql">false</property>

        <property name="hbm2ddl.auto">update</property>
		
	<!-- As Classes mapeadas foram omitidas pois não fazer parte do problema  -->
				
	</session-factory>

</hibernate-configuration>

Isso funciona normalmente com o meu HibernateUtil que é a fábrica de sessões. Tranquilo.

Agora tento integrar com o Spring 3.0.5

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-3.0.xsd
	http://www.springframework.org/schema/tx
	http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
	http://www.springframework.org/schema/aop
	http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
   
    <!-- The singleton hibernate session factory -->
	<bean id="sessionFactory" scope="singleton"
		class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
		<property name="configLocation" value="classpath:hibernate.cfg.xml" />
	</bean>

	
	<!-- Spring's hibernate transaction manager -->
	<bean id="transactionManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>
	
	<bean id="permissionarioDAO" class="br.mil.siscop.repositories.PermissionarioDAO">
		<property name="sessionFactory" ref="sessionFactory"/>
	</bean>	
	
	<!-- So classes/functions with @Transactional get a hibernate txn -->
	<tx:annotation-driven />

</beans>

mas quando tento utlizar a Injeção de Dependencia na minha DAO é lançado um NullPointerException quando tento ulitilizar o sessionFactory no método login();

DAO

(A classe está anotada com @Transaction do SPRING)



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


	@Override
	public Permissionario login(String nip, String senha) throws Exception {
		Criteria criteria = this.sessionFactory.getCurrentSession().createCriteria(Permissionario.class);
			criteria.add( Restrictions.idEq(nip));
			criteria.add( Restrictions.eq("deSenha", senha));
		return (Permissionario) criteria.uniqueResult();
	}

Aguardo Resposta!

Meu arquivo Web.xml esta assim:

<?xml version="1.0"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee  http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
	<display-name>ExampleProject Web</display-name>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
		/WEB-INF/applicationContext.xml
		/WEB-INF/applicationContext-security.xml
		</param-value>
	</context-param>
	<context-param>
		<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
		<param-value>.xhtml</param-value>
	</context-param>
  <context-param>
    <param-name>org.richfaces.SKIN</param-name>
    <param-value>#{skinBean.skin}</param-value>
  </context-param>
	<context-param>
		<param-name>org.ajax4jsf.VIEW_HANDLERS</param-name>
		<param-value>com.sun.facelets.FaceletViewHandler</param-value>
	</context-param>
	<filter>
		<display-name>RichFaces Filter</display-name>
		<filter-name>richfaces</filter-name>
		<filter-class>org.ajax4jsf.Filter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>richfaces</filter-name>
		<servlet-name>Faces Servlet</servlet-name>
		<dispatcher>REQUEST</dispatcher>
		<dispatcher>FORWARD</dispatcher>
		<dispatcher>INCLUDE</dispatcher>
	</filter-mapping>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<listener>
		<listener-class>
			org.springframework.web.util.IntrospectorCleanupListener</listener-class>
	</listener>
	<listener>
		<listener-class>
			org.springframework.web.context.request.RequestContextListener</listener-class>
	</listener>
	<servlet>
		<servlet-name>Faces Servlet</servlet-name>
		<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>Faces Servlet</servlet-name>
		<url-pattern>*.faces</url-pattern>
	</servlet-mapping>
	<login-config>
		<auth-method>BASIC</auth-method>
	</login-config>

	<listener>
		<listener-class>
			org.springframework.security.ui.session.HttpSessionEventPublisher</listener-class>
	</listener>




	<filter>
		<filter-name>springSecurityFilterChain</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
	</filter>

	<filter-mapping>
		<filter-name>springSecurityFilterChain</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>


	<listener>
		<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
	</listener>


<filter>
	  <filter-name>hibernateFilter</filter-name>
	  <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
	</filter>


	<filter-mapping>
	  <filter-name>hibernateFilter</filter-name>
	  <url-pattern>/*</url-pattern> 
	</filter-mapping>




    <session-config>  
       <!-- 30 MINUTOS -->  
       <session-timeout>30</session-timeout>  
    </session-config> 
</web-app>

Meu applicationContext.xml esta assim:


<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:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"
	default-autowire="byName" default-lazy-init="false"> 
	<context:annotation-config />
	<context:component-scan base-package="br.com.sansoftware">
		<context:include-filter type="annotation"
			expression="org.springframework.stereotype.Repository" />
	</context:component-scan>


	<tx:annotation-driven proxy-target-class="true" />
 



	<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url" value="jdbc:mysql://localhost/oxrh" />
		<property name="username" value="root" />
		<property name="password" value="123456" />
	</bean>

	<bean id="hibernateProperties"
		class="org.springframework.beans.factory.config.PropertiesFactoryBean">
		<property name="properties">
			<props>
				<prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.c3p0.minPoolSize">5</prop>
				<prop key="hibernate.c3p0.maxPoolSize">20</prop>
				<prop key="hibernate.c3p0.timeout">600</prop>
				<prop key="hibernate.c3p0.max_statement">50</prop>
				<prop key="hibernate.c3p0.testConnectionOnCheckout">false</prop>
				 
					<prop key="hibernate.format_sql">false</prop>
					<!-- <prop key="hibernate.hbm2ddl.auto">create</prop> -->

			</props>
		</property>
	</bean>

<bean id="PROPAGATION_REQUIRES"
class="org.apache.camel.spring.spi.SpringTransactionPolicy">
    <property name="transactionManager" ref="transactionManager"/>
    <property name="propagationBehaviorName" value="PROPAGATION_REQUIRES"/>
</bean>



	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
		<property name="dataSource">
			<ref local="myDataSource" />
		</property>
		<property name="hibernateProperties">
			<ref bean="hibernateProperties" />
		</property>
		<property name="packagesToScan" value="br.com.sansoftware" />
	</bean>



	<bean id="transactionManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">

	</bean>


</beans>

Não tem mapeamento de bean no xml, ele e efetuado atraves destas linhas:

<property name="packagesToScan" value="br.com.sansoftware" />

E aqui o mapeamento do Dao

<context:component-scan base-package="br.com.sansoftware">
		<context:include-filter type="annotation"
			expression="org.springframework.stereotype.Repository" />
	</context:component-scan>

E anotando seus Daos assim:

@Repository
public class EmployeeDaoImpl extends GenericDAOImpl<Employee, Long> implements EmployeeDao{

	protected final static Log log = LogFactory.getLog(EmployeeDaoImpl.class);	




	protected Class<Employee> getEntityClass() {

        return Employee.class;

  }


	
}

Interface Dao generico

package br.com.sansoftware.dao;

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

import org.hibernate.FetchMode;
import org.hibernate.criterion.Criterion;

import br.com.sansoftware.model.Supplier;


public interface GenericDAO<T, ID extends Serializable>{

	T findById(ID id);
	T findByIdString(String id);
	
	
	void persist(T entity);

	void update(T entity);

	void delete(T entity);

	List<T> loadAll();
	

	String[] filds(Class<?> classe);
	

    
    void delete(ID id);


    List<T> findAllByProperty(String propertyName, Object value);
    
    List<T> findAllByPropertyLong(String propertyName, Object value);
    
	List list();

    
}

Implementacao Dao Generico

package br.com.sansoftware.dao;




@Repository
public abstract class GenericDAOImpl<T, ID extends Serializable> extends HibernateDaoSupport implements GenericDAO<T, ID>{

	private Class<T> persistentClass;
	
	protected abstract Class<T> getEntityClass();
	
    protected DetachedCriteria createDetachedCriteria() {

        return DetachedCriteria.forClass(getEntityClass());

  }
	
	
	public Class<T> getPersistentClass() {  
		return this.persistentClass;  
	}  
	

	@SuppressWarnings("unchecked")
	protected GenericDAOImpl(){

	}
	

	@Transactional(propagation = Propagation.REQUIRED)	
	public void delete(T entity) {
		// TODO Auto-generated method stub
		getHibernateTemplate().delete(entity);
	}

	
	public T findById(ID id) {
		// TODO Auto-generated method stub
		return getHibernateTemplate().get(getEntityClass(), id);
	}

	public T findByIdString(String id) {
		// TODO Auto-generated method stub
		return getHibernateTemplate().get(getEntityClass(), id);
	}
	
	
	@SuppressWarnings("unchecked")
	public List<T> loadAll() {
		
		return getHibernateTemplate().loadAll(getEntityClass());
	}


	public List list() {
		
		return getHibernateTemplate().loadAll(getEntityClass());
	}
	
	
	@Transactional(propagation = Propagation.REQUIRED)	
	public void persist(T entity) {
		
		getHibernateTemplate().persist(entity);

		
	}

	@Transactional(propagation = Propagation.REQUIRED)
	public void update(T entity) {
		getHibernateTemplate().merge(entity);
		
	}



	@Transactional(propagation = Propagation.REQUIRED)	
	public void delete(ID id) {

		T entity = findById(id);
		getHibernateTemplate().delete(entity);

	}









	

	

	public String[] filds(Class<?> classe) {
        try {
            Field fieldlist[] = classe.getDeclaredFields();
            String[] fields = new String[fieldlist.length-1];
            for (int i = 0; i <= fieldlist.length-1; i++) {
            	
                Field fld = fieldlist[i];
                Annotation[] annotations = fld.getAnnotations();  
                for (Annotation a : annotations) {  
               	 for (Method m : a.annotationType().getDeclaredMethods()) {  
               		 if(a.annotationType()!=javax.persistence.Transient.class){
                         fields[i]=fld.getName();
               			 }
               		 }
               	 }
            }
            return fields;
        }
        catch (Throwable e) {
            System.err.println(e);
        }
		return null;
    }	
    @SuppressWarnings("unchecked")
	public List<T> findAllByProperty(String propertyName, Object value) {

        DetachedCriteria criteria = createDetachedCriteria();

        criteria.add(Restrictions.like(propertyName, "%"+value+"%"));

        return getHibernateTemplate().findByCriteria(criteria);

  }


    
    
    public List<T> findAllByPropertyLong(String propertyName, Object value){

        DetachedCriteria criteria = createDetachedCriteria();

        criteria.add(Restrictions.eq(propertyName, value));

        return getHibernateTemplate().findByCriteria(criteria);

  }
	    
    

}

Interface EmployeDao

package br.com.sansoftware.dao;

import br.com.sansoftware.model.Employee;

public interface EmployeeDao extends GenericDAO<Employee, Long>{

}

Desculpem, fui clicar em editar e cliquei em citar, post duplicado

Ok! Obrigado pelo retorno. Vou tentar endenter tudo isso, rsrs!

Então não preciso mais do hibernate-cfg.xml ?

Seria só inserir as configurações de conexão como você postou?

  <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource">  
       <property name="driverClassName" value="com.mysql.jdbc.Driver" />  
       <property name="url" value="jdbc:mysql://localhost/oxrh" />  
       <property name="username" value="root" />  
       <property name="password" value="123456" />  
  </bean> 

Até aí, se eu estiver correto, entendi tudo.

Mas onde o Spring provê o que o HibernateUtil (Fabrica de conexão) retorna.

HibernateUtil.java


import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.classic.Session;

public class HibernateUtil {

		private static final SessionFactory sessionFactory;

		static {
			try {
				sessionFactory = new AnnotationConfiguration().configure()
						.buildSessionFactory();
			} catch (Throwable ex) {
				System.err.println("Não foi possivel criar a SessionFactory." + ex);
				throw new ExceptionInInitializerError(ex);
			}
		}

		public static Session getSession() {
			return sessionFactory.openSession();
		}

	}

Tenho mais dúvidas mas vamos por partes.

Obrigado!

A classe GenericDAOImpl extends HibernateDaoSupport, esta nossa classe herda uma classe do springframework, “HibernateDaoSupport”, pois esta classe é responsavel por disponibilizar uma sessão hibernate.