2015-02-23 78 views
1

我試圖在Hibernate實現中使用Spring上的JPA。我想用Spring至少註釋,自動裝配&交易管理。儘管如此,我仍然遇到以下問題。任何幫助將不勝感激!DAO測試 - Spring + JPA自動裝配問題

我GenericDAO實現:

package gov.cms.cicdim.cpc.data.dao; 

import java.io.Serializable; 
import java.lang.reflect.ParameterizedType; 
import java.util.List; 

import javax.persistence.EntityManager; 
import javax.persistence.PersistenceContext; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Repository; 
import org.springframework.transaction.annotation.Transactional; 

@Repository 
@Transactional 
public abstract class GenericDAO<K, T extends Serializable> 
    implements IGenericDAO<K, T> 
{ 
    protected Class<T> entityClass; 

    @PersistenceContext 
    protected EntityManager entityManager; 

    @Autowired 
    public GenericDAO() 
    { 
     ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass(); 
     this.entityClass = (Class<T>) genericSuperclass.getActualTypeArguments()[1]; 
    } 

    public T findOne(K id) 
    { 
     if(isEmpty(id)) { return null; } 

     return this.entityManager.find(entityClass, id); 
    } 

    public List<T> findAll() 
    { 
     return this.entityManager.createQuery("from " + entityClass.getName()).getResultList(); 
    } 

    public void create(T entity) 
    { 
     this.entityManager.persist(entity); 
     this.entityManager.close(); 
    } 

    public void update(T entity) 
    { 
     this.entityManager.merge(entity); 
     this.entityManager.flush(); 
     this.entityManager.close(); 
    } 

    public void delete(T entity) 
    { 
     this.entityManager.remove(entity); 
     this.entityManager.close(); 
    } 

    public void deleteById(K id) 
    { 
     T entity = findOne(id); 
     delete(entity); 
    } 

    /** 
    * Utility method to determine if objects is empty or all elements are null for optimization purposes. 
    * 
    * @param objects the objects 
    * @return true, if is empty 
    */ 
    protected boolean isEmpty(Object...objects) { 
     if(objects.length == 0) { 
      return true; 
     } 

     for(Object o : objects) { 
      if(o != null) { 
       return false; 
      } 
     } 

     return true; 
    } 

} 

的DAO本身:

package gov.cms.cicdim.cpc.data.dao; 

import gov.cms.cicdim.cpc.data.model.Practice; 

import org.apache.commons.logging.Log; 
import org.apache.commons.logging.LogFactory; 
import org.springframework.stereotype.Repository; 
import org.springframework.transaction.annotation.Transactional; 

/** 
* The Class PracticeDAO for CRUD operations for Practice data. 
*/ 
@Repository 
@Transactional 
public class PracticeDAO extends GenericDAO<String, Practice> 
    implements IPracticeDAO 
{ 
    public PracticeDAO(){} 

    /** The Constant logger. */ 
    private static final Log logger = LogFactory.getLog(PracticeDAO.class); 

    @Override 
    public Practice findPersonByFullName(String full_Name) { 
     // TODO Auto-generated method stub 
     return null; 
    } 
} 

測試DAO:包括空間(在SRC/test/java下)

package gov.cms.cicdim.cpc.data.dao; 

import gov.cms.cicdim.cpc.data.model.Practice; 

import java.util.List; 

import junit.framework.AssertionFailedError; 
import junit.framework.TestCase; 

import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.test.context.ContextConfiguration; 
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 
import org.springframework.transaction.annotation.Transactional; 

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration("/applicationContext.xml") 
@Transactional 
public class PracticeDAOTest extends TestCase 
{ 
    @Autowired 
    public PracticeDAO testPracticeDAO; 

    public void setPracticeDAO(PracticeDAO testPracticeDAO) { 
     this.testPracticeDAO = testPracticeDAO; 
    } 

    boolean doit = true; 

