Kim VamPa

[Spring][쇼핑몰 프로젝트][31] 검색 구현(조건 검색 적용 -2) 본문

스프링 프레임워크/쇼핑몰 프로젝트

[Spring][쇼핑몰 프로젝트][31] 검색 구현(조건 검색 적용 -2)

Kim VamPa 2021. 8. 31. 18:56
728x90
반응형
프로젝트 Github : https://github.com/sjinjin7/Blog_Project
프로젝트 포스팅 색인(index) : https://kimvampa.tistory.com/188

 

목표

조건 검색을 위해 기존 검색 쿼리를 동적 쿼리로 변환

 

 저번 포스팅에 이어서 동적 쿼리문을 완성하는 것을 목표로 합니다. 

 

 

 

 

순서

1. 동적 쿼리(Oracle)

2. 동적 쿼리(MySQL)

 

 

 

 

 

1. 동적 쿼리(Oracle)

 저의 경우 처음 보았을대 MyBatis를 통해 동적 쿼리를 만드는 것이 많이 헷갈렸습니다. 차근히 하나씩 동적 쿼리를 적용해보겠습니다. 먼저 Oracle 쿼리문을 중점적으로 설명을 하고, MySQL 쿼리문에선 Oracle의 맥락과 거의 같기 때문에 차이점만 말하고자 합니다.

 

 현재의 쿼리문에는 <sql> 태그를 사용하여 getGoodsList() 메서드와 goodsGetTotal() 메서드의 쿼리문에서 공통적으로 적용될 쿼리문을 따로 빼서 작성했었습니다. <sql>태그 내부에 작성한 내용을 일단 모두 지웁니다.

 

 

 진행할 방식은 작성 코드와 해당 코드 작성으로 인해 생성될 예상 쿼리 코드 순으로 소개를 하도록 최대한 노력하겠습니다.

 

 현재의 작성할 쿼리는 '~where'과 'rownum~' 사이에 작성되어야 하는데 조건문에 해당하는 부분이기 때문에 <sql> 태그 내부에 아래와 같이 작성해줍니다. 

 

 

예상 형태는 다음과 같습니다.

 

<-- 예상 쿼리-->
( ) AND

 

 

 검색을 어떠한 조건을 가지고 있는지에 대한 데이터가 typeArr(type 변수의 데이터를 변수로 변환)인데 전달받는 조건에 따라서 조건 코드가 추가되어야 합니다. 따라서 foreEach를 통해서 typeArr에 담긴 요소수만큼 반복되어 작성되도록 먼저 작성해줍니다.

 

그림 1-3

 

