요즘 재미삼아 스프링 공부를 해보고 있는데
우리나라에서는 Database를 사용할때 mybatis나 아니면 JPA를 쓰더군요
저는 어차피 재미 삼아 공부를 하는 거기때문에 Jetbrains에서 만든 Exposed가 눈에 띄었습니다.
Query 형 또는 Dao형 둘다 되더군요..
거기에다 저는 무려 Jetbrains의 노예이기 때문에.. 한번 공부를 해야겠다는 마음을 먹고 이리저리 돌려보고 있었습니다.
이걸 여러개의 Database접근을 할 수 있는 내용을 찾아보다가 삽질하면서 만들어봤습니다.
프로젝트 스프링부트 프로젝트 빌드 타입은 Gradle 그리고 언어는 당연하게도 코틀린을 선택하였습니다.
(Jetbrains Exposed는 코틀린 전용 DB 프레임워크 라이브러리입니다..)
build.gradle.kts에서 dependencies부분에 Jetbrains exposed 라이브러리를 추가해야합니다..
dependencies {
// with exposed
implementation("org.jetbrains.exposed:exposed-spring-boot-starter:0.34.1")
}
application.yaml
spring:
datasource:
hikari:
primary:
driver-class-name: org.mariadb.jdbc.Driver
jdbc-url: jdbc:mariadb://localhost:3306/db
username: sa
password: 1234!
maximum-pool-size: 50
max-lifetime: 30000
idle-timeout: 28000
connection-timeout: 0
transaction-isolation: TRANSACTION_READ_UNCOMMITTED
secondary:
driver-class-name: org.mariadb.jdbc.Driver
jdbc-url: jdbc:mariadb://localhost:3307/db
username: sa
password: 1234!
maximum-pool-size: 50
max-lifetime: 30000
idle-timeout: 28000
connection-timeout: 0
transaction-isolation: TRANSACTION_READ_UNCOMMITTED
DataBaseConfig.kt
import com.zaxxer.hikari.HikariConfig
import com.zaxxer.hikari.HikariDataSource
import org.jetbrains.exposed.spring.SpringTransactionManager
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Primary
import org.springframework.transaction.annotation.EnableTransactionManagement
import javax.sql.DataSource
@Configuration
@EnableTransactionManagement
class Datasource{
@Bean
@Primary
@Qualifier("primaryHikariConfig")
@ConfigurationProperties(prefix = "spring.datasource.hikari.primary")
fun primaryHikariConfig(): HikariConfig? {
return HikariConfig()
}
@Bean
@Primary
@Qualifier("primaryDataSource")
@Throws(Exception::class)
fun primaryDataSource(): DataSource? {
return HikariDataSource(primaryHikariConfig())
}
@Bean
@Qualifier("secondaryHikariConfig")
@ConfigurationProperties(prefix = "spring.datasource.hikari.secondary")
fun secondaryHikariConfig(): HikariConfig? {
return HikariConfig()
}
@Bean
@Qualifier("secondaryDataSource")
@Throws(java.lang.Exception::class)
fun secondaryDataSource(): DataSource? {
return HikariDataSource(secondaryHikariConfig())
}
}
@Configuration
@EnableTransactionManagement
class DatabaseConfig(
@Qualifier("primaryDataSource") private val dataSource: DataSource, @Qualifier("secondaryDataSource") private val secondaryDataSource : DataSource
) {
@Bean(name = ["PrimaryDB"])
@Primary
fun primaryTransactionManager() = SpringTransactionManager(dataSource)
@Bean(name = ["SecondaryDataDB"])
fun secondaryTransactionManager() = SpringTransactionManager(secondaryDataSource)
}
이제 한번 테스트로 두번째로 연결된 DB로 대충 만든 테이블을 Sleect 해보자...
import org.jetbrains.exposed.dao.IntEntity
import org.jetbrains.exposed.dao.IntEntityClass
import org.jetbrains.exposed.dao.id.EntityID
import org.jetbrains.exposed.dao.id.IntIdTable
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.transactions.transaction
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
// name = "user" 테이블 이름이 user 라는 뜻
// 테이블 이름지정 없이 할 경우 클래스 이름으로 테이블에 접근하게 된다. users
// id 컬럼을 다른 이름으로 지정했을 경우 이런식으로 바꿀수도 있다.
object Users : IntIdTable(name = "user", columnName = "idx") {
val name = varchar("user_id", 256)
val pw = varchar("user_pw", 256)
}
class User(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<User>(Users)
val name by Users.name
val pw by Users.pw
}
@Service
@Transactional("SecondaryDataDB")
class UserRepository {
fun showAll() {
transaction {
for (user in User.all()) {
println("id: ${user.id.value}, name:${user.name} password: ${user.pw}")
}
}
}
}
처음에는 스프링 자체도 낯설다 보니 헤맸지만 막상 하고 보니 어렵지는 않다.