https://bobo12.tistory.com/311
3. 검색 조건 처리를 위한 Criteria의 변화
▷ 페이징 처리에 검색 조건 처리가 들어가면 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를 통해 동일한 내용은 반복해서 사용할 수 있네요!!
이어서 검색 기능을 구현해보겠습니다!!
많은 분들의 피드백은 언제나 환영합니다! 많은 댓글 부탁드려요~~