2014-09-22 48 views
5

語境

我想在同一個Spring上下文使用具有共享同一名稱的實體兩個不同的數據庫,但不是相同的結構。我依靠Spring Data MongoDB和JPA/JDBC。我有兩個軟件包,其中包含以下文件:春數據:注入2個倉庫名稱相同,但在2周不同的包

  • com。 酒吧 .entity
    • Car.class
  • 融爲一體。 酒吧 .repository
    • CarRepository.class
    • RepoBarMarker.class
  • 融爲一體。 酒吧的.config
    • MongoConfiguration.class
  • 融爲一體。 .entity
    • Car.class
  • 融爲一體。 .repository
    • CarRepository.class
    • RepoFooMarker.class
  • 融爲一體。 的.config
    • JPAConfiguration.class
    • SpecEntityManagerFactory.class

每個Car.class的內容是不同的,我不能重複使用。 bar使用Spring-Mongo和foo使用Spring-JPA,並通過@EnableMongoRepositories和@EnableJpaRepositories註釋來初始化存儲庫。當我的應用程序組件之一,我嘗試訪問FOO版本庫的:

@Resource 
private com.foo.repository.CarRepository carRepository; 

我當創建了包含@Resource方面的階級以下異常:

Caused by: org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'carRepository' must be of type [com.foo.repository.CarRepository], but was actually of type [com.sun.proxy.$Proxy31] 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:374) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198) 
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:446) 
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:420) 
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:545) 
    at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:155) 
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) 
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:305) 
    ... 26 more 

看來,Spring試圖將一個條形碼庫存儲庫轉換爲foo存儲庫,而不是創建一個新的bean,因爲在同一個堆棧中,我也有以下例外:

Caused by: java.lang.IllegalStateException: Cannot convert value of type [com.sun.proxy.$Proxy31 implementing com.bar.repository.CarRepository,org.springframework.data.repository.Repository,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised] to required type [com.foo.repository.CarRepository]: no matching editors or conversion strategy found 
     at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:267) 
     at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:93) 
     at org.springframework.beans.TypeConverterSupport.doConvert(TypeConverterSupport.java:64) 
     ... 35 more 

如果我嘗試,而不是自動裝配庫:

@Autowire 
private com.foo.repository.CarRepository carRepository; 

我得到以下異常:

Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.foo.CarRepository com.shell.ShellApp.carRepository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.foo.CarRepository] 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:509) 
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:290) 
    ... 26 more 

Spring的數據配置

(JPA)包,JPAConfigration.class

@Configuration 
@EnableJpaRepositories(basePackageClasses = RepoFooMarker.class) 
public class JPAConfiguration { 

    @Autowired 
    public DataSource dataSource; 

    @Autowired 
    public EntityManagerFactory entityManagerFactory; 

    @Bean 
    public EntityManager entityManager(final EntityManagerFactory entityManagerFactory) { 
     return entityManagerFactory.createEntityManager(); 
    } 

    @Bean 
    public Session session(final EntityManager entityManager) 
    { 
     return entityManager.unwrap(Session.class); 
    } 

    @Bean 
    public PlatformTransactionManager transactionManager() throws SQLException { 

     final JpaTransactionManager txManager = new JpaTransactionManager(); 
     txManager.setEntityManagerFactory(entityManagerFactory); 
     return txManager; 
    } 

    @Bean 
    public HibernateExceptionTranslator hibernateExceptionTranslator() { 
     return new HibernateExceptionTranslator(); 
    } 
} 

SpecEntityManagerFactory.class

@Configuration 
public class SpecEntityManagerFactory { 

    @Bean 
    public EntityManagerFactory entityManagerFactory(final DataSource dataSource) throws SQLException { 

     final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); 
     vendorAdapter.setGenerateDdl(false); 
     vendorAdapter.setDatabase(Database.POSTGRESQL); 

     final LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); 
     factory.setJpaVendorAdapter(vendorAdapter); 
     factory.setPackagesToScan("com.foo.entity"); 
     factory.setJpaProperties(getHibernateProperties()); 
     factory.setDataSource(dataSource); 
     factory.afterPropertiesSet(); 

     return factory.getObject(); 
    } 

    private Properties getHibernateProperties() 
    { 
     final Properties hibernateProperties = new Properties(); 
     hibernateProperties.setProperty("hibernate.temp.use_jdbc_metadata_defaults", "false"); 

     return hibernateProperties; 
    } 

} 

(MongoDB的)封裝,MongoConfiguration.class

@Configuration 
@EnableMongoRepositories(basePackageClasses = RepoBarMarker.class) 
public class MongoConfiguration extends AbstractRepoConfig { 

    @Override 
    @Bean 
    public MongoOperations mongoTemplate() { 

     final MongoClient mongo = this.getMongoClient(); 
     final MongoClientURI mongoUri = this.getMongoClientUri(); 

     final MongoTemplate mongoTemplate = new MongoTemplate(mongo, mongoUri.getDatabase()); 
     mongoTemplate.setReadPreference(ReadPreference.secondaryPreferred()); 
     mongoTemplate.setWriteConcern(WriteConcern.UNACKNOWLEDGED); 

     return mongoTemplate; 
    } 
} 

問題

如果我將foo存儲庫中的實體名稱更改爲CarFoo.class並將存儲庫更改爲CarFooRepository.class,則一切正常。但是,爲了避免重命名它們,並且每個類型仍然有一個真正的接線,而不是名稱(因爲這似乎是在這裏完成的),對於Spring Data存儲庫?

+0

你能不能展示你的Spring Data配置? – geoand 2014-09-22 11:50:59

+0

@geoand更新了Spring Data配置。我的設置更復雜,我簡化了它,同時保留了基本的Spring Data配置部分。 – Nicolas 2014-09-22 12:18:29

+0

我懷疑它會工作,但你介意在'com.foo.repository.CarRepository'上添加@Repository(「fooCarRepository」)嗎? – geoand 2014-09-22 12:35:56

回答

3

在你的情況,你可以使用Spring數據@Repository通常所需要的接口上的

com.foo.repository.CarRepository

接口聲明中使用

@Repository("fooCarRepository")

雖然時,但在你的情況下,你需要提供它。這是因爲你需要使用自定義名稱(在本例中爲fooCarRepository)使Spring註冊bean的實現,以避免名稱衝突。

+0

所以實際上Spring是忽略了包? – 2017-01-09 15:01:09

+0

@KeesdeKooter我不知道我明白:( – geoand 2017-01-10 09:44:27

+1

@geond'com.foo.repository.CarRepository'是與'com.bar.repository.CarRepository'不同的類,但顯然Spring只使用類名而不是包名來作爲默認的bean名稱,它並沒有警告你重複。 – 2017-01-10 10:05:40

相關問題