加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Spring Data:注入2个具有相同名称但在2个不同包中的存储库

发布时间:2020-12-15 01:27:18 所属栏目:大数据 来源:网络整理
导读:上下文 我想在同一个Spring上下文中使用两个不同的数据库,这些数据库具有共享相同名称但不是相同结构的实体.我依赖Spring Data MongoDB和JPA / JDBC.我有两个包,其中包含以下文件: com.bar.entity Car.class com.bar.repository CarRepository.class RepoBa

上下文

我想在同一个Spring上下文中使用两个不同的数据库,这些数据库具有共享相同名称但不是相同结构的实体.我依赖Spring Data MongoDB和JPA / JDBC.我有两个包,其中包含以下文件:

> com.bar.entity

> Car.class

> com.bar.repository

> CarRepository.class
> RepoBarMarker.class

> com.bar.config

> MongoConfiguration.class

> com.foo.entity

> Car.class

> com.foo.repository

> CarRepository.class
> RepoFooMarker.class

> com.foo.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尝试将bar存储库转换为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数据配置

在foo(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;
    }

}

在bar(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存储库来说,是否要避免重命名它们并且每个类型仍然有一个真正的连线,而不是名称(就像这里似乎要做的那样)?

最佳答案
在您的情况下,您可以使用

@Repository( “fooCarRepository”)

关于接口声明

com.foo.repository.CarRepository

虽然在使用Spring Data时,接口上通常不需要@Repository,但是在您的情况下需要提供它.那是因为你需要让Spring使用自定义名称(在本例中为fooCarRepository)注册bean的实现,以避免名称冲突.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读