2014-09-22 14 views
5

प्रसंग

मैं संस्थाओं का हिस्सा है कि एक ही नाम है कि दो अलग-अलग डेटाबेस एक ही वसंत संदर्भ में उपयोग करना चाहते हैं, लेकिन एक ही संरचना में 2 खजाने इंजेक्षन। मैं स्प्रिंग डेटा मोंगोडीबी और जेपीए/जेडीबीसी पर भरोसा करता हूं। मेरे पास दो पैकेज हैं, जिनमें निम्नलिखित फाइलें हैं:स्प्रिंग डाटा: ही नाम के साथ लेकिन 2 अलग संकुल

  • कॉम। बार .entity
    • Car.class
  • कॉम। बार .repository
    • CarRepository.class
    • RepoBarMarker.class
  • कॉम। बार
    • .config MongoConfiguration.class
  • कॉम। foo .entity
    • Car.class
  • कॉम। foo .repository
    • CarRepository.class
    • RepoFooMarker.class
  • कॉम। foo .config
    • JPAConfiguration.class
    • SpecEntityManagerFactory.class

प्रत्येक Car.class की सामग्री के विभिन्न मैं उन्हें पुन: उपयोग नहीं किया जा सकता है। बार स्प्रिंग-मोंगो और foo स्प्रिंग-जेपीए का उपयोग करता है, और भंडार @EnableMongoRepositories और @EnableJpaRepositories एनोटेशन के माध्यम से शुरू किए जाते हैं।

@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 

अपने आवेदन घटक में से एक में मैं भंडार के foo संस्करण पर पहुँचने का प्रयास करते हैं ऐसा प्रतीत होता है कि वसंत एक बार को भंडार भंडार में एक नया बीन बनाने के बजाय भंडार को बदलने की कोशिश करता है, जैसा कि एक ही स्टैक में है, मेरे पास निम्नलिखित अपवाद भी है:

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 के बजाय का प्रयास करें:

@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 

वसंत-डेटा विन्यास

में foo (जेपीए) पैकेज, 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 में बदलता हूं, तो सब कुछ काम करता है। लेकिन वसंत डेटा भंडारों के लिए, नाम बदलने के बजाए उन्हें फिर से नाम बदलने से बचने के लिए दूर है और अभी भी एक असली तारों का नाम है (जैसा कि ऐसा लगता है)?

+0

क्या आप कृपया अपनी स्प्रिंग डेटा कॉन्फ़िगरेशन दिखा सकते हैं? – geoand

+0

@geoand स्प्रिंग डेटा कॉन्फ़िगरेशन के साथ अपडेट किया गया। मेरा सेटअप अधिक जटिल है, मैंने आवश्यक स्प्रिंग डेटा कॉन्फ़िगरेशन भाग को रखते हुए इसे सरल बना दिया। – Nicolas

+0

मुझे संदेह है कि यह काम करेगा, लेकिन क्या आप 'com.foo.repository.CarRepository' पर' @ रिपोजिटरी ("fooCarRepository") जोड़ने की कोशिश कर रहे हैं? – geoand

उत्तर

3

आपके मामले में, आप का उपयोग कर स्प्रिंग डाटा @Repositoryनहीं आम तौर पर इंटरफेस पर की जरूरत है

com.foo.repository.CarRepository

के इंटरफेस घोषणा पर

@Repository("fooCarRepository")

उपयोग कर सकते हैं हालांकि जब, हालांकि आपके मामले में आपको इसे आपूर्ति करने की आवश्यकता है। ऐसा इसलिए है क्योंकि नाम टकराव से बचने के लिए आपको स्प्रिंग को कस्टम नाम (इस मामले में fooCarRepository) के साथ बीन के कार्यान्वयन को पंजीकृत करने की आवश्यकता है।

+0

तो असल में वसंत पैकेज को अनदेखा कर रहा है ?? –

+0

@KeesdeKooter मुझे यकीन नहीं है कि मैं समझता हूं :( – geoand

+1

@geond 'com.foo.repository.CarRepository' 'com.bar.repository.CarRepository' की तुलना में एक अलग वर्ग है, लेकिन स्पष्ट रूप से वसंत केवल क्लासनाम का उपयोग करता है, न कि पैकेज का नाम डिफ़ॉल्ट बीन नाम। और यह आपको डुप्लिकेट की चेतावनी नहीं देता है। –

संबंधित मुद्दे