😎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 |