※ typeArr의 요소로 존재하는 'A', 'C', 'T' 값들은 그 값 자체로 쿼리 코드(#{type})로 출력이 되는 것이 아니라 쿼리 코드가 실행이 되는 조건(<when test="type == 'A'.toString()">)으로 사용될 것입니다. 

 

 

 저는 'A', 'C', 'T' 데이터의 존재 유무에 따라서 각 검색 조건 쿼리문이 추가되길 바랍니다. <foreach> 태그 내용에 <choose>, <when> 태그를 작성해 줍니다. 

 

그림 1-4

 

 예상 형태는 다음과 같습니다.

 

<-- 예상 쿼리1 -->

(authorId = #{authorId} cateCode LIKE #{cateCode} bookName LIKE #{keyword}) AND

<-- 예상 쿼리1 -->

(authorId = #{authorId}) AND

<-- 예상 쿼리1 -->

(cateCode LIKE #{cateCode}) AND

<-- 예상 쿼리1 -->

( bookName LIKE #{keyword}) AND


<-- 예상 쿼리 -->
<--
AC, AT, CT 경우 생략
-->

 

 

 그런데 각 조건문끼리는 AND로 이어져야 하기 때문에 <trim> 태그를 추가해줍니다.

 

 

 예상 형태는 다음과 같습니다.( 아래는 조건이 ACT, AC인 경우만 작성을 하였고 그 외의 경우는 생략하였습니다.)

 

<-- 예상코드 1-->

(AND authorId = #{authorId} AND cateCode LIKE #{cateCode} AND bookName LIKE #{keyword}) AND

<-- 예상코드 2-->

(AND authorId = #{authorId} AND cateCode LIKE #{cateCode}) AND

<-- 이하생략 -->

 

 

 그런데 문제가 있습니다. 각 쿼리문에 각각 AND가 추가되도록 해주었는데, where의 첫 조건 문에는 AND가 없어야 합니다. 따라서 최상위의 <trim> 태그에 prefixOverrides 속성을 추가해서 제일 앞의 조건문에는 AND를 제거해줍니다.

 

그림 1-6

 

 예상 형태는 다음과 같습니다. (  ACT, AC인 경우만 작성을 하였고 그 외의 경우는 생략하였습니다.)

 

<-- 예상코드 1-->

(authorId = #{authorId} AND cateCode LIKE #{cateCode} AND bookName LIKE #{keyword}) AND

<-- 예상코드 2-->

(authorId = #{authorId} AND cateCode LIKE #{cateCode}) AND

<-- 이하생략 -->

 

 

 작가 검색 조건문에는 한 가지 문제가 있습니다. 조건이 되는 데이터인 authorId는 배열 형태로 전달받아서 여러개일 수 있습니다. 따라서 앞에서 작성한 방식과 같이 <trim>, <foreach>, <trim> 태그를 작성해서 여러 개의 authorId만큼 조건 코드가 추가되도록 아래와 같이 작성하였습니다.

 

 

예상 코드는 다음과 같습니다.( 조건은 AC이고 작가 ID(authorId)가 1개인 경우와 3개인 경우)

 

<-- 예상코드 1-->

((authorId = #{authorId1}) AND cateCode LIKE #{cateCode}) AND

<-- 예상코드 2-->

((authorId = #{authorId1} OR authorId = #{authorId2} OR authorId = #{authorId3) 
AND cateCode LIKE #{cateCode}) AND

<-- 이하생략 -->

 

 

 

전체 동적 쿼리는 다음과 같습니다.

 

	<!-- criteria(검색조건) -->
	<sql id="criteria">

	  	<trim prefix="(" suffix=") AND" prefixOverrides="AND">
	  		<foreach item="type" collection="typeArr">
	  			<trim prefix="AND">
	  				<choose>
	  					<when test="type == 'A'.toString()">
	  						<trim prefixOverrides="or">
			  					<foreach collection="authorArr" item="authorId">
			  						<trim prefix="or">
			  							authorId = #{authorId}
			  						</trim>
			  					</foreach>  						
	  						</trim>
	  					</when>
	  					<when test="type == 'C'.toString()">
	  						cateCode like '%' || #{cateCode} || '%'
	  					</when>  					
	  					<when test="type == 'T'.toString()">
	  						bookName like '%' || #{keyword} || '%'
	  					</when>  					
	  				</choose>
	  			</trim>
	  		</foreach>
	  	</trim>

	</sql>

 

 

 

 

2. 동적 쿼리(MySQL)

 MySQL 쿼리문에서는 rownum 조건문을 사용하지 않고 오직 동적으로 추가될 조건문만 있기 때문에 최상위의 <trim> 태그를 통해 앞에  "WHERE" 키워드가 들어가고 맨뒤에 붙었던 "AND"가 없도록 다음과 같이 작성해주어야 합니다.

 

그림 2-1

 

 그 외에는 동일합니다.

 

 전체 동적 쿼리는 다음과 같습니다.

 

	<!-- criteria(검색조건) -->
	<sql id="criteria">

	  	<trim prefix="where (" suffix=")" prefixOverrides="AND">
	  		<foreach item="type" collection="typeArr">
	  			<trim prefix="AND">
	  				<choose>
	  					<when test="type == 'A'.toString()">
	  						<trim prefixOverrides="or">
			  					<foreach collection="authorArr" item="authorId">
			  						<trim prefix="or">
			  							a.authorId = #{authorId}
			  						</trim>
			  					</foreach>  						
	  						</trim>
	  					</when>
	  					<when test="type == 'C'.toString()">
	  						a.cateCode like concat ('%', #{cateCode}, '%')
	  					</when>  					
	  					<when test="type == 'T'.toString()">
	  						bookName like concat ('%', #{keyword}, '%')
	  					</when>  					
	  				</choose>
	  			</trim>
	  		</foreach>
	  	</trim>
	
	</sql>

 

그림 2-2

 

 작성한 동적 쿼리문이 의도대로 동작하는지 확인하기 위한 테스트는 다음 포스팅에서 진행하겠습니다. 

 

 

REFERENCE

  • 코드로배우는 스프링 웹 프로젝트(남가람북스)
  •  

 

 

 

DATE

  • 2020.08.

 

728x90
반응형
Comments