본문 바로가기

카테고리 없음

[코드로 배우는 스프링 웹 프로젝트] ch15 검색 처리 2(type, keyword)

728x90
반응형

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를 통해 동일한 내용은 반복해서 사용할 수 있네요!!

 

이어서 검색 기능을 구현해보겠습니다!!

 

많은 분들의 피드백은 언제나 환영합니다!  많은 댓글 부탁드려요~~

 

728x90
반응형