简体   繁体   中英

Why not @Autovired Session Factory? Java Hibernate Spring

I can not understand why the bean sessionFactory does not fill out. Why is this happening?

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: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/context http://www.springframework.org/schema/context/spring-context.xsd">

      <context:component-scan base-package="config"/>


    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

AppConfiguration in which the @Bean sessionFactory is declared:

@Configuration
@ComponentScan({"controllers","model","dao","service"})
public class AppConfiguration {

    @Bean
    LocalSessionFactoryBean sessionFactory(){
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setPackagesToScan(new String[]{"model"});
        sessionFactory.setDataSource(datasource());
        return sessionFactory;
    }

    @Bean
    JdbcTemplate jdbcTemplate(){return new JdbcTemplate(datasource());}

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

    @Bean
    HibernateTransactionManager transactionManager(@Autowired SessionFactory sessionFactory){
        HibernateTransactionManager manager= new HibernateTransactionManager();
        manager.setDataSource(datasource());
        manager.setSessionFactory(sessionFactory);
        return manager;
    }


}

A class that uses the bean sessionFactory. He is not @Autowired, as a result of which he has null:

@Service
public class AnswerDAOReal extends EntityDAO<Answer, Integer> {
    @Autowired SessionFactory sessionFactory;

    public AnswerDAOReal() {
        session=sessionFactory.openSession();
    }
}

abstract class EntityDAO -It is the parent of classes such as: AnswerDAOReal, UserDAOReal ... XxxDAOReal

abstract class EntityDAO<T, Id extends Serializable> {//Wnen: T- is type of Entity, iD- Type of ID// and DAOEntity- inheritor type of DAOEntity
     SessionFactory sessionFactory;
     Session session;

     EntityDAO(){}

    public void persist(T entity) {
        Transaction transaction = session.beginTransaction();
        session.persist(entity);
        session.flush();
        transaction.commit();
    }

    public void update(T entity) {
        Transaction transaction = session.beginTransaction();
        session.update(entity);
        session.flush();
        transaction.commit();
    }

    public T findById(Id id) {
        Transaction transaction = session.beginTransaction();
        T entity= (T) session.get(getGenericType(),id);
        session.flush();
        transaction.commit();
        return  entity;
    }

    public void delete(Id id) {
        Transaction transaction = session.beginTransaction();
        T entity = (T) findById(id);
        session.delete(entity);
        session.flush();
        transaction.commit();
    }

    public List<T> findAll() {
        Transaction transaction = session.beginTransaction();
        List<T> collection = session.createQuery("from "+getGenericType().getSimpleName()).list();
        session.flush();
        transaction.commit();
        return collection;
    }
    public void deleteAll() {
        Transaction transaction = session.beginTransaction();
        List<T> entityList = findAll();
        for (T entity : entityList) {
            session.delete(entity);
        }
        session.flush();
        transaction.commit();
    }


    public Class getGenericType(){
        Class type= (Class) ((ParameterizedType) getClass()
                .getGenericSuperclass()).getActualTypeArguments()[0];
        return type;
    }
}

Exception:

 org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'accountController': Unsatisfied dependency expressed through field 'userService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userService': Unsatisfied dependency expressed through field 'userDAOReal'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userDAOReal' defined in file [C:\JProjects\Hillel\SpringQuiz\out\artifacts\Servlet1_war_exploded\WEB-INF\classes\dao\UserDAOReal.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [dao.UserDAOReal]: Constructor threw exception; nested exception is java.lang.NullPointerException

    Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userService': Unsatisfied dependency expressed through field 'userDAOReal'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userDAOReal' defined in file [C:\JProjects\Hillel\SpringQuiz\out\artifacts\Servlet1_war_exploded\WEB-INF\classes\dao\UserDAOReal.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [dao.UserDAOReal]: Constructor threw exception; nested exception is java.lang.NullPointerException
    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userDAOReal' defined in file [C:\JProjects\Hillel\SpringQuiz\out\artifacts\Servlet1_war_exploded\WEB-INF\classes\dao\UserDAOReal.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [dao.UserDAOReal]: Constructor threw exception; nested exception is java.lang.NullPointerException
    Caused by: java.lang.NullPointerException
        at dao.UserDAOReal.<init>(UserDAOReal.java:16)

Your autowiring seems to be wrong. You inject the property on the field but you also have a constructor that opens the session.

Firstly, I would suggest to avoid injecting the property on the field itself and I would strongly recommend a constructor injection. Secondly where is the declaration of the session attribute in your AnswerDAOReal example?

With those in mind, I would suggest the following:

  • Use constructor based dependency injection. Doing it on the field is not the recommended way.
  • Have a method annotated with @PostConstruct which will be responsible for opening your session. Using this annotation will guarantee that the this is going to be called right after the initialization of the bean that finished taking place.

An example of this would be:

@Service
public class AnswerDAOReal extends EntityDAO<Answer, Integer> {

    private final SessionFactory sessionFactory;
    private Session session;

    @Autowired
    public AnswerDAOReal(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    @PostConstruct
    private void openSession() {
        this.session = sessionFactory.openSession();
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM