The Hibernate SessionFactory is always null when u

2019-04-11 08:42发布

问题:

I am getting a NullpointerException on my save method in CityDaoImpl. Seems that sessionFactory is not autowired since on debugging it was revealed that sessionFactory is never injected in CityDaoImpl. I have look through many answers but none of them could solve my problem. This is my HibernateConfig.xml file:

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

    <context:component-scan 
        base-package="com.testing" />
    <context:annotation-config></context:annotation-config>
    <tx:annotation-driven/>
    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/sybrium" />
        <property name="username" value="root" />
        <property name="password" value="" />
    </bean>

    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="annotatedClasses">
            <list>
                <value>com.testing.bean.City</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">create</prop>
                <prop key="debug">true</prop>
            </props>
        </property>
    </bean>
    <bean id="cityDao" class="com.testing.dao.CityDaoImpl">
        <property name="sessionFactory" ref="sessionFactory"></property>
    </bean>
</beans>

And this is CityDaoImpl.java :

public class CityDaoImpl implements CityDao{

    @Autowired
    private SessionFactory sessionFactory;

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

    public void save(City city){
        this.sessionFactory.getCurrentSession().save(city);
    }

}

Now I am executing a unit test on my dao class. But is failing with a NPE.

public class TestCityDao {

    ApplicationContext ctx;

    @Before
    public void setup(){
        ctx = new ClassPathXmlApplicationContext("HibernateConfig.xml");
    }

    @Test
    public void test(){
        City city = new City();
        city.setName("Karachi");
        city.setCountry("Pakistan");
        CityDao dao = (CityDao) ctx.getBean("cityDao");
        dao.save(city);
    }
}

Console output:

Jan 15, 2015 11:54:53 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@b34bf3: display name [org.springframework.context.support.ClassPathXmlApplicationContext@b34bf3]; startup date [Thu Jan 15 23:54:53 PKT 2015]; root of context hierarchy
Jan 15, 2015 11:54:53 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [HibernateConfig.xml]
Jan 15, 2015 11:54:53 PM org.springframework.context.support.AbstractApplicationContext obtainFreshBeanFactory
INFO: Bean factory for application context [org.springframework.context.support.ClassPathXmlApplicationContext@b34bf3]: org.springframework.beans.factory.support.DefaultListableBeanFactory@1b8202e
Jan 15, 2015 11:54:53 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1b8202e: defining beans [dataSource,sessionFactory,cityDao]; root of factory hierarchy
Jan 15, 2015 11:54:53 PM org.springframework.jdbc.datasource.DriverManagerDataSource setDriverClassName
INFO: Loaded JDBC driver: com.mysql.jdbc.Driver
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Jan 15, 2015 11:54:53 PM org.springframework.orm.hibernate3.LocalSessionFactoryBean buildSessionFactory
INFO: Building new Hibernate SessionFactory

And the exception thrown is :

java.lang.NullPointerException
    at com.testing.dao.CityDaoImpl.save(CityDaoImpl.java:19)
    at com.testing.TestCityDao.test(TestCityDao.java:26)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

回答1:

You declare the sessionFactory dependency:

<bean id="cityDao" class="com.testing.dao.CityDaoImpl">
    <property name="sessionFactory" ref="sessionFactory"></property>
</bean>

and then you also have:

@Autowired
private SessionFactory sessionFactory;

Try removing the @Autowired annotation, since it's redundant if you use XML configuration.

Just because you added the sessionFactory, it doesn't mean Spring can automatically manage Hibernate Sessions too.

You also need to add:

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

as well as:

<tx:annotation-driven/>

Now you need to also add @Transactional to your save routine:

@Transactional
public void save(City city){
    this.sessionFactory.getCurrentSession().save(city);
}