DATA JPA를 사용할 때, read only와 write db를 따로 구성해서 서버 성능을 올리고 싶을때 사용한다.
import java.util.HashMap;
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 com.zaxxer.hikari.HikariDataSource;
@Configuration
public class MyDataSourceConfiguration {
public static final String MASTER_DATASOURCE = "masterDataSource";
public static final String SLAVE_DATASOURCE = "slaveDataSource";
@Bean(MASTER_DATASOURCE)
@ConfigurationProperties(prefix = "spring.datasource.master.hikari")
public DataSource masterDataSource() {
return DataSourceBuilder.create()
.type(HikariDataSource.class)
.build();
}
@Bean(SLAVE_DATASOURCE)
@ConfigurationProperties(prefix = "spring.datasource.slave.hikari")
public DataSource slaveDataSource() {
return DataSourceBuilder.create()
.type(HikariDataSource.class)
.build();
}
@Bean
@Primary
@DependsOn({MASTER_DATASOURCE, SLAVE_DATASOURCE})
public DataSource routingDataSource(
@Qualifier(MASTER_DATASOURCE) DataSource masterDataSource,
@Qualifier(SLAVE_DATASOURCE) DataSource slaveDataSource) {
RoutingDataSource routingDataSource = new RoutingDataSource();
Map<Object, Object> datasourceMap = new HashMap<>() {
{
put("master", masterDataSource);
put("slave", slaveDataSource);
}
};
routingDataSource.setTargetDataSources(datasourceMap);
routingDataSource.setDefaultTargetDataSource(masterDataSource);
return routingDataSource;
}
@Bean
@DependsOn("routingDataSource")
public LazyConnectionDataSourceProxy dataSource(DataSource routingDataSource){
return new LazyConnectionDataSourceProxy(routingDataSource);
}
}
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.springframework.transaction.support.TransactionSynchronizationManager;
public class RoutingDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() { // (1)
return (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) ? "slave" : "master"; //(2)
}
}
properties
#DB
spring.datasource.master.hikari.username=
spring.datasource.master.hikari.password=
spring.datasource.master.hikari.driver-class-name=net.sf.log4jdbc.sql.jdbcapi.DriverSpy
spring.datasource.master.hikari.jdbc-url=
spring.datasource.master.hikari.minimum-idle=5
spring.datasource.master.hikari.connection-timeout=30000
spring.datasource.master.hikari.validation-timeout=30000
spring.datasource.master.hikari.max-lifetime=240000
spring.datasource.master.hikari.maximum-pool-size=5
spring.datasource.slave.hikari.username=
spring.datasource.slave.hikari.password=
spring.datasource.slave.hikari.driver-class-name=net.sf.log4jdbc.sql.jdbcapi.DriverSpy
spring.datasource.slave.hikari.jdbc-url=
spring.datasource.slave.hikari.minimum-idle=5
spring.datasource.slave.hikari.connection-timeout=30000
spring.datasource.slave.hikari.validation-timeout=30000
spring.datasource.slave.hikari.max-lifetime=240000
spring.datasource.slave.hikari.maximum-pool-size=5
private final MemberRepository memberRepository;
@Transactional(readOnly = true)
public Member selectMember(String memberKey){
return memberRepository.findByMemberKey(memberKey);
}
이런식으로 select만 하는 method를 만들어 사용하면 된다.
주의할 점은 readOnly가 설정되어 있더라도 method 안에 write하는 쿼리가 있다면, method 안에 모든 쿼리는 write db로 쓰여진다.
'개발 > Spring' 카테고리의 다른 글
Spring boot health check. (0) | 2022.04.06 |
---|---|
Spring boot profile(AWS Secret Manager, Log4j2) (0) | 2022.04.06 |
Spring boot&React Cookie 설정 SameSite Cookie 변경된 크롬 80 쿠키 정책 (0) | 2022.04.06 |
Part.2 Spring boot 갯수 제한 이벤트 구현(Redis 이용) Redisson, Transaction, Sync(lock) 유저가 많이 몰릴때. (0) | 2022.04.06 |
Spring @RequestParam @RequestBody @ModelAttribute 차이 (0) | 2022.03.20 |