본문 바로가기

AWS

Amazon Aurora + spring boot + java + maven

Intro.

Aurora를 사용할 때, 코드에서 어떻게 작성해야 하는지 소개하겠다. Aurora에 대한 소개는 다른 글을 참고 바란다.

MySQL 버전은 5.7.x이다.

 

1. dependency

		<dependency>
			<groupId>org.mariadb.jdbc</groupId>
			<artifactId>mariadb-java-client</artifactId>
			<version>2.4.1</version>
		</dependency>
  • mysql이 아니라 mariadb connector를 사용할 것.
  • 버전은 꼭 2.4.1을 사용할 것.
  • database 접속할 때도 driver를 mariadb를 사용하고 버전을 2.4.1로 맞춰줄 것

2. config

[1] AuroraDataSourceProperties

package com.domain.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

import lombok.Getter;
import lombok.Setter;

@Getter @Setter
@Configuration
@ConfigurationProperties(prefix = "spring.datasource.aurora")
@Profile("!test")
public class AuroraDataSourceProperties {
    private String username;
    private String password;
    private String driverClassName;
    private Writer writer;
    private Reader reader;

    @Getter @Setter
    public static class Writer {
        private String name;
        private String url;
    }
    @Getter @Setter
    public static class Reader {
        private String name;
        private String url;
    }
}

[2] AuroraRoutingDataSource

package com.domain.config;

import org.springframework.context.annotation.Profile;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import java.util.Map;


@Profile("!test")
public class AuroraRoutingDataSource extends AbstractRoutingDataSource {
    private static final String WRITER = "master";
    private static final String READER = "slave";
    @Override
    public void setTargetDataSources(Map<Object, Object> targetDataSources) {
        super.setTargetDataSources(targetDataSources);
    }

    @Override
    public Object determineCurrentLookupKey() {
        return TransactionSynchronizationManager.isCurrentTransactionReadOnly()
            ? READER : WRITER;
    }
}

[3] AuroraDataSourceConfiguration

package com.domain.config;

import com.zaxxer.hikari.HikariDataSource;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

@Configuration
@RequiredArgsConstructor
@Profile("!test")
public class AuroraDataSourceConfiguration {
    private final AuroraDataSourceProperties auroraDataSourceProperties;

    @Bean
    public DataSource routingDataSource() {
        AuroraRoutingDataSource auroraRoutingDataSource = new AuroraRoutingDataSource();
        AuroraDataSourceProperties.Writer writer = auroraDataSourceProperties.getWriter();
        DataSource writeDataSource = createDataSource(writer.getUrl());

        Map<Object, Object> dataSourceMap = new HashMap<>();
        dataSourceMap.put(writer.getName(), writeDataSource);

        AuroraDataSourceProperties.Reader reader = auroraDataSourceProperties.getReader();
        dataSourceMap.put(reader.getName(), createDataSource(reader.getUrl()));

        auroraRoutingDataSource.setDefaultTargetDataSource(writeDataSource);
        auroraRoutingDataSource.setTargetDataSources(dataSourceMap);
        auroraRoutingDataSource.afterPropertiesSet();
        return new LazyConnectionDataSourceProxy(auroraRoutingDataSource);
    }

    private DataSource createDataSource(String url) {
        HikariDataSource hikariDataSource = new HikariDataSource();
        hikariDataSource.setDriverClassName(auroraDataSourceProperties.getDriverClassName());
        hikariDataSource.setUsername(auroraDataSourceProperties.getUsername());
        hikariDataSource.setPassword(auroraDataSourceProperties.getPassword());
        hikariDataSource.setJdbcUrl(url);

        return hikariDataSource;
    }
}

 

  • @Transactional(readOnly = true), @Transactional
  • 해당 애노테이션으로 reader와 writer 구분

3. application.yml

spring:
  datasource:
    aurora:
      username: ${rds.user}
      password: ${rds.password}
      driverClassName: org.mariadb.jdbc.Driver
      writer:
        name: master
        url: jdbc:mariadb://${rds.writer.host}:${rds.port}/${rds.db.name}?serverTimezone=Asia/Seoul&useSSL=false&allowPublicKeyRetrieval=true
      reader:
        name: slave
        url: jdbc:mariadb://${rds.reader.host}:${rds.port}/${rds.db.name}?serverTimezone=Asia/Seoul&useSSL=false&allowPublicKeyRetrieval=true