mini-pms 42
42. 비즈니스 로직 분리하기 : 서비스 객체의 도입
1단계 - 프로젝트 삭제 Command 객체에서 업무 코드를 분리한다.
커맨드 객체에서 비즈니스 로직을 분리하여 서비스 객체에 옮긴다.
- com.eomcs.pms.service.ProjectService 인터페이스 생성
- 서비스 객체의 메서드 명은 보통 업무 관련 용어를 사용한다.
- DAO 객체의 메서드 명은 데이터 관련 용어를 사용한다.
delete()메서드 선언
public interface ProjectService {
int delete(int projectNo) throws Exception;
}
- com.eomcs.pms.service.DefaultProjectService 클래스 생성
delete()메서드 구현ProjectDeleteCommand에서 비즈니스 로직과 관련된 코드를 가져온다.
public class DefaultProjectService implements ProjectService {
ProjectDao projectDao;
TaskDao taskDao;
SqlSessionFactoryProxy factoryProxy;
public DefaultProjectService(
ProjectDao projectDao,
TaskDao taskDao,
SqlSessionFactoryProxy factoryProxy) {
this.projectDao = projectDao;
this.taskDao = taskDao;
this.factoryProxy = factoryProxy;
}
@Override
public int delete(int no) throws Exception {
try {
// 트랜잭션 시작
factoryProxy.startTransaction();
// 프로젝트에 소속된 모든 작업 삭제하기
taskDao.deleteByProjectNo(no);
// 프로젝트 삭제하기
int count = projectDao.delete(no);
// 트랜잭션 작업이 성공하였다면 커밋
factoryProxy.commit();
return count;
} catch (Exception e) {
// 트랜잭션 작업 도중에 예외가 발생하면 롤백
factoryProxy.rollback();
// 서비스 객체에서 발생한 예외는 호출자에게 전달한다.
throw e;
} finally {
// 트랜잭션 종료
factoryProxy.endTransaction();
}
}
}
- com.eomcs.pms.handler.ProjectDeleteCommand 클래스 변경
ProjectService구현체를 사용하여 프로젝트 삭제 처리
public class ProjectDeleteCommand implements Command {
ProjectService projectService;
public ProjectDeleteCommand(ProjectService projectService) {
this.projectService = projectService;
}
@Override
public void execute(Map<String,Object> context) {
System.out.println("[프로젝트 삭제]");
int no = Prompt.inputInt("번호? ");
String response = Prompt.inputString("정말 삭제하시겠습니까?(y/N) ");
if (!response.equalsIgnoreCase("y")) {
System.out.println("프로젝트 삭제를 취소하였습니다.");
return;
}
try {
if (projectService.delete(no) == 0) {
System.out.println("해당 번호의 프로젝트가 존재하지 않습니다.");
return;
}
System.out.println("프로젝트를 삭제하였습니다.");
} catch (Exception e) {
System.out.println("프로젝트 삭제 중 오류 발생!");
e.printStackTrace();
}
}
}
2단계 - 프로젝트 삭제 DAO 객체에서 업무 코드를 분리한다.
DAO 객체에서 비즈니스 로직을 분리하여 서비스 객체에 옮긴다.
- com.eomcs.pms.dao.ProjectDao 인터페이스 변경
deleteMembers()메서드 선언 추가
public interface ProjectDao {
int insert(Project project) throws Exception;
int delete(int no) throws Exception;
Project findByNo(int no) throws Exception;
List<Project> findAll() throws Exception;
List<Project> findByKeyword(String item, String keyword) throws Exception;
List<Project> findByDetailKeyword(Map<String,Object> keywords) throws Exception;
int update(Project project) throws Exception;
int deleteMembers(int PorjectNo) throws Exception;
}
- com.eomcs.pms.dao.mariadb.ProjectDaoImpl 클래스 변경
delete()메서드에서 멤버 삭제 관련 코드를 별도의 메서드deleteMembers()로 분리한다.
public class ProjectDaoImpl implements com.eomcs.pms.dao.ProjectDao {
.
.
.
@Override
public int delete(int no) throws Exception {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
// 프로젝트를 삭제한다.
return sqlSession.delete("ProjectDao.delete", no);
}
}
.
.
.
@Override
public int deleteMembers(int projectNo) throws Exception {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
// 프로젝트에 소속된 모든 멤버를 삭제한다.
return sqlSession.delete("ProjectDao.deleteMembers", projectNo);
}
}
}
- com.eomcs.pms.service.DefaultProjectService 클래스 변경
delete()메서드 변경- 프로젝트 멤버를 삭제하는
deleteMembers()를 호출한다.
- 프로젝트 멤버를 삭제하는
public class DefaultProjectService implements ProjectService {
.
.
.
@Override
public int delete(int no) throws Exception {
try {
// 트랜잭션 시작
factoryProxy.startTransaction();
// 프로젝트에 소속된 모든 작업 삭제하기
taskDao.deleteByProjectNo(no);
// 프로젝트에 소속된 모든 멤버 삭제하기
projectDao.deleteMembers(no);
// 프로젝트 삭제하기
int count = projectDao.delete(no);
// 트랜잭션 작업이 성공하였다면 커밋
factoryProxy.commit();
return count;
} catch (Exception e) {
// 트랜잭션 작업 도중에 예외가 발생하면 롤백
factoryProxy.rollback();
// 서비스 객체에서 발생한 예외는 호출자에게 전달한다.
throw e;
} finally {
// 트랜잭션 종료
factoryProxy.endTransaction();
}
}
}
3단계 - 프로젝트 등록 커맨드 객체에서 비즈니스 로직을 분리한다.
- com.eomcs.pms.dao.ProjectDao 인터페이스 변경
insertMembers()메서드 선언 추가
public interface ProjectDao {
int insert(Project project) throws Exception;
int delete(int no) throws Exception;
Project findByNo(int no) throws Exception;
List<Project> findAll() throws Exception;
List<Project> findByKeyword(String item, String keyword) throws Exception;
List<Project> findByDetailKeyword(Map<String,Object> keywords) throws Exception;
int update(Project project) throws Exception;
int deleteMembers(int PorjectNo) throws Exception;
int insertMembers(Project project) throws Exception;
}
- com.eomcs.pms.dao.mariadb.ProjectDaoImpl 클래스 변경
insert()메서드에서 비즈니스 로직을 추출하여 별도의 메서드insertMembers()로 옮긴다.
public class ProjectDaoImpl implements com.eomcs.pms.dao.ProjectDao {
SqlSessionFactory sqlSessionFactory;
public ProjectDaoImpl(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
}
@Override
public int insert(Project project) throws Exception {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
// 프로젝트 정보 입력
return sqlSession.insert("ProjectDao.insert", project);
}
}
.
.
.
@Override
public int insertMembers(Project project) throws Exception {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
// 프로젝트의 멤버 정보 입력
return sqlSession.insert("ProjectDao.insertMembers", project);
}
}
}
- com.eomcs.pms.service.ProjectService 인터페이스 변경
add()메서드 선언
public interface ProjectService {
int delete(int projectNo) throws Exception;
int add(Project project) throws Exception;
}
- com.eomcs.pms.service.DefaultProjectService 클래스 변경
add()메서드 구현ProjectAddCommand에서 비즈니스 로직과 관련된 코드를 가져온다.
public class DefaultProjectService implements ProjectService {
.
.
.
@Override
public int add(Project project) throws Exception {
projectDao.insert(project);
return 1;
}
}
- project를 insert할 때 memberDao를 사용하기 때문에
- com.eomcs.pms.service.MemberService 인터페이스 생성
list()메서드 선언
- com.eomcs.pms.service.MemberService 인터페이스 생성
public interface MemberService {
// findByName 이기 때문에 이름을 리스트로 리턴한다.
List<Member> list(String name) throws Exception;
}
- com.eomcs.pms.service.DefaultMemberService 인터페이스 생성
list()메서드 구현
public interface MemberDao {
int insert(Member member) throws Exception;
int delete(int no) throws Exception;
Member findByNo(int no) throws Exception;
List<Member> findByName(String name) throws Exception;
List<Member> findAll() throws Exception;
int update(Member member) throws Exception;
List<Member> findByProjectNo(int projectNo) throws Exception;
Member findByEmailPassword(String email, String password) throws Exception;
}
public class DefaultMemberService implements MemberService {
MemberDao memberDao;
public DefaultMemberService(MemberDao memberDao) {
this.memberDao = memberDao;
}
@Override
public List<Member> list(String name) throws Exception {
return memberDao.findByName(name);
}
}
- com.eomcs.pms.service.MemberDao 인터페이스 변경
findByName()의 리턴 값을List객체로 변경한다.
public interface MemberDao {
int insert(Member member) throws Exception;
int delete(int no) throws Exception;
Member findByNo(int no) throws Exception;
List<Member> findByName(String name) throws Exception;
List<Member> findAll() throws Exception;
int update(Member member) throws Exception;
List<Member> findByProjectNo(int projectNo) throws Exception;
Member findByEmailPassword(String email, String password) throws Exception;
}
- com.eomcs.pms.service.MemberDaoImpl 클래스 변경
findByName()의 리턴 값을List객체로 변경한다.
public class MemberDaoImpl implements com.eomcs.pms.dao.MemberDao {
.
.
.
@Override
public List<Member> findByName(String name) throws Exception {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
return sqlSession.selectList("MemberDao.findByName", name);
}
}
.
.
.
}
- com.eomcs.pms.handler.ProjectAddCommand 클래스 변경
MemberService구현체를 사용하여 멤버 찾기ProjectService구현체를 사용하여 프로젝트 등록 처리
public class ProjectAddCommand implements Command {
ProjectService projectService;
MemberService memberService;
public ProjectAddCommand(ProjectService projectService, MemberService memberService) {
this.projectService = projectService;
this.memberService = memberService;
}
@Override
public void execute(Map<String,Object> context) {
System.out.println("[프로젝트 등록]");
try {
Project project = new Project();
project.setTitle(Prompt.inputString("프로젝트명? "));
project.setContent(Prompt.inputString("내용? "));
project.setStartDate(Prompt.inputDate("시작일? "));
project.setEndDate(Prompt.inputDate("종료일? "));
Member loginUser = (Member) context.get("loginUser");
project.setOwner(loginUser);
// 프로젝트에 참여할 회원 정보를 담는다.
List<Member> members = new ArrayList<>();
while (true) {
String name = Prompt.inputString("팀원?(완료: 빈 문자열) ");
if (name.length() == 0) {
break;
} else {
// Dao가 아니라 Service를 사용하게 한다.
List<Member> list = memberService.list(name);
if (list == null) {
System.out.println("등록된 회원이 아닙니다.");
continue;
}
// 리스트의 0번째에 담는다.
members.add(list.get(0));
}
}
// 사용자로부터 입력 받은 멤버 정보를 프로젝트에 저장한다.
project.setMembers(members);
// Dao가 아니라 Service를 사용하게 한다.
projectService.add(project);
System.out.println("프로젝트가 등록되었습니다!");
} catch (Exception e) {
System.out.println("프로젝트 등록 중 오류 발생!");
e.printStackTrace();
}
}
}
4단계 - 프로젝트 목록 조회 커맨드에서 비즈니스 로직을 분리한다.
- com.eomcs.pms.service.ProjectService 인터페이스 변경
list()메서드 선언
public interface ProjectService {
int delete(int projectNo) throws Exception;
int add(Project project) throws Exception;
List<Project> list(String keyword) throws Exception;
}
- com.eomcs.pms.service.DefaultProjectService 클래스 변경
list()메서드 구현ProjectListCommand에서 비즈니스 로직과 관련된 코드를 가져온다.
public class DefaultProjectService implements ProjectService {
.
.
.
@Override
public List<Project> list(String keyword) throws Exception {
// 이 메서드를 보면 서비스 객체가 할 일이 없다.
// 그냥 Dao 객체의 메서드를 호출한 다음에 리턴값을
// 그대로 리턴해주는 일을 한다.
// 그럼 왜 이런 메서드를 만들어야 하는가?
// => 프로그래밍의 일관성을 위해서다
// => 커맨드 객체가 상황에 따라 Service 객체를 쓰거나 Dao 객체를 써야 한다면
// 프로그래밍의 일관성이 없어서 유지보수 하기가 어렵다.
// => 커맨드 객체가 서비스 객체를 사용하기로 했으면
// 어떤 작업을 수행하든간에 일관되게 서비스 객체를 사용하는 것이
// 유지보수하기에 더 낫다.
// => 그래서 이런 메서드를 만드는 것이다.
// 즉, 서비스 객체의 메서드에서 특별히 할 일이 없다 하더라도
// 커맨드 객체가 일관성 있게 작업을 수행할 수 있도록
// 중간에서 Dao 객체의 메서드를 호출해주는 것이다.
return projectDao.findAll(keyword);
}
}
- com.eomcs.pms.handler.ProjectListCommand 클래스 변경
ProjectService구현체를 사용하여 프로젝트 목록 조회 처리
public class ProjectListCommand implements Command {
ProjectService projectService;
public ProjectListCommand(ProjectService projectService) {
this.projectService = projectService;
}
@Override
public void execute(Map<String,Object> context) {
System.out.println("[프로젝트 목록]");
try {
// 오류가 나지 않도록 일단 null을 넣어둔다.
List<Project> list = projectService.list((String) null);
System.out.println("번호, 프로젝트명, 시작일 ~ 종료일, 관리자, 팀원");
for (Project project : list) {
StringBuilder members = new StringBuilder();
for (Member member : project.getMembers()) {
if (members.length() > 0) {
members.append(",");
}
members.append(member.getName());
}
System.out.printf("%d, %s, %s ~ %s, %s, [%s]\n",
project.getNo(),
project.getTitle(),
project.getStartDate(),
project.getEndDate(),
project.getOwner().getName(),
members.toString());
}
} catch (Exception e) {
System.out.println("프로젝트 목록 조회 중 오류 발생!");
e.printStackTrace();
}
}
}
5단계 - 프로젝트 검색 커맨드에서 비즈니스 로직을 분리한다.
- com.eomcs.pms.service.ProjectService 인터페이스 변경
list(String)메서드 변경- 검색어를 받는 파라미터를 추가한다.
public interface ProjectService {
int delete(int projectNo) throws Exception;
int add(Project project) throws Exception;
List<Project> list(String keyword) throws Exception;
}
- com.eomcs.pms.service.DefaultProjectService 클래스 변경
list(String)메서드 구현- 검색어를 받는 파라미터를 추가한다.
public class DefaultProjectService implements ProjectService {
.
.
.
@Override
public List<Project> list(String keyword) throws Exception {
return projectDao.findByDetailKeyword(keyword);
}
}
- com.eomcs.pms.dao.ProjectDao 인터페이스 변경
findAll(String)메서드를 변경한다.findByKeyword()메서드를 삭제한다.findAll()메서드와 합친다.
public interface ProjectDao {
int insert(Project project) throws Exception;
int delete(int no) throws Exception;
Project findByNo(int no) throws Exception;
List<Project> findAll(String keyword) throws Exception;
List<Project> findByDetailKeyword(Map<String,Object> keywords) throws Exception;
int update(Project project) throws Exception;
int deleteMembers(int PorjectNo) throws Exception;
int insertMembers(Project project) throws Exception;
}
- com.eomcs.pms.dao.mariadb.ProjectDaoImpl 클래스 변경
- 인터페이스 변경에 맞춰
findAll(String)메서드를 변경한다. findByKeyword()메서드를 삭제한다.- 구현 기능을
findAll()메서드에 합친다.
- 구현 기능을
- 인터페이스 변경에 맞춰
public class ProjectDaoImpl implements com.eomcs.pms.dao.ProjectDao {
SqlSessionFactory sqlSessionFactory;
public ProjectDaoImpl(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
}
.
.
.
@Override
public List<Project> findAll(String keyword) throws Exception {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
return sqlSession.selectList("ProjectDao.findAll", keyword);
}
}
.
.
.
}
- src/main/resources/com/eomcs/pms/mapper/ProjectMapper.xml 변경
findAllSQL 문을 변경한다.findByKeywordSQL 문을 삭제한다.findAllSQL 문과 기능을 합친다.
<sql id="sql1">
select
p.no,
p.title,
p.sdt,
p.edt,
m.no owner_no,
m.name owner_name,
mp.member_no,
m2.name member_name
from
pms_project p
inner join pms_member m on p.owner=m.no
left outer join pms_member_project mp on p.no=mp.project_no
left outer join pms_member m2 on mp.member_no=m2.no
</sql>
<select id="findAll" resultMap="ProjectMap" parameterType="string">
<!-- 별도로 분리된 SQL 코드를 가져오고 싶다면, 다음과 같이 하라. -->
<include refid="sql1"/>
<if test="keyword != null">
where
p.title like concat('%', #{keyword}, '%')
or m.name like concat('%', #{keyword}, '%')
or m2.name like concat('%', #{keyword}, '%')
</if>
order by p.no desc
</select>
- com.eomcs.pms.handler.ProjectListCommand 클래스 변경
ProjectService.list(String)메서드 호출 코드를 변경한다.
public class ProjectListCommand implements Command {
ProjectService projectService;
public ProjectListCommand(ProjectService projectService) {
this.projectService = projectService;
}
@Override
public void execute(Map<String,Object> context) {
System.out.println("[프로젝트 목록]");
try {
// 오류가 나지 않도록 일단 null을 넣어둔다.
List<Project> list = projectService.list((String) null);
System.out.println("번호, 프로젝트명, 시작일 ~ 종료일, 관리자, 팀원");
.
.
.
}
- com.eomcs.pms.handler.ProjectSearchCommand 클래스 변경
ProjectService.list(String)메서드를 사용하여 프로젝트를 검색한다.
public class ProjectSearchCommand implements Command {
ProjectService projectService;
public ProjectSearchCommand(ProjectService projectService) {
this.projectService = projectService;
}
@Override
public void execute(Map<String,Object> context) {
System.out.println("[프로젝트 검색]");
try {
String keyword = Prompt.inputString("검색어? ");
List<Project> list = projectService.list(keyword);
System.out.println("번호, 프로젝트명, 시작일 ~ 종료일, 관리자, 팀원");
.
.
.
}
6단계 - 프로젝트 상세 검색 커맨드에서 비즈니스 로직을 분리한다.
- com.eomcs.pms.service.ProjectService 인터페이스 변경
list(Map<String,Object> keywords)메서드 추가(오버로딩)- 검색 항목과 검색어를 입력 받는 파라미터를 추가한다.
public interface ProjectService {
int delete(int projectNo) throws Exception;
int add(Project project) throws Exception;
List<Project> list(String keyword) throws Exception;
// ProjectListCommand가 Map 객체를 받는다?
// List 오버로딩한다.
//메서드의 파라미터 개수나 파라미터 타입이 다르더라도
// 같은 기능을 수행한다면
// 같은 이름을 부여함으로서 프로그래밍의 일관성을 유지하게 도와주는 문법
List<Project> list(Map<String,Object> keywords) throws Exception;
}
- com.eomcs.pms.service.DefaultProjectService 클래스 변경
list(Map<String,Object> keywords)메서드 구현(오버로딩)- 검색 항목과 검색어를 입력 받는 파라미터를 추가한다.
public class DefaultProjectService implements ProjectService {
.
.
.
@Override
public List<Project> list(Map<String, Object> keywords) throws Exception {
return projectDao.findByDetailKeyword(keywords);
}
}
- com.eomcs.pms.handler.ProjectDetailSearchCommand 클래스 변경
ProjectService.list(Map)메서드를 사용하여 프로젝트를 검색한다.
public class ProjectDetailSearchCommand implements Command {
ProjectService projectService;
public ProjectDetailSearchCommand(ProjectService projectService) {
this.projectService = projectService;
}
@Override
public void execute(Map<String,Object> context) {
System.out.println("[프로젝트 상세 검색]");
try {
HashMap<String,Object> keywords = new HashMap<>();
String title = Prompt.inputString("프로젝트명? ");
if (title.length() > 0) {
keywords.put("title", title);
}
String owner = Prompt.inputString("관리자명? ");
if (owner.length() > 0) {
keywords.put("owner", owner);
}
String member = Prompt.inputString("팀원명? ");
if (member.length() > 0) {
keywords.put("member", member);
}
List<Project> list = projectService.list(keywords);
System.out.println("번호, 프로젝트명, 시작일 ~ 종료일, 관리자, 팀원");
.
.
.
}
7단계 - 프로젝트 상세 조회 커맨드에서 비즈니스 로직을 분리한다.
- com.eomcs.pms.service.ProjectService 인터페이스 변경
get(int)메서드 추가
public interface ProjectService {
int delete(int projectNo) throws Exception;
int add(Project project) throws Exception;
List<Project> list(String keyword) throws Exception;
// ProjectListCommand가 Map 객체를 받는다?
// List 오버로딩한다.
//메서드의 파라미터 개수나 파라미터 타입이 다르더라도
// 같은 기능을 수행한다면
// 같은 이름을 부여함으로서 프로그래밍의 일관성을 유지하게 도와주는 문법
List<Project> list(Map<String,Object> keywords) throws Exception;
Project get(int no) throws Exception;
}
- com.eomcs.pms.service.DefaultProjectService 클래스 변경
get(int)메서드 구현
public class DefaultProjectService implements ProjectService {\
.
.
.
@Override
public Project get(int no) throws Exception {
return projectDao.findByNo(no);
}
}
- com.eomcs.pms.service.TaskService 인터페이스 생성
listByProject(int)메서드 추가
public interface TaskService {
List<Task> listByProject(int projectNo) throws Exception;
}
- com.eomcs.pms.service.DefaultTaskService 클래스 생성
listByProject(int)메서드 구현
public class DefaultTaskService implements TaskService {
TaskDao taskDao;
public DefaultTaskService(TaskDao taskDao) {
this.taskDao = taskDao;
}
@Override
public List<Task> listByProject(int projectNo) throws Exception {
HashMap<String,Object> map = new HashMap<>();
map.put("projectNo", projectNo);
return taskDao.findAll(map);
}
}
- com.eomcs.pms.handler.ProjectDetailCommand 클래스 변경
ProjectService.get(int)메서드를 사용하여 프로젝트를 조회한다.TaskService.listByProject(int)메서드를 사용하여 작업 목록을 조회한다.
public class ProjectDetailCommand implements Command {
ProjectService projectService;
TaskService taskService;
public ProjectDetailCommand(ProjectService projectService, TaskService taskService) {
this.projectService = projectService;
this.taskService = taskService;
}
@Override
public void execute(Map<String,Object> context) {
System.out.println("[프로젝트 상세보기]");
int no = Prompt.inputInt("번호? ");
try {
Project project = projectService.get(no);
if (project == null) {
System.out.println("해당 번호의 프로젝트가 존재하지 않습니다.");
return;
}
System.out.printf("프로젝트명: %s\n", project.getTitle());
System.out.printf("내용: %s\n", project.getContent());
System.out.printf("기간: %s ~ %s\n",
project.getStartDate(),
project.getEndDate());
System.out.printf("관리자: %s\n", project.getOwner().getName());
System.out.print("팀원: ");
project.getMembers().forEach(
member -> System.out.print(member.getName() + " "));
System.out.println();
System.out.println("작업:");
System.out.println("--------------------------------");
HashMap<String,Object> map = new HashMap<>();
map.put("projectNo", project.getNo());
List<Task> tasks = taskService.listByProject(no);
System.out.println("번호, 작업내용, 마감일, 작업자, 상태");
for (Task task : tasks) {
String stateLabel = null;
switch (task.getStatus()) {
case 1:
stateLabel = "진행중";
break;
case 2:
stateLabel = "완료";
break;
default:
stateLabel = "신규";
}
System.out.printf("%d, %s, %s, %s, %s\n",
task.getNo(),
task.getContent(),
task.getDeadline(),
task.getOwner().getName(),
stateLabel);
}
} catch (Exception e) {
System.out.println("프로젝트 조회 중 오류 발생!");
e.printStackTrace();
}
}
}
8단계 - 프로젝트 변경 커맨드에서 비즈니스 로직을 분리한다.
- com.eomcs.pms.service.ProjectService 인터페이스 변경
update(Project)메서드 추가
public interface ProjectService {
int delete(int projectNo) throws Exception;
int add(Project project) throws Exception;
List<Project> list(String keyword) throws Exception;
// ProjectListCommand가 Map 객체를 받는다?
// List 오버로딩한다.
//메서드의 파라미터 개수나 파라미터 타입이 다르더라도
// 같은 기능을 수행한다면
// 같은 이름을 부여함으로서 프로그래밍의 일관성을 유지하게 도와주는 문법
List<Project> list(Map<String,Object> keywords) throws Exception;
Project get(int no) throws Exception;
int update(Project project) throws Exception;
}
- com.eomcs.pms.service.DefaultProjectService 클래스 변경
update(Project)메서드 구현
public class DefaultProjectService implements ProjectService {
.
.
.
@Override
public int update(Project project) throws Exception {
return projectDao.update(project);
}
}
- src/main/resources/com/eomcs/pms/mapper/ProjectMapper.xml 변경
updateSQL 문을 동적 SQL로 변경한다.
<update id="update" parameterType="project">
update pms_project
<set>
<if test="title != null">title = #{title},</if>
<if test="title != null">content = #{content},</if>
<if test="title != null">sdt = #{startDate},</if>
<if test="title != null">edt = #{endDate},</if>
</set>
where no = #{no}
</update>
- com.eomcs.pms.handler.ProjectUpdateCommand 클래스 변경
ProjectService.update(Project)메서드를 사용하여 프로젝트를 변경한다.
package com.eomcs.pms.handler;
import java.sql.Date;
import java.util.Map;
import com.eomcs.pms.domain.Project;
import com.eomcs.pms.service.ProjectService;
import com.eomcs.util.Prompt;
public class ProjectUpdateCommand implements Command {
ProjectService projectService;
public ProjectUpdateCommand(ProjectService projectService) {
this.projectService = projectService;
}
@Override
public void execute(Map<String,Object> context) {
System.out.println("[프로젝트 변경]");
int no = Prompt.inputInt("번호? ");
try {
Project project = projectService.get(no);
if (project == null) {
System.out.println("해당 번호의 프로젝트가 존재하지 않습니다.");
return;
}
String value = Prompt.inputString(String.format(
"프로젝트명(%s)? ", project.getTitle()));
if (value.length() > 0) {
project.setTitle(value);
}
value = Prompt.inputString(String.format(
"내용(%s)? ", project.getContent()));
if (value.length() > 0) {
project.setContent(value);
}
value = Prompt.inputString(String.format(
"시작일(%s)? ", project.getStartDate()));
if (value.length() > 0) {
project.setStartDate(Date.valueOf(value));
}
value = Prompt.inputString(String.format(
"종료일(%s)? ", project.getEndDate()));
if (value.length() > 0) {
project.setEndDate(Date.valueOf(value));
}
String response = Prompt.inputString("정말 변경하시겠습니까?(y/N) ");
if (!response.equalsIgnoreCase("y")) {
System.out.println("프로젝트 변경을 취소하였습니다.");
return;
}
if (projectService.update(project) == 0) {
System.out.println("해당 번호의 프로젝트가 존재하지 않습니다.");
} else {
System.out.println("프로젝트를 변경하였습니다.");
}
} catch (Exception e) {
System.out.println("프로젝트 변경 중 오류 발생!");
e.printStackTrace();
}
}
}