@Primary即时

时间:2018-05-21 18:40:11

标签: spring kotlin spring-data-jpa

我需要一个建议。

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

enter image description here

现在,radiusfttx.domain包中的bean注释为@Primary。这个项目基本上就是它,它没有做任何事情。

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

@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,那么一切都不起作用。正如您在上面的示例中所看到的,我没有添加&#34; radiusfttx.domain&#34; @ComponentScan和@Primary就在那里。

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

提前致谢。

编辑1

作为一种解决方法,我创建了一个&#34;虚拟&#34; H2持久性我标记为@Primary并添加到我的所有项目中。这样,我所有的真实&#34;数据源不需要设置为@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`
    }
}

2 个答案:

答案 0 :(得分:1)

您可以使用@Qualifier,或者根本不将您的组件标记为@Component,而是将它们作为简单类留在您的lib中,并根据@Bean设置您想要的任何一个在客户端应用程序中。

通过这种方式,您可以拥有单个数据源,或者如果您需要更多数据源,则可以在@Primary上添加@Bean

关于配置文件,您可以设置除prod / dev / test之外的其他配置文件,例如prod,ds1 prod,ds2 test,tds1等等......

答案 1 :(得分:0)

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

虽然我理解@Qualifier的用法,但对于我的特定项目来说,它还不够,因为据我所知,注释必须在&#34;库&#34;导入的项目。我的问题实际上与事务有关,因为在导入一个特定的包之后我无法指定@Primary,其中持久性配置尚未标记为@Primary。

所以我就是这样解决的。

而不是仅仅在&#34;库&#34;上创建存储库。项目我还在那里创建了@Service层。这些@Services我也可以使用@Transactional进行注释,并命名transactionManager Spring需要用于该特定服务。所以,在&#34; ServiceDummy&#34;例如,我可以添加@Transactional(&#34; tmDummy&#34;)并仅在另一个应用程序上自动装配@Service。这样,Spring就不会争论有两个,三个或更多的transactionManagers可供选择。

简要示例:

package com.entre.databases.dummy.service

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

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

}

另一个导入&#34;库&#34;:

的应用程序
@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)
}