1. 기본구조
웹 화면 - Controller - Service - DAO - Mapper - DB
Controller : 호출된 URL을 통한 데이터 입출력
Service : DAO 데이터를 주고 받으며 비즈니스 로직 수행
DAO(Data Access Object) : DB 데이터에 접근, 데이터를 삽입, 삭제, 조회 등 할 수 있음.
Mapper : Mapping 파일에 있는 SQL을 자바 인터페이스를 통해 호출할 수 있도록 해줌.
DTO(Data Transfer Object) : 계층 간 데이터 교환을 위한 로직을 가지지 않는 데이터 객체. getter, setter 메소드만 가진 클래스
Mapper: DAO 대신 인터페이스만을 사용하여 DB에 접근할 수 있다. (mybatis 사용 시 사용함.)
각각의 기능을 상세히 살펴보자.
* 각각 이해를 위한 예시코드일 뿐, 서로 100% 연관된 코드가 아님.
SampleDAO, Sample Service : Interface로 생성.
SampleDAOImPl , SampleServiceImpl : Class로 생성.
Controller - Service - ServiceImpl - DAO - DAOImpl 순으로 파일을 불러오는데 동작하는 예시
1. Controller
: 화면(웹 브라우저)에서 요청되는 URL 매핑을 통해, 컨트롤러에 접근해서 Service 객체를 호출한다.
@Controller
: @Controller 어노테이션을 붙여 이 클래스가 컨트롤러 클래스 라는 것을 알려준다.
사용자 요청이 들어오면 이 컨트롤러가 호출된다.
@RequestMappring("/apple")
: baseurl/apple 로 접속하게 되면 이 어노테이션을 가진 메소드로 매핑이 된다.
@Controller //해당 클래스를 컨트롤러로 동작하게 한다.
public class BoardController {
@Autowired
private BoardService boardService;
@RequestMapping("/apple") // 이 주소로 접속하면 이 메소드를 호출한다.(매핑한다.)
public ModelAndView openBoardList() throws Exception{
ModelAndView mv = new ModelAndView("/apple/boardList");
List<BoardDto> list = boardService.selectBoardList();
mv.addObject("list",list);
return mv;
}
}
[컨트롤러 예시]
List<BoardDto> list = boardService.selectBoardList();
이 부분이 Service를 호출하는 부분이다.
Service의 반환값을 list 에 저장하고 있다.
그럼 Service를 호출하면 어떻게 동작하는 알아 보자.
2-1. Service
: 컨트롤러에서는 요청을 받아 Service에 주입하고,
Service는 자신이 수행해야 할 서비스만 진행한다.
조건에 따라 로직을 생성하는 경우 대부분 Service에서 작업한다.
: 비즈니스 로직(biz)을 수행한다.
DB에 접근하는 DAO를 통해 결과값을 받아온다.
* DAO대신에 MyBatis의 Mapper을 사용하는 경우 역시 Service의 return을 통해 매퍼를 호출한다.
* BizImpl에서 Service 역할을 할 수 있다.
// interface는 개발 코드와 객체가 서로 통신하는 접점 역할을 함
// 개발 코드가 인터페이스의 메소드를 호출하면 인터페이스는 객체의 메소드를 호출
public interface SampleService {
// Controller에서 인자와 함께 전달된 메소드
List<SampleVO> selectSampleList(SearchConditionVO searchVO);
}
[sampleService]
Interface : 개발코드와 객체가 서로 통신하는 접점 역할
개발 코드가 인터페이스의 메소드를 호출하면, 인터페이스는 객체의 메소드를 호출한다.
이때 메소드는 컨트롤러에서 인자와 함께 전달된 메소드이다.
// Service를 인식시켜주기 위한 설정
@Service("sampleService")
public class SampleServiceImpl implements SampleService {
// SampleDAO 로 연결을 하기 위한 선언
@Autowired
private SampleDAO sampleDao;
// Controller에서 받아온 selectSampleList의 메소드를 SampleDAO의 selectSampleList 메소드 전달
// 결과로 얻은 반환값을 return을 통해 다시 Controller로 전달
@Override
public List<SampleVO> selectSampleList(SearchConditionVO searchVO) {
return sampleDao.selectSampleList(searchVO);
}
}
[SampleServiceImpl]
@Autowired : SampleDAO로 연결을 하기 위한 선언
컨트롤러에서 받아온 selectSampleList의 메소드를 SampleDAO의 selectSampleList 메소드 전달
결과로 얻은 반환값을 return으로 다시 컨트롤러에 전달한다.
2-2. BizImpl , Biz
: Service 대신 BizImpl, Biz을 사용하여 DAO(or Mapper)의 데이터를 받는 용도로 사용할 수 있다.
@Service("-") : Service용도로 사용하겠다는 어노테이션
@AutoWired : 의존성 주입을 위한 어노테이션
의존 객체의 타입에 해당하는 빈(bean)을 찾아 주입해준다.
@Transactional : 하나의 함수가 하나의 데이터베이스 트랜잭션 범위 안에서 실행되어야 함을 명시한다.
만약, 메서드에 적용하면 SpringBoot가 해당 메서드를 시작할 때 트랜잭션을 시작한다.
메서드가 성공적으로 완료되면 트랜잭션을 COMMIT, 만약 도중 예외가 발생하면 ROLLBACK 한다.
ROLLBACK이 발생했을때, 트랜잭션의 일부 작업만 데이터베이스에 적용되는 것을 방지해서 데이터일관성을 유지할 수있다.
메소드 or 클래스 단위에 선언,
클래스에 선언하면, 해당 클래스에 속하는 메서드에 공통적으로 적용된다.
메서드에 선언하면, 해당 메서드에만 적용된다.
*일반적으로 @Transactional은 비즈니스 로직을 처리하는 서비스 레이어에서 사용한다.
@Service("파워")
public class PowerBizImpl implements ProductBiz<PowerDto> {
@Autowired
private ProductMapper productMapper;
@Autowired
private PowerMapper powerMapper;
@Override
public List<PowerDto> selectAll() {
return null;
}
@Override
public PowerDto selectOne(int product_code) {
return null;
}
@Override
@Transactional
public int insert(PowerDto dto) {
System.out.println("Biz : " + dto);
int result = 0;
try {
result = productMapper.insertProduct(dto);
System.out.println("Biz : " + result);
int productCode = productMapper.getCurrentProductCode();
dto.setProduct_code(productCode);
result += powerMapper.insertPower(dto);
System.out.println("Biz : " + result);
} catch (Exception e) {
System.err.println("Error during insert: " + e.getMessage());
throw e;
}
return result;
}
}
3-1. DAO
: DB에 접속하여 비즈니스 로직 실행에 필요한 쿼리를 호출한다.
: DAO 대신에 mybatis의 Mapper을 이용해서 데이터베이스에 접근하여 데이터를 주고 받을 수 있다.
public interface SampleDAO {
// ServiceImpl에서 인자와 함께 전달된 메소드
List<SampleVO> selectSampleList(SearchConditionVO searchVO);
}
[ SampleDAO 전체 코드 ]
//DAO를 인식시켜주기 위한 설정
@Repository("sampleDao")
public class SampleDAOImpl implements SampleDAO {
// mybatis를 사용하기 위한 객체 선언
@Autowired
private SqlSessionTemplate mybatis;
// mybatis.속성("[mapper namespace].[select id]",[정보를 주고 받을 VO])
@Override
public List<SampleVO> selectSampleList(SearchConditionVO searchVO) {
// select를 위한 mybatis의 selectList 속성을 사용하여 mapper의 sql문을 실행시킨 후 값을 되받고
// Controller에 주기 위한 return 작업
return mybatis.selectList("SampleMapper.selectSampleList", searchVO);
}
}
[ SampleDAOImpl 전체 코드 ]
@Autowired : SqlSessionTemplate으로 연결을 하기 위한 선언
3-2. Mapper
: Mybatis 를 사용해 매퍼를 사용하여 DB에 접근할 수 있어진다.
이 경우, DAO대신 Mapper를 사용한다.
: 매퍼를 사용하면, 일일이 DAO를 만들지 않고 인터페이스만을 이용해 더 편하게 개발을 할 수 있다.
또한, SQL문을 JAVA코드와 분리하기 때문에 휴먼에러를 막아줄 수 있다.
4. DTO
: 각 계층(controller, view, service, DAO, DB)이 데이터를 주고 받을 때 사용하는 객체
: getter, setter 메소드가 있는 곳.
package com.boot.selftop_web.order.model.dto;
public class OrderBoardDto {
private int order_no;
private int seller_no;
private int customer_no;
private String address;
private String request;
private String reason;
private String name;
private String phone;
public OrderBoardDto() {}
public OrderBoardDto(int order_no, int seller_no, int customer_no, String address, String request, String reason,
String name, String phone) {
super();
this.order_no = order_no;
this.seller_no = seller_no;
this.customer_no = customer_no;
this.address = address;
this.request = request;
this.reason = reason;
this.name = name;
this.phone = phone;
}
public int getOrder_no() {
return order_no;
}
public void setOrder_no(int order_no) {
this.order_no = order_no;
}
public int getSeller_no() {
return seller_no;
}
public void setSeller_no(int seller_no) {
this.seller_no = seller_no;
}
public int getCustomer_no() {
return customer_no;
}
public void setCustomer_no(int customer_no) {
this.customer_no = customer_no;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getRequest() {
return request;
}
public void setRequest(String request) {
this.request = request;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
[DTO 예시]
'⚙️Backend > SPRING' 카테고리의 다른 글
[Thymeleaf] Thymeleaf 초기 설정 , 뷰 템플릿 사용 (4) | 2024.12.14 |
---|---|
[Spring Boot] 컨트롤러 / @annotation 정리 +간단한 view파일 넘기기 (2) | 2024.12.14 |
[Spring Boot] 스프링 의존성 주입 @Autowired, @Resource, @Inject (2) | 2024.12.14 |
[STS/Spring Boot] STS에서 maven으로 build 하는 방법 (1) | 2024.12.12 |