레이어드 아키텍처(Layered Architecture) 실습4

oyeon·2021년 1월 26일
0

Service Layer 부분 실습

  1. GuestbookService.java
package kr.or.connect.guestbook.service;

import java.util.List;

import kr.or.connect.guestbook.dto.Guestbook;

public interface GuestbookService {
	/* - 요구사항 -
	 * 방명록 정보를 페이지 별로 읽어오기
	 * 페이징 처리를 위해서 전체 건 수 구하기
	 * 방명록 저장하기
	 * id에 해당하는 방명록 삭제하기
	 * */
	public static final Integer LIMIT = 5;
	public List<Guestbook> getGuestbooks(Integer start);
	public int deleteGuestbook(Long id, String ip);
	public Guestbook addGuestbook(Guestbook guestbook, String ip);
	public int getCount();
}
  1. GuestbookServiceImpl.java
package kr.or.connect.guestbook.service.impl;

import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import kr.or.connect.guestbook.dao.GuestbookDao;
import kr.or.connect.guestbook.dao.LogDao;
import kr.or.connect.guestbook.dto.Guestbook;
import kr.or.connect.guestbook.dto.Log;
import kr.or.connect.guestbook.service.GuestbookService;

@Service
public class GuestbookServiceImpl implements GuestbookService {
	// Bean을 자동으로 등록.
	@Autowired
	GuestbookDao guestbookDao;
	
	@Autowired
	LogDao logDao;

	/* 읽기만 하는 메서드는 트랜잭션을 처리할 때 @Transactional을 통해
	 * 내부적으로 readOnly 형태로 connection을 사용한다.
	 */
	@Override
	@Transactional
	public List<Guestbook> getGuestbooks(Integer start) {
		List<Guestbook> list = guestbookDao.selectAll(start, LIMIT);
		return list;
	}

	// 삭제될 때 log table에 기록
	@Override
	@Transactional(readOnly = false)
	public int deleteGuestbook(Long id, String ip) {
		int deleteCount = guestbookDao.deleteById(id);
		Log log = new Log();
		log.setIp(ip);
		log.setMethod("delete");
		log.setRegdate(new Date());
		logDao.insert(log);
		return deleteCount;
	}
	
	/* regdate는 따로 값을 가져 오지 않으므로 setRegdate 해준다.
	 * id는 입력시 자동으로 만들어진 것이므로 setId로 값을 넣어줌
	 * (Log에 남겨주기 위해)
	 * 입력될 때 log table에 기록
	 */
	@Override
	@Transactional(readOnly = false)
	public Guestbook addGuestbook(Guestbook guestbook, String ip) {
		guestbook.setRegdate(new Date());
		Long id = guestbookDao.insert(guestbook);
		guestbook.setId(id);
		
		Log log = new Log();
		log.setIp(ip);
	        // log.setId(id);  
            	/* 오류 발생. 위의 코드 guestbookDao.insert(guestbook) 부분이
            	 * Rollback 되는 것으로 트랜잭션이 제대로 동작되는 것을 볼 수 있다.
            	 * 
                 * 고의로 예외를 발생시켜도 트랜잭션을 확인할 수 있다.
                 * if(true)
			throw new RuntimeException("test exception");
		*/		

		log.setMethod("insert");
		log.setRegdate(new Date());
		logDao.insert(log);
		
		return guestbook;
	}

	@Override
	public int getCount() {
		return guestbookDao.selectCount();
	}
}
  1. GuestbookServiceTest.java
  • 테스트 파일을 만들어 입력이 제대로 되는지 확인해 보자. (Run Java Application)
package kr.or.connect.guestbook.service.impl;

import java.util.Date;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import kr.or.connect.guestbook.config.ApplicationConfig;
import kr.or.connect.guestbook.dto.Guestbook;
import kr.or.connect.guestbook.service.GuestbookService;

public class GuestbookServiceTest {
	public static void main(String[] args) {
		ApplicationContext ac = new AnnotationConfigApplicationContext(ApplicationConfig.class); 
		GuestbookService guestbookService = ac.getBean(GuestbookService.class);
		
		Guestbook guestbook = new Guestbook();
		guestbook.setName("최호연");
		guestbook.setContent("반갑다. 제군.");
		guestbook.setRegdate(new Date());
		Guestbook result = guestbookService.addGuestbook(guestbook, "127.0.0.1");
		System.out.println(result);
	}
}

결과

  • guestbook 테이블의 id가 3인 것은 addGuestbook 메서드에서 log.setIp(ip);를 log.setId(id);로 잘못 작성해서 에러가 발생했기 때문이다. 에러가 발생한 시점에 id 2가 사용이 되었던 것이다.
  • 주목할 점은 예외가 발생했을 때 이전에 성공했었던 guestbookDao.insert(guestbook) 부분이 Rollback 처리 되어 guestbook 테이블에 입력되지 않은 것을 확인할 수 있다.
  • @Transactional(readOnly = false) 를 주석처리하면 어떻게 될까?
  • 예외 발생 전에 수행된 Long id = guestbookDao.insert(guestbook); 부분이 수행되어 guestbook 테이블에 추가되고 log 테이블에는 추가되지 않는 것을 볼 수 있다. 이런 상황을 방지하기 위해 트랜잭션은 필수이다.
profile
Enjoy to study

0개의 댓글