I can do it(Feat. DEV)

[Mybatis] Pageable로 페이지 처리하기 본문

개발자 모드/응용

[Mybatis] Pageable로 페이지 처리하기

까짓거 해보자 개발자 2023. 12. 27. 15:31
728x90

 

📝글을 쓰게 된 계기

 

이번에 새로 개발 중인 웹 사이트는 개발 시간 단축을 위해 기존 시스템처럼 Mybatis를 사용하여 데이터를 조회함.

 

그런데 JPA로는 Pageable을 사용해 페이징 처리를 해보았지만, Mybatis는 해보지 않았음.

 

혹시 될 수도 있지 않을까 궁금해서 Page 타입에 Mybatis로 가져온 데이터를 넣어보았지만 당연히 에러가 남. 😅

 

바로 갓글에 검색 ~ 🤭

 

참조 사이트에 친절하게 설명되어 있지만 한번 더 숙지하기 위해 이 글을 작성함.

 

참고로 view 단 페이징은 이번 포스팅에서는 제외하고 back 단 구현만 포스팅함.

 

틀린 점 있다면 dm 말고 댓글로 말씀 부탁드림.🙏

 


 

챕터 1. pom.xml에 의존성 추가

 

Spring Data에서 제공하는 Pageable을 사용하려면 라이브러리를 추가해야 하는데 

 

필자는 Maven으로 라이브러리를 관리하고 있기에 pom.xml에 의존성을 추가함.

 

<dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-commons</artifactId>
</dependency>

 

참조 사이트는 위처럼 추가를 하면 된다고 나와있지만 혹시 ❓  필자처럼 spring boot 프로젝트를 생성할 때

 

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

 

spring boot starter data jpa가 추가되어 있다면 굳이 추가하지 않아도 됨.

 

🔎이유 : Spring Boot에서는 spring-boot-starter-data-jpa를 추가하면 spring-data-jpa 라이브러리와 관련된 의존성들이 자

동으로 추가됩니다. spring-boot-starter-data-jpa는 Spring Data JPA 및 Hibernate와 같은 관련 기술들을 사용하기 위한 스

타터 패키지로, 필요한 의존성들을 자동으로 설정해 줍니다.

 

(혹~시 필자처럼 궁금하신 분들을 위해서 찾아봄.)

 

그리고 application.yml 에 mybatis 설정 중 type-aliases-package를 여러 개 설정하고 싶다면

 

#mybatis설정
mybatis:
  mapper-locations: classpath:mapper/**/*.xml   #mybatis 매퍼 파일 위치 설정
  type-aliases-package: egovframework.uis.employee, egovframework.common.util #return 타입 패키지 지정
  configuration:
    map-underscore-to-camel-case: true  #카멜 케이스로 변환

 

이렇게 콤마(,)로 여러 개 설정하면 됨!!!(꿀팁👍)


 

챕터 2. RequestList.java 파일 추가(데이터 조회, 페이징 관련 파라미터를 담을 클래스) 

 

주의) 각자 프로젝트 구조마다 패키지 설정이 다를 수 있으니 혹시 에러가 난다면 자신의 프로젝트 구조를 잘 살펴보자.

 

또한 변수 or 메소드 명칭도 달라질 수 있음.

 

package test.common.util;

import lombok.Builder;
import lombok.Data;
import org.springframework.data.domain.Pageable;

@Builder
@Data
public class RequestList<T> {

    private T data; //요청 파라미터
    private Pageable pageable;  //페이지 설정 관련
}

 

필자는 test.common.util 위치에 RequestList 클래스 파일을 추가하였음.

 

위치는 만들기 나름인 듯하여 독자분들이 만들고 싶은 위치에 생성하면 될 듯.

 

 

728x90

 


 

챕터 3. 서비스 로직 구현

 

Dto에는 목록 조회 시 where 절에 들어갈 파라미터들을 담고(추후 mybatis xml의 parameterType에 들어감),

 

resultType은 Test라는 Domain으로 세팅함.

@RestController
@RequestMapping("/testUrl")
@RequiredArgsConstructor
public class TestController {//컨트롤러

    private final TestService service;	//서비스 의존성 주입

