코딩기록 저장소 🐕/JSP

MyBatis

kimkongmom 2023. 9. 21. 09:03

 

 

 

 

😎MyBatis란?

 

MyBatis는 자바 개발자들이 데이터베이스를 쉽게 다룰 수 있도록 도와주는 오픈 소스 ORM프레임워크이다

 

 

😎MyBatis의 사용 목적

 

MyBatis는 데이터베이스 쿼리 <-> 프로그래밍 언어 코드를 분리하여 유지보수성과 생산성을 높이는것이다.

 

 

Mybatis는 Data Access Layer에서 사용하는 프레임워크이다.
Controller에서 Service를 호출하고 Service가 DAO계층에 있는 메소드를 호출하면 DAO에서 Mybatis를 호출한다

 

 

 

만드는 순서

 

 

sql 쿼리

 

1
2
3
4
5
6
7
8
9
10
11
12
DROP TABLE BOOK_T;
CREATE TABLE BOOK_T (
  BOOK_NO NUMBER             NOT NULL,
  TITLE   VARCHAR2(100 BYTE) NOT NULL,
  AUTHOR  VARCHAR2(100 BYTE),
  PRICE   NUMBER,
  PUBDATE DATE,
  CONSTRAINT PK_BOOK PRIMARY KEY(BOOK_NO)
);
 
DROP SEQUENCE BOOK_SEQ;
CREATE SEQUENCE BOOK_SEQ NOCACHE;
cs

 

▶ ActionForward

path: 페이지 이동 경로를 나타내는 문자열입니다. 이 경로는 다음에 이동할 페이지의 주소를 나타냅니다.

isRedirect: 페이지 이동 방식을 나타내는 부울(boolean) 값입니다. true일 경우 리다이렉트(redirect) 방식으로 페이지 이동하고, false일 경우 포워드(forward) 방식으로 페이지 이동합니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
package common;
 
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
 
@NoArgsConstructor
@AllArgsConstructor
@Data
public class ActionForward {
  private String path;
  private boolean isRedirect;
}
cs

 

 

BookDto

sql 필드가져오기

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package domain;
 
import java.sql.Date;
 
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
 
@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder
public class BookDto {
  private int bookNo;
  private String title;
  private String author;
  private int price;
  private Date pubdate;
}
cs

 

 

myBatis-config

 MyBatis는 데이터베이스와의 상호 작용을 단순화하는 Java ORM(Object-Relational Mapping) 프레임워크 중 하나로, SQL 쿼리를 XML 파일에 저장하고 Java 객체와 연결하여 데이터베이스 작업을 수행하는 데 사용됩니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-config.dtd">
 
<configuration>
    
  <!-- 설정 -->
  <settings>
    <setting name="mapUnderscoreToCamelCase" value="true"/>
  </settings>
  
  <!-- 환경 설정(Transaction, Connection Pool) -->
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC" />
      <dataSource type="POOLED">
        <property name="driver" value="oracle.jdbc.OracleDriver"/>
        <property name="url" value="jdbc:oracle:thin:@localhost:1521:xe"/>
        <property name="username" value="GD"/>
        <property name="password" value="1111"/>
      </dataSource>
    </environment>
  </environments>
  
  <!-- 매퍼 설정(매퍼의 위치와 이름) -->
  <mappers>
    <mapper resource="mybatis/mapper/book.xml"/>
  </mappers>
 
</configuration>
cs

 

 

book.xml

MyBatis 매퍼 파일로, SQL 쿼리와 Java 객체 간의 매핑 및 데이터베이스 작업을 정의합니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
 
