Last active
June 20, 2020 10:24
-
-
Save yusufcakal/d7c8b52f47389fd0763bc7b199277d52 to your computer and use it in GitHub Desktop.
Using TransactionalReadOnly annotation to change data source in runtime for Spring
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Configuration | |
@EnableTransactionManagement | |
public class DatabaseConfiguration { | |
@Bean | |
@Primary | |
@Profile("!test") | |
@DependsOn({"primaryDataSource", "replicaDataSource"}) | |
public DataSource dataSource(@Qualifier("primaryDataSource") HikariDataSource primaryDataSource, | |
@Qualifier("replicaDataSource") HikariDataSource replicaDataSource) { | |
final RoutingDataSource routingDataSource = new RoutingDataSource(); | |
final Map<Object, Object> targetDataSources = new HashMap<>(); | |
targetDataSources.put(RoutingDataSource.Route.PRIMARY, primaryDataSource); | |
targetDataSources.put(RoutingDataSource.Route.REPLICA, replicaDataSource); | |
routingDataSource.setTargetDataSources(targetDataSources); | |
routingDataSource.setDefaultTargetDataSource(primaryDataSource); | |
return routingDataSource; | |
} | |
@Profile("!test") | |
@Bean(destroyMethod = "close") | |
public HikariDataSource primaryDataSource() { | |
HikariConfig hikariConfig = buildHikariConfig("primary-hikari-pool", dataSourceProperties.getUrl()); | |
return new HikariDataSource(hikariConfig); | |
} | |
@Profile("!test") | |
@Bean(destroyMethod = "close") | |
public HikariDataSource replicaDataSource() { | |
HikariConfig hikariConfig = buildHikariConfig("replica-hikari-pool", dataSourceProperties.getReplicaUrl()); | |
return new HikariDataSource(hikariConfig); | |
} | |
private HikariConfig buildHikariConfig(String poolName, String url) { | |
HikariConfig hikariConfig = new HikariConfig(); | |
hikariConfig.setPoolName(poolName); | |
hikariConfig.setDataSourceClassName(dataSourceProperties.getDriverClassName()); | |
hikariConfig.addDataSourceProperty("url", url); | |
hikariConfig.addDataSourceProperty("user", dataSourceProperties.getUsername()); | |
hikariConfig.addDataSourceProperty("password", dataSourceProperties.getPassword()); | |
hikariConfig.setMaximumPoolSize(dataSourceProperties.getMaxPoolSize()); | |
hikariConfig.setMinimumIdle(dataSourceProperties.getMinIdle()); | |
hikariConfig.setLeakDetectionThreshold(dataSourceProperties.getLeakThreshold()); | |
hikariConfig.setConnectionTimeout(10000); | |
hikariConfig.setMaxLifetime(360000); | |
hikariConfig.setIdleTimeout(80000); | |
return hikariConfig; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Aspect | |
@Component | |
@Order(Ordered.HIGHEST_PRECEDENCE) | |
@ConditionalOnProperty("read.replica.enabled") | |
public class ReadOnlyRouteInterceptor { | |
@Around("@annotation(TransactionalReadOnly)") | |
public Object proceed(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { | |
try { | |
RoutingDataSource.setReplicaRoute(); | |
return proceedingJoinPoint.proceed(); | |
} finally { | |
RoutingDataSource.clearReplicaRoute(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class RoutingDataSource extends AbstractRoutingDataSource { | |
private static final ThreadLocal<Route> ctx = new ThreadLocal<>(); | |
public static void clearReplicaRoute() { | |
ctx.remove(); | |
} | |
public static void setReplicaRoute() { | |
ctx.set(Route.REPLICA); | |
} | |
@Override | |
protected Object determineCurrentLookupKey() { | |
return ctx.get(); | |
} | |
public enum Route { | |
PRIMARY, REPLICA | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Target(ElementType.METHOD) | |
@Retention(RetentionPolicy.RUNTIME) | |
@Transactional(readOnly = true, propagation = Propagation.REQUIRES_NEW) | |
public @interface TransactionalReadOnly { | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment