이전에 작성한 코드를 더 효율적으로 바꿀 수 있는 방법으로 DAO 패턴 적용하기를 했는데 뭐가 내용이 많아서 정신은 없었지만 재밌었음. 역시 효율충 어디 안간다..
/{변수}
형식을 사용하여 경로를 지정 가능@RequestMappig("/detail/{idx}")
public String detail(@ModelAttribute Dto dto, @PathVariable int idx) {
//...
return "detail";
}
//요청 파라미터 방식(@RequestParam, @ModelAttribute)
http://localhost:8888/detail?index=5
//경로 변수 방식(@PathVariable, @ModelAttribute)
http://localhost:8080/detail/5
DAO
: Data Access Object, 데이터 접근 객체CRUD
작업을 처리하는 도구모듈화
할 수 있음지금까지는 Controller에서 모든 작업을 처리하도록 구현했음
연계 작업
만 처리해야 함(데이터를 받아서 누군가를 주고 처리해달라고 한다음에 그 결과를 받아서 안내해주는 역할만 담당)DAO Pattern을 적용해 데이터의 CRUD를 처리하는 과정을 살펴보려고 함. 아래 Database 정보를 기반으로 진행
CREATE TABLE GUEST_BOOK(
NO NUMBER PRIMARY KEY,
NAME VARCHAR2(21) NOT NULL,
MEMO VARCHAR2(90) NOT NULL
);
CREATE SEQUENCE GB_SEQ;
package com.jw.spring07rv.entity;
public class GuestBookDto {
private int no;
private String name;
private String memo;
//getter(), setter(), Constructor, toString()...
}
추상화
구조@Repository
)@Autowired
)package com.jw.spring07rv.repository;
public interface GuestBookDao {
//oo기능의 형태(추상 메소드)
}
package com.jw.spring07rv.repository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class GuestBookDaoImpl implements GuestBookDao{
//oo기능의 형태 + 구현 코드
@Autowired
private JdbcTemplate jdbcTemplate;
}
추상체(Interface)를 주입
함으로써 약결합
프로그램을 만들기 위함. (결합도가 낮고 응집도가 높을 수록 좋은 프로그램)@Controller
public class GuestBookController {
@Autowired
private GuestBookDao guestBookDao;
}
GuestBookDao(interface)
: 데이터 CRUD 각각에 대한 메소드 틀을 작성GuestBookDaoImpl(class)
: 추상 메소드 오버라이딩을 통해 처리 코드 구현GuestBookController
: DTO에서 데이터를 받아 DAO에 넘기고, DAO로부터 받은 결과를 처리해 return하는 메소드 작성INSERT INTO GUEST_BOOK(NO, NAME, MEMO)
VALUES(GB_SEQ.NEXTVAL, ?, ?);
파라미터
를 GuestBookDto 객체 형태
로 선언하면 한 번의 선언으로 데이터를 묶어서 전달받을 수 있음void insert(GuestBookDto dto);
//void insert(int no, String name, String memo);
public void insert(GuestBookDto dto) {
String sql = "insert into guest_book(no, name, memo) "
+ "values(guest_book_seq.nextval, ?, ?)";
Object[] param = {dto.getName(), dto.getMemo()};
jdbcTemplate.update(sql, param);
}
@RequestMapping("/insert")
@ResponseBody
public String insert(@ModelAttribute GuestBookDto dto) {
return "등록 완료";
}
UPDATE GUEST_BOOK SET NAME = ?, MEMO = ? WHERE NO = ?;
boolean update(GuestBookDto dto);
public boolean update(GuestBookDto dto) {
String sql = "update guest_book set name = ?, memo = ? where no = ?";
Object[] param = {dto.getName(), dto.getMemo(), dto.getNo()};
//쿼리 실행 결과가 0보다 큰지 판단해서 결과 반환
return jdbcTemplate.update(sql, param) > 0;
}
@RequestMapping("/update")
@ResponseBody
public String update(@ModelAttribute GuestBookDto dto) {
if(guestBookDao.update(dto)) {
return "수정 완료";
}else {
return "없는 번호";
}
}
DELETE GUEST_BOOK WHERE NO = ?;
boolean delete(int no);
public boolean delete(int no) {
String sql = "delete guest_book where no = ?";
Object[] param = {no};
return jdbcTemplate.update(sql, param) > 0;
}
@RequestMapping("/delete/{no}")
@ResponseBody
public String delete(@PathVariable int no) {
if(guestBookDao.delete(no)) { //result 변수 안만들기
return "삭제 완료";
}else {
return "없는 번호";
}
}
SELECT * FROM GUEST_BOOK ORDER BY NO ASC; //목록 조회(여러 행)
SELECT * FROM GUEST_BOOK
WHERE INSTR(#1, ?) > 0
ORDER BY #1 ASC; //키워드 검색결과 조회(단일 행)
List<GuestBookDto> selectList();
List<GuestBookDto> selectList(String type, String keyword) //오버로딩
//RowMapper<T>
private RowMapper<GuestBookDto> mapper = (rs, idx) -> {
GuestBookDto dto = new GuestBookDto();
dto.setNo(rs.getInt("no"));
dto.setName(rs.getString("name"));
dto.setMemo(rs.getString("memo"));
return dto;
};
//목록 조회
@Override
public List<GuestBookDto> selectList() {
String sql = "select * from guest_book order by no asc";
return jdbcTemplate.query(sql, mapper);
}
//검색 결과 조회
@Override
public List<GuestBookDto> selectList(String type, String keyword) {
String sql = "select * from guest_book "
+ "where instr(#1, ?) > 0 "
+ "order by no asc";
sql = sql.replace("#1", type);
Object[] param = {keyword};
return jdbcTemplate.query(sql, mapper, param);
}
파라미터 존재 여부
를 조건으로 설정required=false
로 지정required=false, defaultValue=""
@RequestMapping("/list")
@ResponseBody
public String list(
@RequestParam(required=false)String type,
@RequestParam(required=false)String keyword
) {
boolean search = type != null && keyword != null; //검색인지 판단
List<GuestBookDto> data;
if(search) {
data = guestBookDao.selectList(type, keyword);
}else {
data = guestBookDao.selectList();
}
return data.toString();
}
SELECT * FROM GUEST_BOOK WHERE NO = ?;
DTO는 테이블 안에 있는 한 개의 행 데이터
를 저장하기 위한 클래스이므로 단일 행을 조회하는 경우 반환형을 DTO로 설정
GuestBookDto selectOne(int no);
//ResultSetExtractor<T>
private ResultSetExtractor<GuestBookDto> extractor = (rs) -> {
if(rs.next()) {
GuestBookDto dto = new GuestBookDto();
dto.setNo(rs.getInt("no"));
dto.setName(rs.getString("name"));
dto.setMemo(rs.getString("memo"));
return dto;
}else {
return null;
}
};
//상세 조회
@RequestMapping("/detail")
@ResponseBody
public String detail(@RequestParam int no) {
GuestBookDto dto = guestBookDao.selectOne(no);
if(dto == null) {
return "없는 번호";
}else {
return dto.toString();
}
}
@RequestMapping("/detail")
@ResponseBody
public String detail(@RequestParam int no) {
GuestBookDto dto = guestBookDao.selectOne(no);
if(dto == null) {
return "없는 번호";
}else {
return dto.toString();
}
}