首页 > 解决方案 > @Primary 即时

问题描述

我需要一个建议。

我有基础 Maven 项目,我在其中声明了所有存储库、实体和持久性类。它们都是无 XML 配置的。每个数据库及其所有相关类都按包划分。这个项目上的所有东西都被注释了,例如:@Entity、@Repository、@Configuration、@Primary 等等……它看起来像这样:

在此处输入图像描述

现在,radiusfttx.domain 包中的 bean 被注释为 @Primary。这个项目基本上就是它,它自己什么都不做。

然后,当我创建一个需要访问任何数据库的新项目时,我只需使用 Maven 导入第一个项目,并且在新项目初始化时,我像这样更改它(它是 Kotlin,但我很确定你可以得到想法):

@SpringBootApplication
@ComponentScan(basePackages = [
    "com.entre.rest.boot", <-- my main class is here
    "com.entre.databases.mailserver.domain", <-- repos from the other project
    "com.entre.databases.integrator.domain" ])

由于所有内容都已注释,因此 Spring-boot 的自动配置会选择类并毫无问题地创建 bean。好吧,至少在我尝试向数据库提交一些东西之前。

因为只有一个持久性可以具有 @Primary 注释,所以如果我不将该持久性添加到 @ComponentScan 一切都不起作用。正如您在上面的示例中所看到的,我没有将“radiusfttx.domain”添加到@ComponentScan 并且@Primary 在那里。

所以我的问题是:有没有办法可以即时设置@Primary?被注释和硬编码不适用于我在这里尝试做的事情。有任何想法吗?

提前致谢。

编辑 1

作为一种解决方法,我创建了一个“虚拟”H2 持久性,我将其标记为 @Primary 并添加到我的所有项目中。这样,我所有的“真实”数据源都不需要设置@Primary。这远不是解决这种情况的方法,但它确实有效。如果有人能想出更好的东西,这个问题仍然悬而未决。

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "emfDummy", transactionManagerRef = "tmDummy",
        basePackages = ["com.entre.databases.dummy.domain"])
class DummyPersistence {
    @Primary
    @Bean("dsDummy")
    fun dataSource() = HikariDataSource().apply {
        username = "sa"
        password = "sa"
        jdbcUrl = "jdbc:h2:mem:db;DB_CLOSE_DELAY=-1"
        driverClassName = "org.h2.Driver"
    }

    fun hibernateJpaVendorAdapter() = HibernateJpaVendorAdapter().apply {
        setDatabasePlatform("org.hibernate.dialect.H2Dialect")
        setShowSql(false)
        setGenerateDdl(true)
    }

    @Primary
    @Bean("emfDummy")
    fun entityManagerFactory() = LocalContainerEntityManagerFactoryBean().apply {
        setPackagesToScan("com.entre.databases.dummy.domain")
        jpaVendorAdapter = hibernateJpaVendorAdapter()
        dataSource = dataSource()
        persistenceUnitName = "puDummy"
        afterPropertiesSet()
    }

    @Primary
    @Bean("tmDummy")
    fun transactionManager() = JpaTransactionManager().apply {
        entityManagerFactory = entityManagerFactory().`object`
    }
}

标签: springkotlinspring-data-jpa

解决方案


感谢所有的答案,你让我找到了正确的方向。

尽管我了解 @Qualifier 的使用,但对于我的特定项目来说还不够,因为据我所知,注释必须位于导入的“库”项目中。我的问题实际上出在事务上,因为在导入持久性配置尚未标记为@Primary 的特定包后,我无法指定@Primary。

所以这就是我解决它的方法。

我不仅在“库”项目上创建存储库,还在那里创建了@Service 层。这些@Services 我也可以用@Transactional 注释并命名事务管理器Spring 需要用于该特定服务。因此,例如,在“ServiceDummy”中,我可以添加 @Transactional("tmDummy") 并仅在其他应用程序上自动装配 @Service。这样一来,Spring 就不会争论有 2、3 或更多的事务管理器可供选择。

简要示例:

package com.entre.databases.dummy.service

@Service
@Transactional("tmDummy")
class DummyService(
    val dummyRepository: DummyRepository)
{

    fun findDummy(id: Int): Optional<Dummy> {
        return dummyRepository.findById(id)
    }

}

而在导入“库”的另一个应用程序上:

@SpringBootApplication
@ComponentScan(basePackages = [
    "com.entre.rest.boot",
    "com.entre.databases.dummy.service",
    "com.entre.rest.web"
])
class Application

fun main(args: Array<String>) {
    runApplication<Application>(*args)
}

推荐阅读