2013-05-07 1 views
6

JPA를 사용하여 내 DAO 클래스에 대한 테스트를 작성하고, JPA 공급자로서 Hibernate를 사용하며, Spring 3.2를 테스트했습니다. 엔티티 관리자를 올바르게 삽입 할 수 없습니다. 액세스하려고하면 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.... 
} 

시험의 클래스는 다음과 같습니다

<?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> 

나는했습니다 :

@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은 다음과 같다 성공하지 못한 채 몇 가지 접근 방식을 시도했으며, 심지어 다른 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

스택 추적을 게시하십시오. –

+0

'persistence.xml'을 보여주세요 – falsarella

+0

web.xml에'root-context.xml'과'ContextLoaderListener'를 설정 했습니까? http://stackoverflow.com/q/9856721/1064325와 http : /image/gif/paws/13532565/1064325 – falsarella

답변

7

나는 마침내 문제를 해결하기 위해 관리했습니다. 이 방법으로 인스턴스화

@Autowired 
private GenericDAO genericDao; 

하지만 DescriptorBO 불리는 이런 클래스, : GenericDAO를 인스턴스화하기 위해 나는를 autowire 주석,이 방법을 사용

DescriptorBO descrBO = new DescriptorBO(...); 

을 따라서의 통제에서 완전히 탈출 봄 컨테이너입니다. 이것을 변경 :

@Autowired 
private DescriptorBO descrBO; 

와 루트의 context.xml에 적절한 bean 정의를 추가 :

<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가 제대로 삽입되었습니다.

Lesson learn : Spring이 EntityManager (또는 다른 삽입 된 객체)를 삽입하지 않으면 객체 위의 모든 객체 계층 구조가 Spring에 의해 관리되는지 확인합니다. 이자형. 직접 또는 Autowired 어노테이션을 사용하여 애플리케이션 컨텍스트에서 Bean으로부터 인스턴스화한다. 새 연산자를 사용하여 해당 객체를 인스턴스화하지 않았는지 확인하십시오 !!

관련 문제