2013-02-28 43 views
1

我試圖自動裝載由存儲庫工廠bean創建的存儲庫。我需要用自定義代碼覆蓋某些存儲庫的save()方法。我在Spring Data's introduction之後跟着工廠bean的例子。無法自動裝載由JpaRepositoryFactoryBean創建的存儲庫

但無論我做什麼,我得到NoSuchBeanDefinitionException

另一方面,'僅接口存儲庫'被創建並注入得很好。

很可能我在某個地方犯了一個愚蠢的錯誤。因爲這應該是Spring Data 101.

有人可以給我一些線索,我還可以嘗試使它工作嗎?

的規格

休眠4.1.9.Final

春3.2.1.RELEASE

春數據1.3.0.RELEASE

JDK 1.6.0_39。

的Arch Linux的x64

的倉庫工廠

如果實體類型吧,我返回不同的存儲庫。否則,將應用默認行爲。

public class RepositoryFactoryBean<R extends JpaRepository<T, I>, T, I extends Serializable> extends JpaRepositoryFactoryBean<R, T, I> { 

    protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) { 
    return new MyRepositoryFactory(entityManager); 
    } 

    private static class MyRepositoryFactory<T, I extends Serializable> extends JpaRepositoryFactory { 

    private EntityManager entityManager; 

    public MyRepositoryFactory(final EntityManager entityManager) { 
     super(entityManager); 
     this.entityManager = entityManager; 
    } 

    protected Object getTargetRepository(final RepositoryMetadata metadata) { 
     if (metadata.getDomainType().equals(Bar.class)) { 
     return new BarDaoImpl((Class<Bar>) metadata.getDomainType(), entityManager); 
     } 
     return super.getTargetRepository(metadata); 
    } 

    protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) { 
     if (metadata.getDomainType().equals(Bar.class)) { 
     return BarDao.class; 
     } 
     return super.getRepositoryBaseClass(metadata); 
    } 
    } 
} 

存儲庫類和接口

package com.bar.persistence.dao; 

@NoRepositoryBean 
public interface BarDao extends JpaRepository<Bar, Long> { 
    // no methods - because I want to override save() 
} 



package com.bar.persistence.dao; 

public class BarDaoImpl extends SimpleJpaRepository<Bar, Long> implements BarDao { 

    public BarDaoImpl(final Class<Bar> domainClass, final EntityManager em) { 
    super(domainClass, em); 
    } 

    @Override 
    public <S extends Bar> S save(final S entity) { 
    // some code to perform before actually saving the entity 
    entity.setName("intercepted save !"); 

    // do the save 
    return super.save(entity); 
    } 
} 

測試注射庫

,因爲它無法找到類型BarDao的豆注入測試失敗。

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration("/persistence-beans.xml") 
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) 
@TransactionConfiguration 
public class SpringDataLearningTest { 

    @Autowired 
    private BarDao barDao; 

    @Transactional 
    @Test 
    public void testModifiedSave() throws Exception { 
    final Bar original = createRandomBar(); 
    final Bar saved = barDao.save(original); 
    assertNotNull("No id was assigned to the saved entity", saved.getId()); 
    assertEquals("intercepted save !", saved.getName()); 
    } 

    private static Bar createRandomBar() {...} 
} 

Spring配置