<mapper namespace="mybatis.mapper.book">
 
  <select id="bookCount" resultType="int">
    SELECT COUNT(*)
      FROM BOOK_T
  </select>
 
  <select id="bookList" parameterType="Map" resultType="domain.BookDto">
    SELECT A.BOOK_NO, A.TITLE, A.AUTHOR, A.PRICE, A.PUBDATE
      FROM (SELECT BOOK_NO, TITLE, AUTHOR, PRICE, PUBDATE, ROW_NUMBER() OVER(ORDER BY BOOK_NO DESC) AS RN
              FROM BOOK_T) A
     WHERE A.RN BETWEEN #{begin} AND #{end}
  </select>
  
  <select id="bookDetail" parameterType="int" resultType="domain.BookDto">
    SELECT BOOK_NO, TITLE, AUTHOR, PRICE, PUBDATE
      FROM BOOK_T
     WHERE BOOK_NO = #{bookNo}
  </select>
  
  <insert id="bookAdd" parameterType="domain.BookDto">
    INSERT INTO BOOK_T (
        BOOK_NO
      , TITLE
      , AUTHOR
      , PRICE
      , PUBDATE
    ) VALUES (
        BOOK_SEQ.NEXTVAL
      , #{title}
      , #{author}
      , #{price}
      , SYSDATE
    )
  </insert>
  
  <update id="bookModify" parameterType="domain.BookDto">
    UPDATE BOOK_T
       SET TITLE = #{title}
         , AUTHOR = #{author}
         , PRICE = #{price}
     WHERE BOOK_NO = #{bookNo}
  </update>
  
  <delete id="bookDelete" parameterType="int">
    DELETE
      FROM BOOK_T
     WHERE BOOK_NO = #{bookNo}
  </delete>
  
</mapper>
cs

 

 

 BookDao

BookDao는 데이터베이스 작업을 수행하기 위한 메서드를 제공하는 데이터 액세스 객체(DAO)입니다. 이 DAO는 MyBatis를 사용하여 데이터베이스와 상호 작용하며,

 

SqlSessionFactory 생성: BookDao 클래스는 MyBatis의 SqlSessionFactory를 생성합니다. SqlSessionFactory는 MyBatis와 데이터베이스 간의 세션을 관리하고 SQL 쿼리를 실행하기 위한 인터페이스를 제공합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package repository;
 
import java.io.InputStream;
import java.util.List;
import java.util.Map;
 
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
 
import domain.BookDto;
 
public class BookDao {
 
  // mybatis의 SqlSession을 만들 수 있는 SqlSessionFactory 선언
  private SqlSessionFactory factory;
  
