Skip to content

Commit

Permalink
JDBC 라이브러리 구현하기
Browse files Browse the repository at this point in the history
  • Loading branch information
kang-hyungu committed Sep 29, 2022
1 parent 2903f56 commit 2832af7
Show file tree
Hide file tree
Showing 12 changed files with 302 additions and 14 deletions.
3 changes: 3 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ dependencies {
implementation project(':mvc')
implementation project(':jdbc')

implementation 'org.springframework:spring-tx:5.3.23'
implementation 'org.springframework:spring-jdbc:5.3.23'

implementation 'org.apache.tomcat.embed:tomcat-embed-core:10.1.0-M16'
implementation 'org.apache.tomcat.embed:tomcat-embed-jasper:10.1.0-M16'
implementation 'ch.qos.logback:logback-classic:1.2.10'
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/java/com/techcourse/dao/UserDao.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.techcourse.dao;

import com.techcourse.domain.User;
import nextstep.jdbc.JdbcTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -21,6 +22,10 @@ public UserDao(final DataSource dataSource) {
this.dataSource = dataSource;
}

public UserDao(final JdbcTemplate jdbcTemplate) {
this.dataSource = null;
}

public void insert(final User user) {
final var sql = "insert into users (account, password, email) values (?, ?, ?)";

Expand Down
62 changes: 62 additions & 0 deletions app/src/main/java/com/techcourse/dao/UserHistoryDao.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.techcourse.dao;

import com.techcourse.domain.UserHistory;
import nextstep.jdbc.JdbcTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class UserHistoryDao {

private static final Logger log = LoggerFactory.getLogger(UserHistoryDao.class);

private final DataSource dataSource;

public UserHistoryDao(final DataSource dataSource) {
this.dataSource = dataSource;
}

public UserHistoryDao(final JdbcTemplate jdbcTemplate) {
this.dataSource = null;
}

public void log(final UserHistory userHistory) {
final var sql = "insert into user_history (user_id, account, password, email, created_at, created_by) values (?, ?, ?, ?, ?, ?)";

Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = dataSource.getConnection();
pstmt = conn.prepareStatement(sql);

log.debug("query : {}", sql);

pstmt.setLong(1, userHistory.getUserId());
pstmt.setString(2, userHistory.getAccount());
pstmt.setString(3, userHistory.getPassword());
pstmt.setString(4, userHistory.getEmail());
pstmt.setObject(5, userHistory.getCreatedAt());
pstmt.setString(6, userHistory.getCreateBy());
pstmt.executeUpdate();
} catch (SQLException e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
} finally {
try {
if (pstmt != null) {
pstmt.close();
}
} catch (SQLException ignored) {}

try {
if (conn != null) {
conn.close();
}
} catch (SQLException ignored) {}
}
}
}
59 changes: 59 additions & 0 deletions app/src/main/java/com/techcourse/domain/UserHistory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.techcourse.domain;

import java.time.LocalDateTime;

public class UserHistory {

private Long id;

private final long userId;
private final String account;
private final String password;
private final String email;

private final LocalDateTime createdAt;

private final String createBy;

public UserHistory(final User user, final String createBy) {
this(null, user.getId(), user.getAccount(), user.getPassword(), user.getEmail(), createBy);
}

public UserHistory(final Long id, final long userId, final String account, final String password, final String email, final String createBy) {
this.id = id;
this.userId = userId;
this.account = account;
this.password = password;
this.email = email;
this.createdAt = LocalDateTime.now();
this.createBy = createBy;
}

public Long getId() {
return id;
}

public long getUserId() {
return userId;
}

public String getAccount() {
return account;
}

public String getPassword() {
return password;
}

public String getEmail() {
return email;
}

public LocalDateTime getCreatedAt() {
return createdAt;
}

public String getCreateBy() {
return createBy;
}
}
32 changes: 32 additions & 0 deletions app/src/main/java/com/techcourse/service/UserService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.techcourse.service;

import com.techcourse.dao.UserDao;
import com.techcourse.dao.UserHistoryDao;
import com.techcourse.domain.User;
import com.techcourse.domain.UserHistory;

public class UserService {

private final UserDao userDao;
private final UserHistoryDao userHistoryDao;

public UserService(final UserDao userDao, final UserHistoryDao userHistoryDao) {
this.userDao = userDao;
this.userHistoryDao = userHistoryDao;
}

public User findById(final long id) {
return userDao.findById(id);
}

public void insert(final User user) {
userDao.insert(user);
}

public void changePassword(final long id, final String newPassword, final String createBy) {
final var user = findById(id);
user.changePassword(newPassword);
userDao.update(user);
userHistoryDao.log(new UserHistory(user, createBy));
}
}
11 changes: 11 additions & 0 deletions app/src/main/resources/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,14 @@ create table if not exists users (
email varchar(100) not null,
primary key(id)
);

create table if not exists user_history (
id bigint auto_increment,
user_id bigint not null,
account varchar(100) not null,
password varchar(100) not null,
email varchar(100) not null,
created_at datetime not null,
created_by varchar(100) not null,
primary key(id)
);
24 changes: 11 additions & 13 deletions app/src/test/java/com/techcourse/dao/UserDaoTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

class UserDaoTest {
Expand All @@ -19,52 +17,52 @@ void setup() {
DatabasePopulatorUtils.execute(DataSourceConfig.getInstance());

userDao = new UserDao(DataSourceConfig.getInstance());
final User user = new User("gugu", "password", "[email protected]");
final var user = new User("gugu", "password", "[email protected]");
userDao.insert(user);
}

@Test
void findAll() {
final List<User> users = userDao.findAll();
final var users = userDao.findAll();

assertThat(users).isNotEmpty();
}

@Test
void findById() {
final User user = userDao.findById(1L);
final var user = userDao.findById(1L);

assertThat(user.getAccount()).isEqualTo("gugu");
}

@Test
void findByAccount() {
final String account = "gugu";
final User user = userDao.findByAccount(account);
final var account = "gugu";
final var user = userDao.findByAccount(account);

assertThat(user.getAccount()).isEqualTo(account);
}

@Test
void insert() {
final String account = "insert-gugu";
final User user = new User(account, "password", "[email protected]");
final var account = "insert-gugu";
final var user = new User(account, "password", "[email protected]");
userDao.insert(user);

final User actual = userDao.findById(2L);
final var actual = userDao.findById(2L);

assertThat(actual.getAccount()).isEqualTo(account);
}

@Test
void update() {
final String newPassword = "password99";
final User user = userDao.findById(1L);
final var newPassword = "password99";
final var user = userDao.findById(1L);
user.changePassword(newPassword);

userDao.update(user);

final User actual = userDao.findById(1L);
final var actual = userDao.findById(1L);

assertThat(actual.getPassword()).isEqualTo(newPassword);
}
Expand Down
18 changes: 18 additions & 0 deletions app/src/test/java/com/techcourse/service/MockUserHistoryDao.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.techcourse.service;

import com.techcourse.dao.UserHistoryDao;
import com.techcourse.domain.UserHistory;
import nextstep.jdbc.DataAccessException;
import nextstep.jdbc.JdbcTemplate;

public class MockUserHistoryDao extends UserHistoryDao {

public MockUserHistoryDao(final JdbcTemplate jdbcTemplate) {
super(jdbcTemplate);
}

@Override
public void log(final UserHistory userHistory) {
throw new DataAccessException();
}
}
63 changes: 63 additions & 0 deletions app/src/test/java/com/techcourse/service/UserServiceTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.techcourse.service;

import com.techcourse.config.DataSourceConfig;
import com.techcourse.dao.UserDao;
import com.techcourse.dao.UserHistoryDao;
import com.techcourse.domain.User;
import com.techcourse.support.jdbc.init.DatabasePopulatorUtils;
import nextstep.jdbc.DataAccessException;
import nextstep.jdbc.JdbcTemplate;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;

@Disabled
class UserServiceTest {

private JdbcTemplate jdbcTemplate;
private UserDao userDao;

@BeforeEach
void setUp() {
this.jdbcTemplate = new JdbcTemplate(DataSourceConfig.getInstance());
this.userDao = new UserDao(jdbcTemplate);

DatabasePopulatorUtils.execute(DataSourceConfig.getInstance());
final var user = new User("gugu", "password", "[email protected]");
userDao.insert(user);
}

@Test
void testChangePassword() {
final var userHistoryDao = new UserHistoryDao(jdbcTemplate);
final var userService = new UserService(userDao, userHistoryDao);

final var newPassword = "qqqqq";
final var createBy = "gugu";
userService.changePassword(1L, newPassword, createBy);

final var actual = userService.findById(1L);

assertThat(actual.getPassword()).isEqualTo(newPassword);
}

@Test
void testTransactionRollback() {
// 트랜잭션 롤백 테스트를 위해 mock으로 교체
final var userHistoryDao = new MockUserHistoryDao(jdbcTemplate);
final var userService = new UserService(userDao, userHistoryDao);

final var newPassword = "newPassword";
final var createBy = "gugu";
// 트랜잭션이 정상 동작하는지 확인하기 위해 의도적으로 MockUserHistoryDao에서 예외를 발생시킨다.
assertThrows(DataAccessException.class,
() -> userService.changePassword(1L, newPassword, createBy));

final var actual = userService.findById(1L);

assertThat(actual.getPassword()).isNotEqualTo(newPassword);
}
}
5 changes: 4 additions & 1 deletion jdbc/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ repositories {
}

dependencies {
implementation 'org.springframework:spring-tx:5.3.23'
implementation 'org.springframework:spring-jdbc:5.3.23'

implementation 'org.apache.commons:commons-lang3:3.12.0'
implementation 'ch.qos.logback:logback-classic:1.2.10'

Expand All @@ -18,6 +21,6 @@ dependencies {
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
}

tasks.named('test') {
test {
useJUnitPlatform()
}
Loading

0 comments on commit 2832af7

Please sign in to comment.