<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:context="http://www.springframework.org/schema/context" 
     xmlns:tx="http://www.springframework.org/schema/tx" 
     xmlns:task="http://www.springframework.org/schema/task" 
     xmlns:util="http://www.springframework.org/schema/util" xmlns:aop="http://www.springframework.org/schema/aop" 
     xmlns:data="http://www.springframework.org/schema/data/jpa" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd 
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd 
      http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd 
      http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd 
      http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd 
      http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"> 

    <!-- Tell Spring Data where to find the interfaces --> 
    <data:repositories base-package="com.bar.persistence.dao" factory-class="com.bar.persistence.dao.RepositoryFactoryBean"/> 

    <!-- include the definitions of the 'upstream' modules --> 
    <import resource="common-beans.xml"/> 
    <import resource="io-beans.xml"/> 

    <!-- The exception translator service--> 
    <bean class="org.springframework.orm.hibernate4.HibernateExceptionTranslator"/> 

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

    <!-- Use the classic Spring JPA Transaction Manager --> 
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="entityManagerFactory" ref="entityManagerFactory"/> 
    </bean> 

    <!-- Describes how to connect to the database --> 
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> 
    <property name="user" value="${database.user.name}"/> 
    <property name="password" value="${database.user.password}"/> 
    <property name="driverClass" value="${database.driver}"/> 
    <property name="jdbcUrl" value="${database.url}"/> 
    <property name="initialPoolSize" value="1"/> 
    <property name="maxPoolSize" value="${database.max.pool.size}"/> 
    <property name="minPoolSize" value="${database.min.pool.size}"/> 
    <property name="acquireIncrement" value="1"/> 
    <property name="acquireRetryAttempts" value="3"/> 
    <property name="checkoutTimeout" value="10000"/> 
    </bean> 

    <!-- Describes how to create hibernate sessions --> 
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="persistenceProviderClass" value="org.hibernate.ejb.HibernatePersistence"/> 
    <property name="persistenceUnitName" value="bars"/> 
    <property name="dataSource" ref="dataSource"/> 
    <property name="jpaProperties"> 
     <props> 
     <prop key="hibernate.cache.region.factory_class">${hibernate.cache.region.factory_class}</prop> 
     <prop key="hibernate.cache.use_second_level_cache">${hibernate.second.level.cache}</prop> 
     <prop key="hibernate.cache.use_query_cache">${hibernate.query.cache}</prop> 
     <prop key="hibernate.generate_statistics">true</prop> 
     <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop> 
     <prop key="hibernate.jdbc.batch_size">${hibernate.jdbc.batch_size}</prop> 
     <prop key="hibernate.show_sql">${database.show.sql}</prop> 
     <prop key="hibernate.dialect">${database.hibernate.dialect}</prop> 
     <prop key="hibernate.search.default.directory_provider">filesystem</prop> 
     <prop key="hibernate.search.default.indexBase">${hibernate.search.dir}</prop> 
     </props> 
    </property> 
    </bean> 
</beans> 

堆棧跟蹤

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.bar.persistence.dao.SpringDataLearningTest': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.bar.persistence.dao.barDao com.bar.persistence.dao.SpringDataLearningTest.barDao; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.bar.persistence.dao.BarDao] 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:288) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1120) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:379) 
    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:313) 
    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:12) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:284) 
    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: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.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:309) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) 
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160) 
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:76) 
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:195) 
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:63) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120) 
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.bar.persistence.dao.BarDao com.bar.persistence.dao.SpringDataLearningTest.barDao; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.bar.persistence.dao.BarDao] 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:514) 
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:285) 
    ... 29 more 
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.bar.persistence.dao.BarDao] 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:967) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:837) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:749) 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:486) 
    ... 31 more 
+0

能否請你分享其中的堆棧跟蹤整個錯誤消息? – zagyi 2013-02-28 17:22:58

回答

2

類似的東西:

  1. BarDao
  2. 刪除@NoRepositoryBean上BarDaoImpl
  3. 移動BarDaoImplBarDao添加@NoRepositoryBeancom.bar.persistence.dao.bar
  4. 添加新interface BarDaoMyRepository extends BarDaocom.bar.persistence.dao.repository
  5. 設置base-package="com.bar.persistence.dao.repository"
  6. 注入您使用的方式來BarDaoMyRepository

添加一些功能ty擴展到每個擴展爲BarDao的存儲庫(因此您需要擴展它並添加一些聲明性方法)。 如果你想添加的功能只有一個倉庫 - 看

http://static.springsource.org/spring-data/data-jpa/docs/current/reference/html/repositories.html#repositories.introduction 1.4.1添加行爲,以單一存儲庫

+0

這樣做! :-)雖然我有點困惑,爲什麼它......基本上,你從Spring Data中移除了特定的存儲庫,除了原始接口上的一個接口。我期望一個接口就夠了。 – 2013-03-01 09:21:57