From f848e5bedf3d35bc93b05a1b006939fa227b8de2 Mon Sep 17 00:00:00 2001 From: Laptop-Limjihoon Date: Thu, 1 Feb 2024 21:06:50 +0900 Subject: [PATCH] =?UTF-8?q?feat=20:=20CQRS=EB=A5=BC=20=EC=9C=84=ED=95=9C?= =?UTF-8?q?=20@Transactional(readOnly)=20=EC=97=90=20=EB=94=B0=EB=A5=B8=20?= =?UTF-8?q?Secondary=20DB=20=EB=A7=A4=ED=95=91=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TransactionRoutingDataSource.java | 26 ++--- .../TransactionRoutingDataSourceConfig.java | 99 +++++++++++-------- src/main/resources/application.yml | 31 +++--- 3 files changed, 84 insertions(+), 72 deletions(-) diff --git a/src/main/java/bc1/gream/global/config/datasource/TransactionRoutingDataSource.java b/src/main/java/bc1/gream/global/config/datasource/TransactionRoutingDataSource.java index 07bf1732..c20a97c8 100644 --- a/src/main/java/bc1/gream/global/config/datasource/TransactionRoutingDataSource.java +++ b/src/main/java/bc1/gream/global/config/datasource/TransactionRoutingDataSource.java @@ -1,15 +1,19 @@ package bc1.gream.global.config.datasource; -public class TransactionRoutingDataSource { -// extends AbstractRoutingDataSource { - -// @Nullable -// @Override -// protected Object determineCurrentLookupKey() { -// return TransactionSynchronizationManager -// .isCurrentTransactionReadOnly() ? -// DataSourceType.READ_ONLY : -// DataSourceType.READ_WRITE; -// } +import jakarta.annotation.Nullable; +import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; +import org.springframework.transaction.support.TransactionSynchronizationManager; + +public class TransactionRoutingDataSource + extends AbstractRoutingDataSource { + + @Nullable + @Override + protected Object determineCurrentLookupKey() { + return TransactionSynchronizationManager + .isCurrentTransactionReadOnly() ? + DataSourceType.READ_ONLY : + DataSourceType.READ_WRITE; + } } \ No newline at end of file diff --git a/src/main/java/bc1/gream/global/config/datasource/TransactionRoutingDataSourceConfig.java b/src/main/java/bc1/gream/global/config/datasource/TransactionRoutingDataSourceConfig.java index c2fbe49d..9cf059a5 100644 --- a/src/main/java/bc1/gream/global/config/datasource/TransactionRoutingDataSourceConfig.java +++ b/src/main/java/bc1/gream/global/config/datasource/TransactionRoutingDataSourceConfig.java @@ -1,52 +1,65 @@ package bc1.gream.global.config.datasource; +import com.zaxxer.hikari.HikariDataSource; +import jakarta.persistence.EntityManagerFactory; +import java.sql.SQLException; +import java.util.Map; +import javax.sql.DataSource; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.DependsOn; +import org.springframework.context.annotation.Primary; +import org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.transaction.PlatformTransactionManager; @Configuration public class TransactionRoutingDataSourceConfig { -// @ConfigurationProperties(prefix = "spring.datasource.hikari.primary") -// @Bean -// public DataSource primaryDataSource() { -// return DataSourceBuilder.create().type(HikariDataSource.class).build(); -// } -// -// @ConfigurationProperties(prefix = "spring.datasource.hikari.secondary") -// @Bean -// public DataSource secondaryDataSource() { -// return DataSourceBuilder.create().type(HikariDataSource.class).build(); -// } -// -// @DependsOn({"primaryDataSource", "secondaryDataSource"}) -// @Bean -// public DataSource routingDataSource( -// @Qualifier("primaryDataSource") DataSource primary, -// @Qualifier("secondaryDataSource") DataSource secondary) throws SQLException { -// TransactionRoutingDataSource routingDataSource = new TransactionRoutingDataSource(); -// -// Map dataSourceMap = Map.of( -// DataSourceType.READ_WRITE, primary, -// DataSourceType.READ_ONLY, secondary -// ); -// -// routingDataSource.setTargetDataSources(dataSourceMap); -// routingDataSource.setDefaultTargetDataSource(primary); -// -// return routingDataSource; -// } -// -// @DependsOn({"routingDataSource"}) -// @Primary -// @Bean -// public DataSource dataSource(DataSource routingDataSource) { -// return new LazyConnectionDataSourceProxy(routingDataSource); -// } -// -// @Bean -// public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) { -// JpaTransactionManager jpaTransactionManager = new JpaTransactionManager(); -// jpaTransactionManager.setEntityManagerFactory(entityManagerFactory); -// return jpaTransactionManager; -// } + @ConfigurationProperties(prefix = "spring.datasource.hikari.primary") + @Bean + public DataSource primaryDataSource() { + return DataSourceBuilder.create().type(HikariDataSource.class).build(); + } + @ConfigurationProperties(prefix = "spring.datasource.hikari.secondary") + @Bean + public DataSource secondaryDataSource() { + return DataSourceBuilder.create().type(HikariDataSource.class).build(); + } + + @DependsOn({"primaryDataSource", "secondaryDataSource"}) + @Bean + public DataSource routingDataSource( + @Qualifier("primaryDataSource") DataSource primary, + @Qualifier("secondaryDataSource") DataSource secondary) throws SQLException { + TransactionRoutingDataSource routingDataSource = new TransactionRoutingDataSource(); + + Map dataSourceMap = Map.of( + DataSourceType.READ_WRITE, primary, + DataSourceType.READ_ONLY, secondary + ); + + routingDataSource.setTargetDataSources(dataSourceMap); + routingDataSource.setDefaultTargetDataSource(primary); + + return routingDataSource; + } + + @DependsOn({"routingDataSource"}) + @Primary + @Bean + public DataSource dataSource(DataSource routingDataSource) { + return new LazyConnectionDataSourceProxy(routingDataSource); + } + + @Bean + public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) { + JpaTransactionManager jpaTransactionManager = new JpaTransactionManager(); + jpaTransactionManager.setEntityManagerFactory(entityManagerFactory); + return jpaTransactionManager; + } } \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 3cdc2019..bad2eca0 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,24 +1,19 @@ spring: profiles: active: prod - datasource: - url: jdbc:mysql://${DB_URL}/gream - username: ${DB_ID} - password: ${DB_PASSWORD} - driver-class-name: com.mysql.cj.jdbc.Driver - # DATASOURCE - # datasource: - # hikari: - # primary: - # driver-class-name: com.mysql.cj.jdbc.Driver - # jdbc-url: jdbc:mysql://${DB_URL}/gream - # username: ${DB_ID} - # password: ${DB_PASSWORD} - # secondary: - # driver-class-name: com.mysql.cj.jdbc.Driver - # jdbc-url: jdbc:mysql://${DB_READ_ONLY_URL}/gream - # username: ${DB_ID} - # password: ${DB_PASSWORD} + # DATASOURCE + datasource: + hikari: + primary: + driver-class-name: com.mysql.cj.jdbc.Driver + jdbc-url: jdbc:mysql://${DB_URL}/gream + username: ${DB_ID} + password: ${DB_PASSWORD} + secondary: + driver-class-name: com.mysql.cj.jdbc.Driver + jdbc-url: jdbc:mysql://${DB_READ_ONLY_URL}/gream + username: ${DB_ID} + password: ${DB_PASSWORD} # JPA jpa: hibernate: