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: 2 additions & 3 deletions src/main/java/com/ch5/domain/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,9 @@ public User() {}

public void upgradeLevel() {
Level nextLevel = this.level.nextLevel();
if(nextLevel == null) {
if (nextLevel == null) {
throw new IllegalStateException(this.level + "은 업그레이드가 불가능합니다.");
}
else {
} else {
this.level = nextLevel;
}
}
Expand Down
33 changes: 33 additions & 0 deletions src/main/java/com/ch6/dao/DaoFactory6.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.ch6.dao;


import com.ch6.service.UserService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;

import javax.sql.DataSource;

// 애플리케이션 컨텍스트 또는 빈 팩토리가 사용할 설정 클래스임을 명시하는 어노테이션
@Configuration
public class DaoFactory6 {
// 오브젝트 생성을 담당하는 IoC용 메소드임을 명시하는 어노테이션
// 해당 메소드 이름이 빈의 이름이 된다.
@Bean
public DataSource connectionMaker() {
SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setDriverClass(com.mysql.jdbc.Driver.class);
dataSource.setUrl("jdbc:mysql://localhost:53306/springbook");
dataSource.setUsername("spring");
dataSource.setPassword("book");
return dataSource;
}

// 빈의 이름은 클래스의 구현 인터페이스 이름을 따르는 것이 좋다.
// -> 그래야 나중에 구현 클래스를 바꿔도 혼란이 없기 때문
@Bean
public UserDao userDao() { return new UserDaoJdbc(connectionMaker()); }

@Bean
public UserService userService() { return new UserService(); }
}
21 changes: 21 additions & 0 deletions src/main/java/com/ch6/dao/UserDao.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.ch6.dao;


import com.ch6.domain.User;

import java.util.List;

// 데이터 엑세스 기술(JPA, Hibernate, JDO ..)에 따른 독립적인 UerDao를 만들기 위해 인터페이스와 구현 분리
public interface UserDao {
/*
데이터 엑세스 기술마다 던지는 예외가 다르므로 예외에 따라 메소드의 선언이 달라진다.
다행히도 JDO, Hibernate, JPA는 SQLException같은 체크 예외 대신 런타임 예외를 사용하기 때문에 메소드에 throws 선언을 해주지 않아도 된다.
JDBC에서 SQLException을 런타임 예외로 포장해 던진다면 예외에 따라 메소드 선언을 다르게 할 필요없이 아래와 같이 선언할 수 있게 된다.
*/
void add(User user);
User get(String id);
List<User> getAll();
void deleteAll();
int getCount();
void update(User user);
}
83 changes: 83 additions & 0 deletions src/main/java/com/ch6/dao/UserDaoJdbc.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package com.ch6.dao;

import com.ch6.domain.Level;
import com.ch6.domain.User;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

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

public class UserDaoJdbc implements UserDao {
private JdbcTemplate jdbcTemplate;

public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}

public UserDaoJdbc(DataSource dataSource) {
setDataSource(dataSource);
}

private RowMapper<User> userMapper =
new RowMapper<User>() {
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setId(rs.getString("id"));
user.setName(rs.getString("name"));
user.setPassword(rs.getString("password"));
user.setLevel(Level.valueOf(rs.getInt("level")));
user.setLogin(rs.getInt("login"));
user.setRecommend(rs.getInt("recommend"));
return user;
}
};

@Override
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()
);
}

public User get(String id) {
return this.jdbcTemplate.queryForObject("select * from users where id = ?",
new Object[] {id}, // SQL에 바인딩할 파라미터 값, 가변인자 대신 배열을 사용한다.
this.userMapper
);
}


public void deleteAll() {
this.jdbcTemplate.update("delete from users");
}

public int getCount() {
return this.jdbcTemplate.queryForObject("select count(*) from users", Integer.class);
}

public List<User> getAll() {
return this.jdbcTemplate.query("select * from users order by id",
this.userMapper);
}

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(),
user.getId()
);
}
}
32 changes: 32 additions & 0 deletions src/main/java/com/ch6/domain/Level.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.ch6.domain;

public enum Level {
GOLD(3, null),
SILVER(2, GOLD),
BASIC(1, SILVER);

private final int value;
private final Level next;

Level(int value, Level next) {
this.value = value;
this.next = next;
}

public int intValue() {
return value;
}

public Level nextLevel() {
return this.next;
}

public static Level valueOf(int value) {
switch (value) {
case 1: return BASIC;
case 2: return SILVER;
case 3: return GOLD;
default: throw new AssertionError("Unknown value: " + value);
}
}
}
78 changes: 78 additions & 0 deletions src/main/java/com/ch6/domain/User.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.ch6.domain;

public class User {
String id;
String name;
String password;
Level level;
int login; // 로그인 수
int recommend; // 추천 수

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public Level getLevel() {
return level;
}

public void setLevel(Level level) {
this.level = level;
}

public int getLogin() {
return login;
}

public void setLogin(int login) {
this.login = login;
}

public int getRecommend() {
return recommend;
}

public void setRecommend(int recommend) {
this.recommend = recommend;
}

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

public User() {}

public void upgradeLevel() {
Level nextLevel = this.level.nextLevel();
if (nextLevel == null) {
throw new IllegalStateException(this.level + "은 업그레이드가 불가능합니다.");
} else {
this.level = nextLevel;
}
}
}
48 changes: 48 additions & 0 deletions src/main/java/com/ch6/service/UserService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.ch6.service;

import com.ch6.dao.UserDao;
import com.ch6.domain.Level;
import com.ch6.domain.User;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

public class UserService {
public static final int MIN_LOGCOUNT_FOR_SILVER = 50;
public static final int MIN_RECCOMEND_FOR_GOLD = 30;
@Autowired
UserDao userDao;

public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}

public void upgradeLevels() {
List<User> users = userDao.getAll();
for(User user : users) {
if (canUpgradeLevel(user)) {
upgradeLevel(user);
}
}
}

protected void upgradeLevel(User user) {
user.upgradeLevel();
userDao.update(user);
}

public boolean canUpgradeLevel(User user) {
Level currentLevel = user.getLevel();
switch(currentLevel) {
case BASIC: return (user.getLogin() >= MIN_LOGCOUNT_FOR_SILVER);
case SILVER: return (user.getRecommend() >= MIN_RECCOMEND_FOR_GOLD);
case GOLD: return false;
default: throw new IllegalArgumentException("Unknown Level: " + currentLevel);
}
}

public void add(User user) {
if (user.getLevel() == null) user.setLevel(Level.BASIC);
userDao.add(user);
}
}
Loading