    @Test 
    public void testCreatePracticeDAO(){ 
     if(doit){ 
     Practice practice = generatePractice(); 
     String porg = practice.getParentOrgName(); 
     String pid = practice.getPracticeId(); 

     //create 
     try { 
       testPracticeDAO.create(practice); 
       String pratice_id = testPracticeDAO.findOne(pid).getPracticeId(); 
       assertEquals("Practice id check", pid, pratice_id); 

      } catch (Exception e) { 
       e.printStackTrace(); 
       throw new AssertionFailedError("Practice Save failed"); 
      } 
     // test update 
     try{ 
       practice.setSiteName("baltimore"); 
       if(testPracticeDAO.findOne(pid) !=null){ 
       testPracticeDAO.update(practice); 
       String site_Name = testPracticeDAO.findOne(pid).getSiteName(); 
       assertEquals("Practice Site check", "baltimore", site_Name); 
       } 

      } catch(Exception e){ 
       e.printStackTrace(); 
       throw new AssertionFailedError("Practice update failed!"); 
      } 
} 
並非所有測試

Persistence.xml

<?xml version="1.0" encoding="UTF-8"?> 
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0"> 

    <persistence-unit name="ApplicationEntityManager"> 
     <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> 
     <properties> 
      <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" /> 
      <property name="javax.persistence.jdbc.url" 
       value="xxxxxxxxx"/> 
      <property name="javax.persistence.jdbc.user" value="xxxxxxx"/> 
      <property name="javax.persistence.jdbc.password" value="xxxxxxx"/> 
     </properties> 

    </persistence-unit> 

</persistence> 

的applicationContext.xml(在SRC /主/資源)

<?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:context="http://www.springframework.org/schema/context" 
     xmlns:jee="http://www.springframework.org/schema/jee" 
     xmlns:lang="http://www.springframework.org/schema/lang" 
     xmlns:p="http://www.springframework.org/schema/p" 
     xmlns:tx="http://www.springframework.org/schema/tx" 
     xmlns:util="http://www.springframework.org/schema/util" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans 
          http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
          http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd 
          http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd 
          http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd 
          http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd 
          http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd 
          http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> 

    <context:annotation-config/> 
    <tx:annotation-driven /> 

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
     <property name="persistenceXmlLocation" value="classpath:persistence.xml" /> 
     <property name="persistenceUnitName" value="ApplicationEntityManager" /> 
     <property name="dataSource" ref="dataSource" /> 
    </bean> 

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

    <tx:annotation-driven transaction-manager="transactionManager" /> 

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
     <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" /> 
     <property name="url" value="xxxxxxx" /> 
     <property name="username" value="xxxxxxx" /> 
     <property name="password" value="xxxxxxx" /> 
    </bean> 

    <context:component-scan base-package="gov.cms.cicdim.cpc.data.dao"/> 

    <!-- Add new DAOs here --> 
    <bean id="practiceDAO" class="gov.cms.cicdim.cpc.data.dao.PracticeDAO"/> 
    <bean id="testPracticeDAO" class="gov.cms.cicdim.cpc.data.dao.PracticeDAO"/> 

    <!-- Add new Managers here --> 
</beans> 

而且堆棧跟蹤:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'gov.cms.cicdim.cpc.data.dao.PracticeDAOTest': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: public gov.cms.cicdim.cpc.data.dao.PracticeDAO gov.cms.cicdim.cpc.data.dao.PracticeDAOTest.testPracticeDAO; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [gov.cms.cicdim.cpc.data.dao.PracticeDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:287) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1106) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:374) 
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:110) 
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75) 
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:290) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) 
    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:236) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) 
    at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252) 
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141) 
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189) 
    at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165) 
    at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85) 
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115) 
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75) 
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: public gov.cms.cicdim.cpc.data.dao.PracticeDAO gov.cms.cicdim.cpc.data.dao.PracticeDAOTest.testPracticeDAO; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [gov.cms.cicdim.cpc.data.dao.PracticeDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:506) 
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:284) 
    ... 32 more 
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [gov.cms.cicdim.cpc.data.dao.PracticeDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:924) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:793) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:707) 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:478) 
    ... 34 more 


Results : 

Tests in error: 
    testCreatePracticeDAO(gov.cms.cicdim.cpc.data.dao.PracticeDAOTest): Error creating bean with name 'gov.cms.cicdim.cpc.data.dao.PracticeDAOTest': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: public gov.cms.cicdim.cpc.data.dao.PracticeDAO gov.cms.cicdim.cpc.data.dao.PracticeDAOTest.testPracticeDAO; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [gov.cms.cicdim.cpc.data.dao.PracticeDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 
    testFindAllPractices(gov.cms.cicdim.cpc.data.dao.PracticeDAOTest): Error creating bean with name 'gov.cms.cicdim.cpc.data.dao.PracticeDAOTest': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: public gov.cms.cicdim.cpc.data.dao.PracticeDAO gov.cms.cicdim.cpc.data.dao.PracticeDAOTest.testPracticeDAO; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [gov.cms.cicdim.cpc.data.dao.PracticeDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 
+1

名稱爲'applicationContext.xml'或'application-context.xml'?我希望這不是問題。 – 2015-02-23 18:03:42

+0

順便說一句,你使用cglib代理或JDK動態代理? – 2015-02-23 18:04:01

+0

這是applicationContext.xml,對不起,我在我的文章中更正了標題。 我沒有使用任何類型的代理。在我找到的例子中,我還沒有看到任何使用或提及它。那是否會給我帶來豆類問題或影響後來的交易? – 2015-02-23 18:30:02

回答

2

declarative transactions are implemented using proxies。默認情況下,如果代理類實現了一個接口,它將使用此處使用的JDK Dynamic代理,因爲PracticeDAO實現了IPracticeDAO

由spring創建的代理實現相同的接口IPracticeDAO,並且該代理的bean已註冊。由於您在PracticeDAO上進行自動裝配,代理bean無法自動裝配,因爲同級類的實例不兼容。這就是爲什麼你應該幾乎總是在接口類型上使用@Autowired註釋,而不是實現類類型。

在你的情況,嘗試自動裝配IPracticeDAO而不是PracticeDAO,它會正常工作。

+0

謝謝!這似乎奏效了。儘管現在看來,測試實體似乎沒有被持久化到數據庫,所以我的Spring事務配置有誤。 – 2015-02-23 19:08:32

+0

爲什麼你的上下文文件中有2個標籤。刪除第一個。 – 2015-02-23 19:12:26

+0

我在這裏看到了另一個例子。它坦率地困惑我以及... 刪除它,我仍然沒有看到實體被持續。 – 2015-02-23 19:14:23