    @PostMapping
    public ResponseEntity<?> resultList(@RequestBody Dto dto, @PageableDefault(size = 5) Pageable pageable){
        return ResponseEntity.ok(service.testList(dto, pageable));
    }
}

 

view 단이 React로 개발 중이라 REST API 구조이기 때문에 위와 같이 컨트롤러 설정을 함.

 

@Service
public interface TestService {	//서비스

    Page<Test> testList(Dto dto, Pageable pageable);
}

 

@Service
@RequiredArgsConstructor
public class TestServiceImpl implements TestService{	//서비스를 구현한 구현체

    private final TestMapper mapper;

    @Override
    public Page<Test> testList(Dto dto, Pageable pageable) {

        RequestList<?> requestList = RequestList.builder()	//RequestList 생성
                .data(dto)
                .pageable(pageable)
                .build();

        List<Test> content = mapper.testList(requestList);	//데이터 조회
        int total = mapper.listCnt(dto);	//총 레코드 수 조회

        return new PageImpl<>(content, pageable, total);	//결과를 Page로 변환 후 반환
    }
}

 

testList에는 'RequestList.builder()'를 사용하여 'RequestList' 객체를 생성하고,

 

data에는 dto 객체를, pageable에는 Spring Data JPA의 페이징 정보를 설정함.

 

그리고 RequestList<?>에서 와일드카드('?')를 사용해서 어떤 타입의 data도 받을 수 있도록 설정함.

 

PageImpl 클래스를 사용하여 content, pageable, total 정보를 이용, 최종적으로 Page 객체를 생성하고 반환함.

 

@Mapper
@Repository
public interface TestMapper {	//mapper 설정

    List<Test> TestList(RequestList<?> requestList);

    int listCnt(Dto dto);
}

 

<?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="test.mapper.TestMapper">

	<!--테스트 목록 데이터-->
	<select id="TestList" parameterType="RequestList" resultType="Test">
		SELECT  id, title, content, writer
	    FROM TEST
		<where>
			<if test="data.title != null and data.title !='' ">
				AND title LIKE '%'||#{data.title}||'%'
			</if>
			<if test="data.writer != null and data.writer !='' ">
				AND writer = #{data.writer}
			</if>
		</where>
        <!--ORDER BY 절 추가-->
		<if test="pageable.sort != null and !pageable.sort.isEmpty()">
			ORDER BY
			<foreach collection="pageable.sort" item="order" separator=",">
				${order.property} ${order.direction}
			</foreach>
		</if>
        <!--페이징 처리-->
		OFFSET #{pageable.offset} ROWS FETCH NEXT #{pageable.pageSize} ROWS ONLY
	</select>
    
    <!--테스트 목록 카운트 -->
    <select id="listCnt" parameterType="Dto" resultType="int">
		SELECT COUNT(*) totcnt
		FROM TEST
		<where>
			<if test="title != null and title !='' ">
				AND title LIKE '%'||#{title}||'%'
			</if>
			<if test="writer != null and writer !='' ">
				AND writer = #{writer}
			</if>
		</where>
    </select>    
</mapper>

 

테스트 목록 데이터에서는 RequestList에서 파라미터를 가져오기 때문에 data. 형식으로 가져옴.

 

하지만 테스트 목록 카운트는 Dto에서 바로 가져오기 때문에 바로 필드명을 기재함.

 

독자분들은 자신의 필드명에 맞춰서 설정을 하면 됨. 😊

 

그리고 pageable 객체 안의 데이터(sort, page 정보 등)를 이용하여 order by 절을 동적으로 구현함.

 

foreach태그를 쓴 이유는 order by 절이 다수일 수도 있어서 위와 같이 설정함.

 

페이징 처리 또한 pageable 객체를 사용해 동적으로 페이징 처리를 하였음. 끝.🖐

 

 

 

📢참조 사이트 

https://devpad.tistory.com/110

 

스프링부트 개발환경 구성하기 (7) 페이징 (Mybatis에서 Pageable)

포스팅 순서는 아래와 같다. OpenJDK 17 설치 STS 4 설치 스프링부트 프로젝트 생성 메이븐 Local Repository 설정 DB 설계와 REST API 설계 mybatis 연동과 게시판 목록 조회 페이징 (Mybatis에서 Pageable) (현재 포

devpad.tistory.com

 

728x90