JPA多数据源配置-Kotlin版本

1,使用环境:SpringBoot 3.0.6

2,application.yml配置文件配置好数据源

spring:
  datasource:
  	#第一个数据源
    test1:
      jdbc-url: jdbc:mysql://127.0.0.1:3306/test1?serverTimezone=Asia/Shanghai
      username: root
      password: 123456
      driver-class-name: com.mysql.cj.jdbc.Driver
    #第二个数据源
    test2:
      jdbc-url: jdbc:mysql://127.0.0.1:3306/test2?serverTimezone=Asia/Shanghai
      username: root
      password: 123456
      driver-class-name: com.mysql.cj.jdbc.Driver

3,配置Config

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.jdbc.DataSourceBuilder
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Primary
import org.springframework.data.jpa.repository.config.EnableJpaRepositories
import org.springframework.orm.jpa.JpaTransactionManager
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean
import org.springframework.transaction.PlatformTransactionManager
import org.springframework.transaction.annotation.EnableTransactionManagement
import javax.sql.DataSource

/**
 * 多数据源配置
 */
@Configuration
class DataSourceConfig {
    /**
     * 主数据源
     */
    @Primary
    @Bean(name = ["test1DataSource"])
    @Qualifier("test1DataSource")
    //和yml配置的数据源前缀一致
    @ConfigurationProperties(prefix = "spring.datasource.test1")
    fun systemDataSource(): DataSource {
        return DataSourceBuilder.create().build()
    }

    /**
     * 第二个数据源
     */
    @Bean(name = ["test2DataSource"])
    @Qualifier("test2DataSource")
    //和yml配置的数据源前缀一致
    @ConfigurationProperties(prefix = "spring.datasource.test2")
    fun messageDataSource(): DataSource {
        return DataSourceBuilder.create().build()
    }

}


/**
 * 主数据源配置Repository
 */
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
    entityManagerFactoryRef = "test1EntityManagerFactory",
    transactionManagerRef = "test1TransactionManager",
    //Repository所在位置
    basePackages = ["com.test1.repositorys"]
)
class Test1Config {
    @Autowired
    @Qualifier("test1DataSource")
    lateinit var test1DataSource: DataSource

    @Autowired
    lateinit var jpaProperties: JpaProperties

    @Autowired
    lateinit var hibernateProperties: HibernateProperties

    //主数据源
    @Primary
    @Bean(name = ["test1EntityManagerFactory"])
    fun entityManagerFactory(builder: EntityManagerFactoryBuilder): LocalContainerEntityManagerFactoryBean {
        val properties = hibernateProperties.determineHibernateProperties(jpaProperties.properties, HibernateSettings())
        return builder.dataSource(test1DataSource).properties(properties)
            //实体包路径
            .packages("com.test1.domains").build()
    }

    @Primary
    @Bean(name = ["test1TransactionManager"])
    fun systemTransactionManager(builder: EntityManagerFactoryBuilder): PlatformTransactionManager? {
        return entityManagerFactory(builder).`object`?.let { JpaTransactionManager(it) }
    }

}


/**
 * 第二个数据源配置Repository
 */
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
    entityManagerFactoryRef = "test2EntityManagerFactory",
    transactionManagerRef = "test2TransactionManager",
    //Repository所在位置
    basePackages = ["com.test2.repositorys"]
)
class Test2Config {

    @Autowired
    @Qualifier("test2DataSource")
    lateinit var test2DataSource: DataSource

    @Autowired
    lateinit var jpaProperties: JpaProperties

    @Autowired
    lateinit var hibernateProperties: HibernateProperties

    @Bean(name = ["test2EntityManagerFactory"])
    fun entityManagerFactory(builder: EntityManagerFactoryBuilder): LocalContainerEntityManagerFactoryBean {
        val properties = hibernateProperties.determineHibernateProperties(jpaProperties.properties, HibernateSettings())
        return builder.dataSource(test2DataSource).properties(properties)
            //实体包路径
            .packages("com.test2.domains").build()
    }

    @Bean(name = ["test2TransactionManager"])
    fun systemTransactionManager(builder: EntityManagerFactoryBuilder): PlatformTransactionManager? {
        return entityManagerFactory(builder).`object`?.let { JpaTransactionManager(it) }
    }
}

