Spring Annotations -java.lang.IllegalArgumentException: 'sessionFactory' or 'hibernateTemplate' is required in spring+hibernate

StackOverflow https://stackoverflow.com/questions/18850090

Domanda

I am getting the error as in the question. My Dao Implement Class is as follows :

package com.argus.intenew;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean;

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class UserDaoImpl extends HibernateDaoSupport implements UserDao {

@Autowired
AnnotationSessionFactoryBean sessionFactory;
    public UserDaoImpl() {
    }

    public AnnotationSessionFactoryBean getCurrentSessionFactory() {
        return sessionFactory;
    }

    public void  setCurrentSessionFactory(AnnotationSessionFactoryBean sessionfactory) {
        this.sessionFactory = sessionfactory;
    }

    @Override
    public void addUser(UserMap userMap) {
        System.out.println("33333333333333333333");
        getHibernateTemplate().save(userMap);
    }

    @Override
    public List<User> findAllUser() {
        return getHibernateTemplate().find("from User");
    }

    @Override
    public void deleteUser(UserMap user) {
        getHibernateTemplate().delete(user);
    }

    @Override
    public void updateUser(UserMap user) {
        getHibernateTemplate().update(user);
    }
}

And my configuration class is as follows:

package com.argus.intenew;

import java.util.Properties;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate3.HibernateTransactionManager;
import org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean;

@Configuration
@ComponentScan(basePackages = {"com.argus.intenew"})
public class Webconfig  {
    private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "org.hibernate.dialect.MySQLDialect ";
    private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "true";

    @Bean
    public DataSource dataSource() {
        System.out.println("----------InDATAsource------------");
        DriverManagerDataSource dataSource = new DriverManagerDataSource();

        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/MyUser");
        dataSource.setUsername("root");
        dataSource.setPassword("XXX");
        System.out.println("----------OutofDATAsource------------");
        return dataSource;
    }

    @Bean
    public AnnotationSessionFactoryBean sessionFactory() {
        System.out.println("----------InsessionFactory------------");
        AnnotationSessionFactoryBean sessionFactory = new AnnotationSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        String[] pckage={"com.argus.intenew"};
        sessionFactory.setPackagesToScan(pckage);
        sessionFactory.setHibernateProperties(hibProperties());
        System.out.println("----------Outof session------------");
        return sessionFactory;
    }

    private Properties hibProperties() {
        System.out.println("----------InhipProp------------");
        Properties properties = new Properties();
        properties.put(PROPERTY_NAME_HIBERNATE_DIALECT, "org.hibernate.dialect.MySQLDialect ");
        properties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, "true");
        System.out.println("----------outofhip------------");
        return properties;
    }

    @Bean
    public HibernateTransactionManager transactionManager() {
        HibernateTransactionManager transactionManager = new HibernateTransactionManager(sessionFactory().getObject());

        return transactionManager;
   }

   @Bean
   public UserBoImpl userBo() {
       System.out.println("----------InUserBo------------");
       UserBoImpl userBo= new UserBoImpl();
       userBo.setUserDao(userDao());
       System.out.println("----------OutofUserbo------------");
       return userBo;
   }

   @Bean
   public UserDaoImpl userDao() {
       System.out.println("----------InUserDao------------");
       UserDaoImpl userDao=new UserDaoImpl();
       userDao.setCurrentSessionFactory(sessionFactory());
       System.out.println("----------OutofUserDao------------");
       return userDao;
   }
}

Anyone please help and tell me what is the correct way to do this with annotations. Here I am not using any xml file.

È stato utile?

Soluzione

Your DAO implementation is not leveraging its superclass correctly.

  1. You're injecting a Spring FactoryBean<SessionFactory> when it really needs a Hibernate SessionFactory.
  2. It's not actually using the injected dependency.
  3. You're attempting to use HibernateDaoSupport#getHibernateTemplate() without giving it a reference to a SessionFactory or a HibernateTemplate.

Note that HibernateDaoSupport will create its own HibernateTemplate as long as you give it a SessionFactory.