  // Singleton Pattern
  private static BookDao dao = new BookDao();
  private BookDao() {
    // SqlSessionFactory 생성
    try {
      String resource = "mybatis/config/mybatis-config.xml";
      InputStream in = Resources.getResourceAsStream(resource);
      factory = new SqlSessionFactoryBuilder().build(in);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  public static BookDao getDao() {
    return dao;
  }
  
  // 매퍼의 namespace
  private final String NS = "mybatis.mapper.book.";
  
  // 전체 개수 반환 메소드
  public int bookCount() {
    SqlSession ss = factory.openSession();
    int count = ss.selectOne(NS + "bookCount");
    ss.close();
    return count;
  }
  
  // 목록 반환 메소드
  public List<BookDto> bookList(Map<String, Object> map) {
    SqlSession ss = factory.openSession();
    List<BookDto> list = ss.selectList(NS + "bookList", map);
    ss.close();
    return list;
  }
  
  // 상세 반환 메소드
  public BookDto bookDetail(int bookNo) {
    SqlSession ss = factory.openSession();
    BookDto dto = ss.selectOne(NS + "bookDetail", bookNo);
    ss.close();
    return dto;
  }
  
  // 등록 메소드 
  public int bookAdd(BookDto dto) {
    SqlSession ss = factory.openSession(false);  // false : 내가 커밋하겠다.
    int addResult = ss.insert(NS + "bookAdd", dto);
    if(addResult == 1) {
      ss.commit();
    }
    ss.close();
    return addResult;
  }
  
  // 수정 메소드
  public int bookModify(BookDto dto) {
    SqlSession ss = factory.openSession(false);
    int modifyResult = ss.update(NS + "bookModify", dto);
    if(modifyResult == 1) {
      ss.commit();
    }
    ss.close();
    return modifyResult;
  }
  
  
  // 삭제 메소드
  public int bookDelete(int bookNo) {
    SqlSession ss = factory.openSession(false);
    int deleteResult = ss.delete(NS + "bookDelete", bookNo);
    if(deleteResult == 1) {
      ss.commit();
    }
    ss.close();
    return deleteResult;
  }
  
}
cs

 

 

 

 

BookService

인터페이스

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package service;
 
import javax.servlet.http.HttpServletRequest;
 
import common.ActionForward;
 
public interface BookService {
   public ActionForward bookList(HttpServletRequest request);
   public ActionForward bookDetail(HttpServletRequest request);
   public ActionForward bookAdd(HttpServletRequest request);
   public ActionForward bookEdit(HttpServletRequest request);
   public ActionForward bookModify(HttpServletRequest request);
   public ActionForward bookDelete(HttpServletRequest request);
}
cs

 

 

 

 

 

▶ BookServiceImpl 

Optional<String> opt = Optional.ofNullable(request.getParameter("page"));
HTTP 요청 파라미터 중 "page" 값을 가져오고, 만약 값이 없으면 빈 Optional 객체를 생성합니다

 

int page = Integer.parseInt(opt.orElse("1"));
Optional 객체에서 값을 꺼내와 정수형으로 변환합니다. 만약 값이 없으면 기본값으로 1을 사용합니다.

 

int total = dao.bookCount();
dao를 사용하여 데이터베이스에서 전체 도서 개수를 가져옵니다.

 

pageVo.setPaging(page, total, display);
페이지 정보를 계산하기 위해 pageVo 객체의 setPaging 메서드를 호출합니다.

 

Map<String, Object> map = new HashMap<String, Object>();
데이터베이스에서 도서 목록을 가져오기 위한 매개변수를 저장할 map 객체를 생성합니다.

 

map.put("begin", pageVo.getBegin());
시작 페이지 번호를 map에 저장합니다.

 

map.put("end", pageVo.getEnd());
끝 페이지 번호를 map에 저장합니다.

 

List<BookDto> bookList = dao.bookList(map);
dao를 사용하여 데이터베이스에서 도서 목록을 가져옵니다.

 

request.setAttribute("bookList", bookList);
도서 목록을 JSP 페이지로 전달하기 위해 request에 속성을 설정합니다.

 

request.setAttribute("paging", pageVo.getPaging(request.getContextPath() + "/book/list.do"));
페이지 번호 목록을 JSP 페이지로 전달하기 위해 request에 속성을 설정합니다. 페이지 번호 목록은 pageVo 객체의 getPaging 메서드를 호출하여 생성합니다.

 

return new ActionForward("/book/list.jsp", false);
JSP 페이지로 포워드하며, 페이지 이동 방식은 리다이렉트가 아닌 포워드를 사용합니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package service;
 
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
 
import javax.servlet.http.HttpServletRequest;
 
import common.ActionForward;
import domain.BookDto;
import repository.BookDao;
import util.PageVo;
 
public class BookServiceImpl implements BookService {
 
  private BookDao dao = BookDao.getDao();
  private PageVo pageVo = new PageVo();
  
  @Override
  public ActionForward bookList(HttpServletRequest request) {
    Optional<String> opt = Optional.ofNullable(request.getParameter("page"));
    int page = Integer.parseInt(opt.orElse("1"));
    int total = dao.bookCount();
    int display = 10;
    pageVo.setPaging(page, total, display);
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("begin", pageVo.getBegin());
    map.put("end", pageVo.getEnd());
    List<BookDto> bookList = dao.bookList(map);
    request.setAttribute("bookList", bookList);
    request.setAttribute("paging", pageVo.getPaging(request.getContextPath() + "/book/list.do"));
    return new ActionForward("/book/list.jsp"false);
  }
 
  @Override
  public ActionForward bookDetail(HttpServletRequest request) {
    Optional<String> opt = Optional.ofNullable(request.getParameter("bookNo"));
    int bookNo = Integer.parseInt(opt.orElse("0"));
    BookDto book = dao.bookDetail(bookNo);
    request.setAttribute("book", book);
    return new ActionForward("/book/detail.jsp"false);
  }
 
  @Override
  public ActionForward bookAdd(HttpServletRequest request) {
    String title = request.getParameter("title");
    String author = request.getParameter("author");
    int price = Integer.parseInt(request.getParameter("price"));
    BookDto dto = BookDto.builder()
        .title(title)
        .author(author)
        .price(price)
        .build();
    int addResult = dao.bookAdd(dto);
    String path = null;
    switch(addResult) {
    case 0: path = request.getContextPath() + "/index.do"break;
    case 1: path = request.getContextPath() + "/book/list.do"break;    
    }
    return new ActionForward(path, true);
  }
 
  @Override
  public ActionForward bookEdit(HttpServletRequest request) {
    Optional<String> opt = Optional.ofNullable(request.getParameter("bookNo"));
    int bookNo = Integer.parseInt(opt.orElse("0"));
    BookDto book = dao.bookDetail(bookNo);
    request.setAttribute("book", book);
    return new ActionForward("/book/edit.jsp"false);
  }
  
  @Override
  public ActionForward bookModify(HttpServletRequest request) {
    int bookNo = Integer.parseInt(request.getParameter("bookNo"));
    String title = request.getParameter("title");
    String author = request.getParameter("author");
    int price = Integer.parseInt(request.getParameter("price"));
    BookDto dto = BookDto.builder()
                    .bookNo(bookNo)
                    .title(title)
                    .author(author)
                    .price(price)
                    .build();
    int modifyResult = dao.bookModify(dto);
    String path = null;
    switch(modifyResult) { 
    case 0: path = request.getContextPath() + "/index.do"break;
    case 1: path = request.getContextPath() + "/book/detail.do?bookNo=" + bookNo; break;    
    }
    return new ActionForward(path, true);
  }
 
  @Override
  public ActionForward bookDelete(HttpServletRequest request) {
    Optional<String> opt = Optional.ofNullable(request.getParameter("bookNo"));
    int bookNo = Integer.parseInt(opt.orElse("0"));
    int deleteResult = dao.bookDelete(bookNo);
    String path = null;
    switch(deleteResult) {
    case 0: path = request.getContextPath() + "/index.do"break;
    case 1: path = request.getContextPath() + "/book/list.do"break;    
    }
    return new ActionForward(path, true);
  }
 
}
cs

 

 

 

 

▶ BookController

ActionForward 객체에 따라 리다이렉트할 것인지(isRedirect) 또는 포워드할 것인지 판단합니다.
리다이렉트할 경우 response.sendRedirect()를 사용하여 다른 페이지로 이동하고, 

포워드할 경우 request.getRequestDispatcher().forward()를 사용하여 현재 페이지 내에서 다른 내용을 표시합니다.

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 
    // BookFilter 실행 후 Controller 실행
    
    // 요청 인코딩(BookFilter가 수행함) + 응답 타입과 인코딩
    // request.setCharacterEncoding("UTF-8");
    response.setContentType("text/html; charset=UTF-8");
    
    // 요청 주소 확인
    String requestURI = request.getRequestURI();
    String contextPath = request.getContextPath();
    String urlMapping = requestURI.substring(contextPath.length());
    
    // 어디로 어떻게 이동할 것인지 알고 있는 ActionForward 객체
    ActionForward af = null;
    
    // 요청에 따른 처리
    switch(urlMapping) {
    // 단순 이동 (forward 처리)
    case "/book/write.do":
      af = new ActionForward("/book/write.jsp"false);
      break;
    case "/index.do":
      af = new ActionForward("/index.jsp"false);
      break;
    // 서비스 처리
    case "/book/add.do":
      af = bookService.bookAdd(request);
      break;
    case "/book/list.do":
      af = bookService.bookList(request);
      break;
    case "/book/detail.do":
      af = bookService.bookDetail(request);
      break;
    case "/book/edit.do":
      af = bookService.bookEdit(request);
      break;
    case "/book/modify.do":
      af = bookService.bookModify(request);
      break;
    case "/book/delete.do":
      af = bookService.bookDelete(request);
      break;
    }
    
    // 이동
    if(af != null) {
      if(af.isRedirect()) {
        response.sendRedirect(af.getPath());
      } else {
        request.getRequestDispatcher(af.getPath()).forward(request, response);
      }
    }
    
  }
cs

 

 

 

 

 

 

 

 

 

'코딩기록 저장소 🐕 > JSP' 카테고리의 다른 글

ajax mybatis  (0) 2023.09.22
게시물 CRUD,DBCP  (0) 2023.09.20
DBCP  (0) 2023.09.19
mvc pattern2  (0) 2023.09.19
mvc pattern  (0) 2023.09.18