4,使用

//@Transactional 注解可以手动指定事物用以区分
@Transactional(value = "test2TransactionManager")
//EntityManager也需要手动指定
@Autowired
@Qualifier("test2EntityManagerFactory")
lateinit var entityManager: EntityManager
### 使用 Kotlin 和 GraalVM 配置 JPA 的集成设置 #### 背景介绍 在现代应用程序开发中,GraalVM 提供了一种高效的方式来构建本地镜像(native image),从而显著提高启动时间和运行性能。然而,在使用 Spring Data JPA 时,由于其依赖于反射机制来创建对象实例,而 GraalVM 默认会禁用未显式注册的反射调用,因此需要额外配置以支持这些功能。 以下是关于如何在基于 Kotlin 的项目中实现 GraalVM 和 JPA 的集成的具体方法: --- #### 创建初始项目结构 可以通过访问 [Spring Initializr](https://start.spring.io/) 来初始化一个新的 Spring Boot 项目[^2]。选择以下选项: - **Project**: Maven 或 Gradle - **Language**: Kotlin - **Dependencies**: 添加 `Spring Web`, `Spring Data JPA` 和其他必要的库 下载并解压该项目后,将其导入到 IDE 中。 --- #### 配置数据库连接 为了使 JPA 正常工作,需通过 `application.properties` 文件定义数据源的相关属性[^3]。例如: ```properties spring.datasource.url=jdbc:h2:mem:testdb spring.datasource.driver-class-name=org.h2.Driver spring.datasource.username=sa spring.datasource.password=password spring.jpa.database-platform=org.hibernate.dialect.H2Dialect ``` 上述配置指定了 H2 数据库作为内存中的测试环境。实际生产环境中可根据需求替换为 MySQL、PostgreSQL 等关系型数据库。 --- #### 注册实体类用于反射 当使用 GraalVM 构建 native image 时,默认情况下不会自动检测到所有的反射操作。为此,必须手动声明哪些类和字段可能被动态加载或修改。这通常涉及编辑 `reflect-config.json` 文件[^4]。 假设有一个简单的 `Person` 实体模型如下所示: ```kotlin import javax.persistence.* @Entity data class Person( @Id @GeneratedValue(strategy = GenerationType.IDENTITY) val id: Long? = null, var firstName: String, var lastName: String ) ``` 此时应向 reflect 配置文件添加类似下面的内容: ```json [ { "name": "com.example.demo.Person", "allDeclaredConstructors": true, "allPublicConstructors": true, "allDeclaredMethods": true, "allPublicMethods": true, "fields": [ {"name":"firstName"}, {"name":"lastName"} ] } ] ``` 此 JSON 片段告诉编译器允许对指定类型的构造函数以及成员变量执行反射访问。 --- #### 修改 build.gradle.kts 支持 Native Image 编译 如果采用的是 Gradle,则应在项目的根目录下的 `build.gradle.kts` 文件里引入插件和支持脚本。具体来说就是加入 graalvm 插件及相关参数设定部分。 ```gradle plugins { ... id("org.graalvm.buildtools.native") version "0.9.17" } graalvmNative { binaries.all { resources.autodetect() // Add additional reflection configurations here. addOptions("--initialize-at-build-time=com.example.demo") } } ``` 以上片段启用了 org.graalvm.buildtools.native 插件,并设置了资源自检模式以便更好地兼容 spring 应用程序上下文中所使用的各种组件和服务发现逻辑。 --- #### 测试生成的应用程序 完成所有更改之后,可以尝试构建一个原生二进制版本并通过命令行验证它是否能够正常运作: ```bash ./gradlew clean nativeCompile target/demo-application ``` 如果一切顺利的话,应该可以看到应用成功启动的消息输出至终端窗口之中;反之则可以根据错误提示进一步调整相关设置直至满足条件为止。 --- ### 总结 综上所述,要在 Kotlin 开发环境下利用 GraalVM 完成与 JPA 的无缝衔接,不仅需要注意基础框架的选择与搭建过程,还需要特别留意因 AOT(Ahead Of Time Compilation)特性带来的特殊约束——即对于那些原本依靠 JVM 动态特性的 API 呼叫链路都需要提前予以明确定义才行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值