使用 Spring 依赖注入时,Hibernate SessionFactory 始终为 null
The Hibernate SessionFactory is always null when using Spring dependency injection
我在 CityDaoImpl
中的保存方法中收到 NullpointerException
。似乎 sessionFactory
没有自动装配,因为在调试时发现 sessionFactory 从未注入 CityDaoImpl
。我浏览了很多答案,但其中 none 可以解决我的问题。
这是我的 HibernateConfig.xml
文件:
<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>
这是 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);
}
}
现在我正在对我的 dao class 执行单元测试。但因 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);
}
}
控制台输出:
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
抛出的异常是:
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.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.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access[=15=]0(ParentRunner.java:53)
at org.junit.runners.ParentRunner.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)
您声明了 sessionFactory 依赖项:
<bean id="cityDao" class="com.testing.dao.CityDaoImpl">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
然后你还有:
@Autowired
private SessionFactory sessionFactory;
尝试删除 @Autowired
注释,因为如果您使用 XML 配置,它是多余的。
仅仅因为你添加了sessionFactory,并不意味着Spring也可以自动管理Hibernate Sessions。
您还需要添加:
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
以及:
<tx:annotation-driven/>
现在您还需要将 @Transactional
添加到您的 save 例程中:
@Transactional
public void save(City city){
this.sessionFactory.getCurrentSession().save(city);
}
我在 CityDaoImpl
中的保存方法中收到 NullpointerException
。似乎 sessionFactory
没有自动装配,因为在调试时发现 sessionFactory 从未注入 CityDaoImpl
。我浏览了很多答案,但其中 none 可以解决我的问题。
这是我的 HibernateConfig.xml
文件:
<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>
这是 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);
}
}
现在我正在对我的 dao class 执行单元测试。但因 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);
}
}
控制台输出:
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
抛出的异常是:
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.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.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access[=15=]0(ParentRunner.java:53)
at org.junit.runners.ParentRunner.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)
您声明了 sessionFactory 依赖项:
<bean id="cityDao" class="com.testing.dao.CityDaoImpl">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
然后你还有:
@Autowired
private SessionFactory sessionFactory;
尝试删除 @Autowired
注释,因为如果您使用 XML 配置,它是多余的。
仅仅因为你添加了sessionFactory,并不意味着Spring也可以自动管理Hibernate Sessions。
您还需要添加:
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
以及:
<tx:annotation-driven/>
现在您还需要将 @Transactional
添加到您的 save 例程中:
@Transactional
public void save(City city){
this.sessionFactory.getCurrentSession().save(city);
}