2013-05-07 58 views
6

我使用JPA和Hibernate作爲JPA提供者和Spring 3.2爲我的DAO類編寫測試。我無法正確注入實體管理器,當試圖訪問實體管理器時,我得到一個NullPointerException。我GenericDAO實施看起來是這樣的:Spring未能注入實體管理器工廠

@Repository 
public class GenericDAOImpl implements GenericDAO { 

    @PersistenceContext(unitName="unitname") 
    private EntityManager entityManager; 

    public EntityManager getEntityManager() { 
     return entityManager; 
    } 


    public void setEntityManager(EntityManager entityManager) { 
     this.entityManager = entityManager; 
    } 

    // NullPointerException when calling this, entityManager is null 
    public Query createNamedQuery(String name) { 
     return entityManager.createNamedQuery(name); 
    }   

    // many other methods.... 
} 

類的測試看起來是這樣的:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { "/com/main/resources/root-context.xml", "/com/main/resources/servlet-context.xml"}) 
public class TestModel { 

    @Before 
    public void setUp() throws Exception{ 
     ... 
    } 

    @Test 
    public void test(){ 
     ... 
    } 
} 

我的根的context.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:beans="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx" 
    xsi:schemaLocation=" 
     http://www.springframework.org/schema/aop 
     http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 
     http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
     http://www.springframework.org/schema/context 
     http://www.springframework.org/schema/context/spring-context-3.0.xsd 
     http://www.springframework.org/schema/mvc 
     http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd   
     http://www.springframework.org/schema/tx 
     http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 
     " 
> 

    <!-- Root Context: defines shared resources visible to all other web components --> 

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
     <property name="driverClassName" value="com.mysql.jdbc.Driver" /> 
     <property name="username" value="root" /> 
     <property name="password" value="root" /> 
    </bean> 

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
     <property name="persistenceUnitName" value="unitname" /> 
     <property name="dataSource" ref="dataSource" /> 
     <property name="packagesToScan" value="com.main" /> 
     <property name="jpaVendorAdapter"> 
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
       <property name="showSql" value="true" /> 
       <property name="generateDdl" value="false" /> 
       <property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect" /> 
      </bean> 
     </property> 
    </bean> 

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
     <property name="entityManagerFactory" ref="entityManagerFactory" /> 
    </bean> 

    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /> 



    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="false" /> 
    <context:component-scan base-package="com.main" /> 
    <context:annotation-config /> 

</beans> 

我已經嘗試了幾種沒有成功的方法,甚至像其他SO問題中所建議的那樣添加了PersistenceAnnotationBeanPostProcessor。所有其他的東西似乎工作正常:Hibernate創建數據庫表,上下文被加載等。我做錯了什麼?

編輯:堆棧跟蹤如下:

java.lang.NullPointerException 
    at com.main.model.dao.JPAImpl.GenericDAOImpl.createNamedQuery(GenericDAOImpl.java:119) 
    at com.main.model.bo.DescriptorBO.persist(DescriptorBO.java:52) 
    at com.main.webmodule.JSONSerializer.deserialize(JSONSerializer.java:149) 
    at com.main.tests.TestModel.test(TestModel.java:86) 
    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:601) 
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42) 
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) 
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74) 
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83) 
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:300) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) 
    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:467) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 

這裏是persistence.xml中:

<?xml version="1.0" encoding="UTF-8"?><persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> 
    <persistence-unit name="unitname" transaction-type="RESOURCE_LOCAL"> 
     <provider>org.hibernate.ejb.HibernatePersistence</provider> 
     <mapping-file>META-INF/jpql/NamedQueries.xml</mapping-file> 


     <class>com.main.model.Account</class> 
     <class>com.main.model.Action</class> 
     <class>com.main.model.Device</class> 
     <class>com.main.model.DeviceDescriptor</class> 
     <class>com.main.model.Event</class> 
     <class>com.main.model.File</class> 
     <class>com.main.model.Rule</class> 
     <class>com.main.model.StateVar</class> 
     <class>com.main.model.Argument</class> 
     <exclude-unlisted-classes>false</exclude-unlisted-classes> 


     <properties> 

      <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/> 
      <property name="hibernate.connection.username" value="root"/> 
      <property name="hibernate.connection.password" value="root"/> 
      <property name="hibernate.connection.provider_class" value="org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider" /> 
      <property name="hibernate.connection.autocommit" value="true"/> 
      <property name="hibernate.connection.release_mode" value="auto"/> 
      <property name="hibernate.connection.url" value="jdbc:mysql://127.0.0.1:3306/testweb"/> 
      <property name="hibernate.hbm2ddl.auto" value="create"/> 

      <property name="hibernate.c3p0.min_size" value="1" /> 
      <property name="hibernate.c3p0.max_size" value="10" /> 
      <property name="hibernate.c3p0.acquire_increment" value="1" /> 
      <property name="hibernate.c3p0.idle_test_period" value="300" /> 
      <property name="hibernate.c3p0.max_statements" value="0" /> 
      <property name="hibernate.c3p0.timeout" value="100" /> 

      <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/> 

     </properties> 




    </persistence-unit> 
</persistence> 
+0

發佈你的堆棧跟蹤。 – 2013-05-07 10:23:42

+0

向我們展示您的'persistence.xml' – falsarella 2013-05-07 11:58:11

+0

您的web.xml中是否配置了'root-context.xml'和'ContextLoaderListener'?請參閱http://stackoverflow.com/q/9856721/1064325和http:///stackoverflow.com/q/1132565/1064325 – falsarella 2013-05-07 12:33:22

回答

7

我終於設法解決這個問題。爲了實例GenericDAO我使用的自動裝配Autowired註解,這樣說:

@Autowired 
private GenericDAO genericDao; 

但課堂,出現這種情況,稱爲DescriptorBO,被實例化這種方式:

DescriptorBO descrBO = new DescriptorBO(...); 

,因此從的控制完全逃脫春天的容器。此更改爲:

@Autowired 
private DescriptorBO descrBO; 

,並添加相應的bean定義到根的context.xml:

<bean name="descriptorBO" class="com.main.model.bo.DescriptorBO"> 
    <property name="genericDao" ref="genericDao" /> 
</bean> 

<bean name="genericDao" class="com.main.model.dao.JPAImpl.GenericDAOImpl" /> 

解決了這個問題。現在EntityManager被正確注入。

獲得的經驗教訓:如果Spring未注入EntityManager(或任何其他注入對象),請檢查對象上方的所有對象層次結構是否都由Spring管理。即從應用程序上下文中的bean實例化,直接或使用Autowired註釋。檢查你是否不使用新的操作符來實例化這些對象!

相關問題