▷ 페이징 처리에 검색 조건 처리가 들어가면 Criteria의 변화가 필요(기존은 pageNum, amount 라는 파라미터 수집)
◎ Criteria.java 클래스 수정(내용 추가)
public class Criteria {
...(생략)...
private String type;
private String keyword;
...(생략)...
public String[] getTypeArr() {
return type == null? new String[] {}: type.split("");
}
}
▷ Criteria 클래스는 type과 keyword라는 변수를 추가 ▷getter, setter는 Lombok을 통해 생성하고, getTypeArr는 검색 조건이 각 글자(T, W, C)로 구성 됨 ▷검색 조건을 배열로 만들어 한 번에 처리하기 위함 ▷getTypeArr() 이용해 MyBatis의 동적 태그 활용 가능
(1) BoardMapper.xml에서 Criteria 처리
▷ BoardMapper.xml은 기존의 getListWithPaging()을 수정해 동적 SQL 처리
◎ BoardMapper.xml 내용 수정
▷ 검색 및 페이징 처리 수정
<select id="getListWithPaging" resultType="org.codehows.domain.BoardVO">
<![CDATA[
select
bno, title, content, writer, regdate, updatedate
from
(
select /*+ INDEX_DESC(tbl_board pk_board) */
rownum rn, bno, title, content, writer, regdate, updatedate
from
tbl_board
where
]]>
<trim prefix="(" suffix =") AND " prefixOverrides="OR">
<foreach item='type' collection="typeArr">
<trim prefix="OR">
<choose>
<when test="type == 'T'.toString()">
title like '%' || #{keyword} || '%'
</when>
<when test="type == 'C'.toString()">
title like '%' || #{keyword} || '%'
</when>
<when test="type == 'W'.toString()">
title like '%' || #{keyword} || '%'
</when>
</choose>
</trim>
</foreach>
</trim>
<![CDATA[
rownum <= #{pageNum} * #{amount}
)
where rn > (#{pageNum}-1) * #{amount}
]]>
</select>
▷ 검색 조건이 3가지이므로 총 6가지 조합이 가능하지만, 각 문자열을 이용해 검색 조건을 결합하는 형태로 하면 3개의 동적 SQL 구문만으로도 처리를 할 수 있음
▷ <foreach>를 이용해 검색 조건들을 처리하는데 typeArr라는 속성을 이용 ▷ MyBatis는 원하는 속성을 찾을 때 getTypeArr()와 같이 이름에 기반을 두어 검색하기 때문에 Criteria에서 만들어둔 getTypeArr() 결과인 문자열의 배열이 <foreach>의 대상이 됨 ▶ MyBatis는 엄격하게 Java Beans의 규칙을 따르지 않고 get/set 메소드만을 활용하는 방식
▷<choose> 안쪽의 동적 SQL은 'OR title ... OR content ... OR write ...' 와 같은 구문을 만들어 냄 ▷바깥쪽에서는 <trim>을 이용해서 맨 앞에 생성되는 'OR'를 없애줌
◎ BoardMapperTests.java 클래스 수정
▷ 동적 SQL은 경우에 따라 여러 종류의 SQL이 생성될 수 있으므로 제대로 동작하는지 여러 번의 확인을 거쳐야 함
...(생략)...
@Test
public void testSearch() {
Criteria cri = new Criteria();
cri.setKeyword("새로");
cri.setType("TC");
List<BoardVO> list = mapper.getListWithPaging(cri);
list.forEach(board -> log.info(board));
}
...(생략)...
▷ testSearch()는 Criteria 객체의 type과 keyword를 넣어 원하는 SQL이 생성되는지 확인하기 위함
◎ 조건에 따른 출력 결과 확인
◎ sql, include와 검색 데이터의 개수 처리
▷ 동적 SQL을 이용해 검색 조건을 처리하는 부분은 해당 데이터 개수를 처리하는 부분에서도 동일하게 적용
▷ 동적 SQL을 수정하는 경우 매번 목록을 가져오는 SQL과 데이터 개수를 처리하는 SQL 쪽을 같이 수정해야 함
◎ BoardMapper.xml 내용 추가
▷ MyBatis는 <sql>이라는 태그를 이용해 SQL의 일부를 별도로 보관하고, 필요한 경우 include
<sql id="criteria">
<trim prefix="(" suffix=") AND " prefixOverrides="OR">
<foreach item='type' collection="typeArr">
<trim prefix="OR">
<choose>
<when test="type == 'T'.toString()">
title like '%'||#{keyword}||'%'
</when>
<when test="type == 'C'.toString()">
content like '%'||#{keyword}||'%'
</when>
<when test="type == 'W'.toString()">
writer like '%'||#{keyword}||'%'
</when>
</choose>
</trim>
</foreach>
</trim>
</sql>
<select id="getListWithPaging"
resultType="org.codehows.domain.BoardVO">
<![CDATA[
select
bno, title, content, writer, regdate, updatedate
from
(
select /*+ INDEX_DESC(tbl_board pk_board) */
rownum rn, bno, title, content, writer, regdate, updatedate
from
tbl_board
where
]]>
<include refid="criteria"></include>
<![CDATA[
rownum <= #{pageNum} * #{amount}
)
where rn > (#{pageNum}-1) * #{amount}
]]>
</select>
<select id="getTotalCount" resultType="int">
select count(*) from tbl_board
where
<include refid="criteria"></include>
bno > 0
</select>
별도의 sql을 만들고 id(criteria)를 별도로 생성해 이후 select 구문에서 사용시 include 해줍니다.
동일한 id를 여러 곳에서 include 할 수도 있습니다.
검색 기능을 이용하기 위해서 Criteria 클래스에 type, keyword 변수를 추가했고 확실하게 구분할 수 있도록 만들었습니다.
xml의 sql 구문 사이에 trim을 통해서 조건을 추가해도 좋습니다.
마지막으로 id를 생성해 select 구문에서 사용시 include를 통해 동일한 내용은 반복해서 사용할 수 있네요!!