I suggest you make the following changes:

  1. Remove AnnotationSessionFactoryBean sessionFactory from UserDaoImpl
  2. Fix configuration of UserDaoImpl by leveraging its inherited setSessionFactory(SessionFactory) method

So you actually end up with this DAO code:

public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
    @Override
    public void addUser(UserMap userMap) {
        getHibernateTemplate().save(userMap);
    }
    @Override
    public List<User> findAllUser() {
        return getHibernateTemplate().find("from User");
    }
    @Override
    public void deleteUser(UserMap user) {
        getHibernateTemplate().delete(user);
    }
    @Override
    public void updateUser(UserMap user) {
        getHibernateTemplate().update(user);
    }
}

And this configuration code:

@Configuration
@ComponentScan(basePackages = {"com.argus.intenew"})  
public class Webconfig  {
    //snip...
    @Bean
    public UserDaoImpl userDao() {
        UserDaoImpl userDao=new UserDaoImpl();
        userDao.setSessionFactory(sessionFactory().getObject());
        return userDao;
    }
}

Note that it's ok to return the FactoryBean from the sessionFactory() configuration method since Spring will detect and utilize its lifecycle methods (via InitializingBean and DisposableBean), but you need to accommodate by calling the FactoryBean method getObject() yourself.

Altri suggerimenti

Don't user HibernateDaoSupport and/or HibernateTemplate. With the release of Hibernate 3.0.1 that support should be regarded deprecated. As mentioned in the reference guide implement the dao/repository based on plain hibernate.

Your dao will look like

@Repository
public class UserDaoImpl implements UserDao {

    @Autowired
    private SessionFactory sessionFactory;

    @Override
    public void addUser(UserMap userMap) {
        System.out.println("33333333333333333333");
        sessionFactory.getCurrentSession().save(userMap);
    }

    @Override
    public List<User> findAllUser() {
        return sessionFactory.getCurrentSession().createQuery("from User").list();
    }

    @Override
    public void deleteUser(UserMap user) {
        sessionFactory.getCurrentSession().delete(user);
    }

    @Override
    public void updateUser(UserMap user) {
        sessionFactory.getCurrentSession().update(user);
    }
}

As you are already using the @ComponentScan annotation (and I assume yo have your BO annotated with @Service and properly annotated with @Autowired there is no need to explictly configure you dao and service in the configuration.

@Configuration  
@ComponentScan(basePackages = {"com.argus.intenew"})  
public class Webconfig  {  

    private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "org.hibernate.dialect.MySQLDialect ";  
    private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "true";  

    @Bean  
    public DataSource dataSource() {  
        DriverManagerDataSource dataSource = new DriverManagerDataSource();  
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");  
        dataSource.setUrl("jdbc:mysql://localhost:3306/MyUser");  
        dataSource.setUsername("root");  
        dataSource.setPassword("XXX");  
        return dataSource;  
    }  

    @Bean  
    public AnnotationSessionFactoryBean sessionFactory() { 
        AnnotationSessionFactoryBean sessionFactory = new AnnotationSessionFactoryBean();  
        sessionFactory.setDataSource(dataSource());
        String[] pckage={"com.argus.intenew"};
        sessionFactory.setPackagesToScan(pckage);  
        sessionFactory.setHibernateProperties(hibProperties());
        return sessionFactory; 
    }  

    private Properties hibProperties() { 
        Properties properties = new Properties();  
        properties.put(PROPERTY_NAME_HIBERNATE_DIALECT, "org.hibernate.dialect.MySQLDialect ");  
        properties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, "true"); 
        return properties;    
    } 

    @Bean  
    public HibernateTransactionManager transactionManager() {  
        return new HibernateTransactionManager(sessionFactory().getObject());  
    }  
}

A note regarding DriverManagerDataSource this is nice for testing but please don't use this in production (unless you want an application that doesn't perform). Use a proper JDBC Connection Pool instead.

A final note, if you really want productivity drop hibernate, switch to JPA and use Spring Data JPA for your repositories. Saves you writing a lot of implementation code. (And the best maintainable and testable code is code not written :) ).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top