Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/applicationContext.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
<bean id="userService" class="springbook.user.service.UserService">
<property name="userDao" ref="userDao" />
<property name="userLevelUpgradePolicy" ref="userLevelPolicy"/>
<property name="transactionManager" ref="transactionManager"/>
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
Comment on lines +22 to +23
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

구현체를 바꾸고 싶으면 여기에서 클래스를 바꿔주면 된다.
ex) JTA 를 사용하고 싶은 경우

<bean id="transactionManager"
      class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!-- ...빈 주입 -->
</bean>

이런식으로 바꾸면 된당.

<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="userDao" class="springbook.user.dao.UserDaoJdbc">
<property name="dataSource" ref="dataSource"/> <!--아직 dao의 get()메서드가 dataSource를 사용하므로 지우지 않음-->
Expand Down
23 changes: 12 additions & 11 deletions src/springbook/user/dao/UserDaoJdbc.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package springbook.user.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
Expand All @@ -8,13 +14,6 @@
import springbook.user.domain.Level;
import springbook.user.domain.User;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

public class UserDaoJdbc implements UserDao {
private JdbcTemplate jdbcTemplate;

Expand All @@ -39,8 +38,10 @@ public User mapRow(ResultSet rs, int rowNum) throws SQLException {


public void add(final User user) {
this.jdbcTemplate.update("insert into users(id, name, password, level, login, recommend) values(?, ? , ?,?,?, ?)",
user.getId(), user.getName(), user.getPassword(), user.getLevel().intValue(), user.getLogin(), user.getRecommend());
this.jdbcTemplate.update(
"insert into users(id, name, password, level, login, recommend, email) values(?, ?, ?, ?, ?, ?, ?)",
user.getId(), user.getName(), user.getPassword(), user.getLevel().intValue(), user.getLogin(),
user.getRecommend(), user.getEmail());
}


Expand All @@ -56,8 +57,8 @@ public List<User> getAll() {
public void update(User user) {
this.jdbcTemplate.update(
"update users set name = ?, password = ?, level = ?, login = ?," +
"recommend = ? where id = ?", user.getName(), user.getPassword(),
user.getLevel().intValue(), user.getLogin(), user.getRecommend(),
"recommend = ?, email = ? where id = ?", user.getName(), user.getPassword(),
user.getLevel().intValue(), user.getLogin(), user.getRecommend(), user.getEmail(),
user.getId());
}

Expand Down
25 changes: 12 additions & 13 deletions src/springbook/user/dao/UserDaoTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package springbook.user.dao;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

import java.sql.SQLException;
import java.util.List;
import javax.sql.DataSource;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
Expand All @@ -14,13 +20,6 @@
import springbook.user.domain.Level;
import springbook.user.domain.User;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.List;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "/test-applicationContext.xml")
public class UserDaoTest {
Expand All @@ -35,13 +34,13 @@ public class UserDaoTest {

@Before
public void setUp() {
this.user1 = new User("aaaa", "운가용", "sleep", Level.BASIC, 1, 0);
this.user2 = new User("aaab", "로지지징", "gohome", Level.SILVER, 55, 10);
this.user3 = new User("aaac", "메롱", "iiii", Level.GOLD, 100, 40);
this.user1 = new User("aaaa", "운가용", "sleep", "user1@email.com", Level.BASIC, 1, 0);
this.user2 = new User("aaab", "로지지징", "gohome", "user2@email.com", Level.SILVER, 55, 10);
this.user3 = new User("aaac", "메롱", "iiii", "user3@eamil.com", Level.GOLD, 100, 40);
}

@Test // Junit에게 테스트용 메소드임을 알려준다.
public void addAndGet() throws SQLException, ClassNotFoundException { // JUnit 테스트 메소드는 반드시 public으로 선언돼야한다.
public void addAndGet() { // JUnit 테스트 메소드는 반드시 public으로 선언돼야한다.
dao.deleteAll();
assertThat(dao.getCount(), is(0));
dao.add(user1);
Expand Down Expand Up @@ -139,8 +138,7 @@ public void sqlExceptionTranslate() {
}

@Test
public void update()
{
public void update() {
dao.deleteAll();
dao.add(user1);

Expand All @@ -155,6 +153,7 @@ public void update()
user1.setLevel(Level.GOLD);
user1.setLogin(1000);
user1.setRecommend(999);
user1.setEmail("hihi@email.com");
dao.update(user1);

User user1update = dao.get(user1.getId());
Expand Down
13 changes: 11 additions & 2 deletions src/springbook/user/domain/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,24 @@ public class User {
String id;
String name;
String password;
String email;
Level level;
int login;
int recommend;

public User() {
}

public User(String id, String name, String password, Level level, int login, int recommend) {
public User(String id, String name, String password, String email, Level level, int login, int recommend) {
this.id = id;
this.name = name;
this.password = password;
this.email = email;
this.level = level;
this.login = login;
this.recommend = recommend;
}


public String getId() {
return id;
}
Expand Down Expand Up @@ -69,6 +70,14 @@ public void setRecommend(int recommend) {
this.recommend = recommend;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public void upgradeLevel() {
Level nextLevel = this.level.nextLevel();
if (nextLevel == null) {
Expand Down
34 changes: 27 additions & 7 deletions src/springbook/user/service/UserService.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
package springbook.user.service;

import java.util.List;
import javax.sql.DataSource;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import springbook.user.dao.UserDao;
import springbook.user.domain.Level;
import springbook.user.domain.User;

import java.util.List;

public class UserService {
UserDao userDao;
UserLevelUpgradePolicy userLevelUpgradePolicy;
PlatformTransactionManager transactionManager;

public void setUserDao(UserDao userDao) {
this.userDao = userDao;
Expand All @@ -18,6 +23,10 @@ public void setUserLevelUpgradePolicy(UserLevelUpgradePolicy userLevelUpgradePol
this.userLevelUpgradePolicy = userLevelUpgradePolicy;
}

public void setTransactionManager(PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}

public void add(User user) {
if (user.getLevel() == null) {
user.setLevel(Level.BASIC);
Expand All @@ -26,12 +35,23 @@ public void add(User user) {
}

public void upgradeLevels() {
List<User> users = userDao.getAll();
for (User user : users) {
if (userLevelUpgradePolicy.canUpgradeLevel(user)) {
userLevelUpgradePolicy.upgradeLevel(user);
userDao.update(user);
TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

transaction을 시작한다는 의미라고 생각하자.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

트랜잭션이 TransactionStatus 타입의 변수에 저장된다.

try {
List<User> users = userDao.getAll();
for (User user : users) {
upgradeLevel(user);
}
transactionManager.commit(status);
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

트랜잭션에 대한 조작이 필요할 때 PlatformTransactionManager의 메서드에 트랜잭션을 인자로 전달해주면 된당.

} catch (Exception e) {
transactionManager.rollback(status);
throw e;
}
}

protected void upgradeLevel(User user) {
if (userLevelUpgradePolicy.canUpgradeLevel(user)) {
userLevelUpgradePolicy.upgradeLevel(user);
userDao.update(user);
}
}
}
76 changes: 61 additions & 15 deletions src/springbook/user/service/UserServiceTest.java
Original file line number Diff line number Diff line change
@@ -1,49 +1,77 @@
package springbook.user.service;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static springbook.user.service.UserLevelUpgradePolicyImpl.MIN_LOGCOUNT_FOR_SILVER;
import static springbook.user.service.UserLevelUpgradePolicyImpl.MIN_RECCOMENT_FOR_GOLD;

import java.util.Arrays;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.PlatformTransactionManager;
import springbook.user.dao.UserDao;
import springbook.user.domain.Level;
import springbook.user.domain.User;

import java.util.Arrays;
import java.util.List;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static springbook.user.service.UserLevelUpgradePolicyImpl.MIN_LOGCOUNT_FOR_SILVER;
import static springbook.user.service.UserLevelUpgradePolicyImpl.MIN_RECCOMENT_FOR_GOLD;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "/test-applicationContext.xml")
public class UserServiceTest {
static class TestUserService extends UserService {
private String id;

private TestUserService(String id) {
this.id = id;
}

@Override
protected void upgradeLevel(User user) {
if (user.getId().equals(this.id)) {
throw new TestUserServiceException();
}
super.upgradeLevel(user);
}
Comment on lines +33 to +38
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UserService에서 protected 접근자로 수정한 덕분에 upgradeLevel을 원하는대로 변경할 수 있게 되었다.

}

static class TestUserServiceException extends RuntimeException {
}

@Autowired
UserService userService;

@Autowired
UserDao userDao;

@Autowired
UserLevelUpgradePolicy userLevelUpgradePolicy;

@Autowired
PlatformTransactionManager transactionManager;

List<User> users;

@Before
public void setUp() {
users = Arrays.asList(
new User("kayoung", "윤가영", "p1", Level.BASIC, MIN_LOGCOUNT_FOR_SILVER - 1, 0),
new User("haneul", "이하늘", "p2", Level.BASIC, MIN_LOGCOUNT_FOR_SILVER, 0),
new User("oieuoa", "윤실버", "p3", Level.SILVER, 60, MIN_RECCOMENT_FOR_GOLD - 1),
new User("silversky", "스카이", "p4", Level.SILVER, 60, MIN_RECCOMENT_FOR_GOLD),
new User("blue", "교수님", "p5", Level.GOLD, 100, Integer.MAX_VALUE)
new User("kayoung", "윤가영", "p1", "kayoung@email.com", Level.BASIC, MIN_LOGCOUNT_FOR_SILVER - 1, 0),
new User("haneul", "이하늘", "p2", "haneul@email.com", Level.BASIC, MIN_LOGCOUNT_FOR_SILVER, 0),
new User("oieuoa", "윤실버", "p3", "oieuoa@email.com", Level.SILVER, 60, MIN_RECCOMENT_FOR_GOLD - 1),
new User("silversky", "스카이", "p4", "silverskey@email.com", Level.SILVER, 60, MIN_RECCOMENT_FOR_GOLD),
new User("blue", "교수님", "p5", "blue@email.com", Level.GOLD, 100, Integer.MAX_VALUE)
);
}

@Test
public void upgradeLevels() {
public void upgradeLevels() throws Exception {
userDao.deleteAll();
for (User user : users) userDao.add(user);
for (User user : users) {
userDao.add(user);
}

userService.upgradeLevels();

Expand Down Expand Up @@ -82,4 +110,22 @@ private void checkLevelUpgraded(User user, Boolean upgraded) {
}
}

@Test
public void upgradeAllOrNothing() {
// user fixture 사용
TestUserService testUserService = new TestUserService(users.get(3).getId());
testUserService.setUserDao(this.userDao); // userDao를 수동 DI해줌
testUserService.setUserLevelUpgradePolicy(this.userLevelUpgradePolicy);
testUserService.setTransactionManager(transactionManager);
userDao.deleteAll();
for (User user : users) {
userDao.add(user);
}
try {
testUserService.upgradeLevels();
fail("TetUserSericeException expected");
} catch (TestUserServiceException e) {
}
checkLevelUpgraded(users.get(1), false);
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p353. 테스트는 실패한다.
모든 사용자의 레벨을 업그레이드하는 작업인 upgradeLevels() 메소드가 하나의 트랜잭션 안에서 동작하지 않았기 때문이다.
트랜잭션이란 더 이상 나눌 수 없는 단위 작업을 말한다. (트랜잭션의 핵심 속성인 원자성)

}
}
5 changes: 5 additions & 0 deletions src/test-applicationContext.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
<bean id="userService" class="springbook.user.service.UserService">
<property name="userDao" ref="userDao" />
<property name="userLevelUpgradePolicy" ref="userLevelPolicy"/>
<property name="transactionManager" ref="transactionManager"/>
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="userDao" class="springbook.user.dao.UserDaoJdbc">
<property name="dataSource" ref="dataSource"/>
Expand Down