@Data
public class Pagination extends Common{
private int listSize = 10; // 초기값으로 목록개수를 10으로 셋팅
private int rangeSize = 10; // 초기값으로 페이지범위를 10으로 셋팅
private int page; // 현재 페이지
private int range; // 현재 페이지 범위 (1~10 = 1)
private int listCnt; // 총 게시물 개수
private int pageCnt; // 총 페이지 개수
private int startPage; // 각 페이지 범위 중 시작 번호
private int startList; // mysql용 게시판 시작 번호 (0, 10, 20..)
private int endPage; // 각 페이지 범위 중 마지막 번호
private boolean prev; // 이전 페이지 여부
private boolean next; // 다음 페이지 여부
public void pageInfo(int page, int range, int listCnt) {
this.page = page; // 현재 페이지
this.listCnt = listCnt; // 게시물 개수 총합
// 페이지 범위
this.range = range;
// 전체 페이지수
this.pageCnt = (int) Math.ceil((double) listCnt / listSize);
// 시작 페이지
this.startPage = (range - 1) * rangeSize + 1 ;
// 끝 페이지
this.endPage = range * rangeSize;
// 게시판 시작번호
this.startList = (page - 1) * listSize;
// 이전 버튼 상태
this.prev = range == 1 ? false : true;
// 다음 버튼 상태
this.next = endPage > pageCnt ? false : true;
if(this.endPage > this.pageCnt) {
this.endPage = this.pageCnt;
this.next = false;
}
}
}
Pagination : 페이지 처리에 필요한 필드 Common을 상속받고 활용할 외부 정보를 저장
package com.min.board.paging;
import lombok.Data;
@Data
public class Common {
private String searchText;
private String writer;
private String type;
}
Common : 메인 게시판, 내 글 관리, 휴지통 등 컨텐츠를 보여줄 때 아래 페이지 처리를 해야하는데 이 때 사용
searchText : 검색 기능이 필요한 페이지의 경우 사용
writer : 내 글 관리, 휴지통 등에서 사용자 정보를 저장
type : 메인 게시판, 내 글 관리, 휴지통 등 DB에서 가져오는 값이 다르므로 Mapper에서 <if> 문으로 동적 쿼리 진행
3. Mapper 코드
@Mapper
public interface BoardMapper {
// 게시글 개수 반환 (메인 게시글, 글 관리, 휴지통)
int selectBoardTotalCount(Pagination pagination);
// 게시글 리스트 (메인 게시글, 글 관리, 휴지통)
List<Board> selectBoardList(Pagination pagination);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.min.board.repository.BoardMapper">
<sql id="boardColumns">
id
,title
,content
,writer_id
,writer
,delete_yn
,create_date
,image
</sql>
<!--(페이징) 게시글 모두 조회-->
<select id="selectBoardList" resultType="Board">
SELECT
<include refid="boardColumns"/>
FROM
tb_board
WHERE
<if test="'list'.equals(type)">
<include refid="CommonMapper.search"/>
</if>
<if test="'myPost'.equals(type)">
<include refid="CommonMapper.myPost"></include>
</if>
<if test="'trash'.equals(type)">
<include refid="CommonMapper.trash"></include>
</if>
ORDER BY
id DESC,
create_date
<include refid="CommonMapper.paging"/>
</select>
<!--(페이징을 위한 카운트) 게시글 개수 카운트-->
<select id="selectBoardTotalCount" resultType="int">
SELECT
COUNT(*)
FROM
tb_board
WHERE
<if test="'list'.equals(type)">
<include refid="CommonMapper.search"/>
</if>
<if test="'myPost'.equals(type)">
<include refid="CommonMapper.myPost"></include>
</if>
<if test="'trash'.equals(type)">
<include refid="CommonMapper.trash"></include>
</if>
</select>
</mapper>
<BoardMapper.xml>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="CommonMapper">
<sql id="paging">
LIMIT
#{startList}, #{listSize}
</sql>
<sql id="search">
delete_yn = 'N'
<if test="searchText != null and searchText !=''">
AND
(
title LIKE CONCAT('%', #{searchText}, '%')
OR content LIKE CONCAT('%', #{searchText}, '%')
)
</if>
</sql>
<sql id="myPost">
delete_yn = 'N'
<if test="writer != null and writer !=''">
AND writer = #{writer}
</if>
</sql>
<sql id="trash">
delete_yn = 'Y'
<if test="writer != null and writer !=''">
AND writer = #{writer}
</if>
</sql>
</mapper>
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/board?serverTimezone=Asia/Seoul&characterEncoding=UTF-8
spring.datasource.username=아이디
spring.datasource.password=비밀번호
spring.devtools.livereload.enabled=true
spring.freemaker.cache=false
spring.thymeleaf.cache=false
# MyBatis
# mapper.xml 위치 src/main/resource/mapper/**/*.xml
mybatis.mapper-locations=classpath:mapper/**/*.xml
# camel case
mybatis.configuration.map-underscore-to-camel-case=true
# 패키지명 alias
mybatis.type-aliases-package=com.min.board.model
# mapper 로그정보
logging.level.com.min.board.model.repository=TRACE
4. 모델 추가 및 Mapper 인터페이스 추가
@Data
public class Board {
private Long id;
@NotNull
@Size(min = 2, max = 30, message = "제목은 2자 이상 30자 이하입니다.")
private String title;
@NotNull
@NotBlank(message = "내용을 입력하세요.")
private String content;
private Long writerId;
private String writer;
private String deleteYN;
private Timestamp createDate;
private String image;
}
@Mapper
public interface BoardMapper {
// 모든 글 조회
List<Board> selectAllBoards();
// 게시글 개수 반환 (메인 게시글, 글 관리, 휴지통)
int selectBoardTotalCount(Pagination pagination);
// 삭제된 글 제외 모두 조회 (메인 게시글, 글 관리, 휴지통)
List<Board> selectBoardList(Pagination pagination);
// 게시글 수정
void updateBoard(Board board);
// 아이디로 글 찾기
Board findById(Long id);
// 휴지통으로 이동 (임시삭제)
void temporaryDeleteById(Long id);
// 글 작성
void insertBoard(Board board);
// 휴지통 비우기
void permanentlyDeleteById(Long boardId);
}
5. resources/mapper 에 mapper.xml 추가
구조
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="CommonMapper">
<sql id="paging">
LIMIT
#{startList}, #{listSize}
</sql>
<sql id="search">
delete_yn = 'N'
<if test="searchText != null and searchText !=''">
AND
(
title LIKE CONCAT('%', #{searchText}, '%')
OR content LIKE CONCAT('%', #{searchText}, '%')
)
</if>
</sql>
<sql id="myPost">
delete_yn = 'N'
<if test="writer != null and writer !=''">
AND writer = #{writer}
</if>
</sql>
<sql id="trash">
delete_yn = 'Y'
<if test="writer != null and writer !=''">
AND writer = #{writer}
</if>
</sql>
</mapper>
<sql> : <include>를 통해 다른 쿼리에 활용 가능
refid : 참조
(select, update, insert, delete의) id : Mapper인터페이스 함수명과 동일
parameterType : #{}에 들어갈 파라미터 타입 (사용 권장하지 않음.)
resultType : 쿼리 결과 타입
#{} : 파리미터(get을 의미) -> DTO(모델)과 똑같은 필드명 작성
#{id} => getId
<if> : if문. test="조건"
참조 매퍼
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="CommonMapper">
<sql id="paging">
LIMIT
#{startList}, #{listSize}
</sql>
<sql id="search">
delete_yn = 'N'
<if test="searchText != null and searchText !=''">
AND
(
title LIKE CONCAT('%', #{searchText}, '%')
OR content LIKE CONCAT('%', #{searchText}, '%')
)
</if>
</sql>
<sql id="myPost">
delete_yn = 'N'
<if test="writer != null and writer !=''">
AND writer = #{writer}
</if>
</sql>
<sql id="trash">
delete_yn = 'Y'
<if test="writer != null and writer !=''">
AND writer = #{writer}
</if>
</sql>
</mapper>
6. Service에서 사용
private final BoardMapper boardMapper;
@Autowired
public BoardService(BoardMapper boardMapper) {
this.boardMapper = boardMapper;
}
// id를 이용해서 해당 글 수정
public Board contentLoad(Long id) {
Board board = boardMapper.findById(id);
return board;
}