diff --git a/jdbc/src/main/java/com/example/jdbc/repository/ex/MyDuplicateKeyException.java b/jdbc/src/main/java/com/example/jdbc/repository/ex/MyDuplicateKeyException.java new file mode 100644 index 00000000..da9d75fc --- /dev/null +++ b/jdbc/src/main/java/com/example/jdbc/repository/ex/MyDuplicateKeyException.java @@ -0,0 +1,19 @@ +package com.example.jdbc.repository.ex; + +public class MyDuplicateKeyException extends MyDbException { + + public MyDuplicateKeyException() { + } + + public MyDuplicateKeyException(String message) { + super(message); + } + + public MyDuplicateKeyException(String message, Throwable cause) { + super(message, cause); + } + + public MyDuplicateKeyException(Throwable cause) { + super(cause); + } +} diff --git a/jdbc/src/test/java/com/example/jdbc/exception/translator/ExTranslatorV1Test.java b/jdbc/src/test/java/com/example/jdbc/exception/translator/ExTranslatorV1Test.java new file mode 100644 index 00000000..b6c6ab81 --- /dev/null +++ b/jdbc/src/test/java/com/example/jdbc/exception/translator/ExTranslatorV1Test.java @@ -0,0 +1,95 @@ +package com.example.jdbc.exception.translator; + +import com.example.jdbc.domain.Member; +import com.example.jdbc.repository.ex.MyDbException; +import com.example.jdbc.repository.ex.MyDuplicateKeyException; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.jdbc.support.JdbcUtils; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.Random; + +import static com.example.jdbc.connection.ConnectionConst.*; + +@Slf4j +public class ExTranslatorV1Test { + + Repository repository; + Service service; + + @BeforeEach + void init() { + DriverManagerDataSource dataSource = new DriverManagerDataSource(URL, USERNAME, PASSWORD); + Repository repository = new Repository(dataSource); + service = new Service(repository); + } + + @Test + void duplicateKeySave() { + service.create("myId"); + service.create("myId"); + } + + @Slf4j + @RequiredArgsConstructor + static class Service { + private final Repository repository; + + public void create(String memberId) { + try { + repository.save(new Member(memberId, 0)); + log.info("saveId={}", memberId); + } catch (MyDuplicateKeyException e) { + log.info("키 중복, 복구 시도"); + String retryId = generateNewId(memberId); + log.info("retryId={}", retryId); + repository.save(new Member(retryId, 0)); + } catch (MyDbException e) { + log.info("데이터 접근 계층 예외", e); + throw e; + } + } + + private String generateNewId(String memberId) { + return memberId + new Random().nextInt(10000); + } + } + + @RequiredArgsConstructor + static class Repository { + private final DataSource dataSource; + + public Member save(Member member) { + String sql = "insert into member(member_id, money) values(?, ?)"; + + Connection con = null; + PreparedStatement pstmt = null; + + try { + con = dataSource.getConnection(); + pstmt = con.prepareStatement(sql); + pstmt.setString(1, member.getMemberId()); + pstmt.setInt(2, member.getMoney()); + pstmt.executeUpdate(); + return member; + } catch (SQLException e) { + // h2 db + if (e.getErrorCode() == 23505) { + throw new MyDuplicateKeyException(e); + } + + throw new MyDbException(e); + } finally { + JdbcUtils.closeStatement(pstmt); + JdbcUtils.closeConnection(con); + } + } + } +}