ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • mybatis: resultMap ( 1:1 / 1:n select )
    기타 2023. 6. 21. 09:25

    이번 프로젝트에서는 DB를 기능마다 나눠서, 기능을 추가하거나 데이터를 관리하기 편리하게

    다음과 같이 설계했다.

     

    다만 데이터를 select 하는데 있어서 두 가지 방법에 대해 이해가 필요했다

     

    1 : 1 관계

    두 가지 테이블을 join 할 때, 각 각 한 개의 행끼리 매치가 되도록 만드는 것이다.

    위의 erd에서는 주문 테이블과 주문취소 테이블이 1:1 방법이다.

     

    1개의 주문에는 해당 주문이 취소되었는지 아닌지 확인하는 주문 취소 열이 필요하다.

    SELECT
    	*
    FROM `order` o
    JOIN order_cancel oc ON o.order_id = oc.order_id
    WHERE oc.state = 'normal'

    이렇게 쿼리문을 작성하면, 주문 테이블과 주문 취소 테이블을 order_id 값을 기준으로 조인하고

    주문 취소 테이블의 state 열의 값이 'normal'인 경우의 데이터만 select 할 수 있다.

    결과로, 1개의 행에 주문에 대한 정보와 주문 취소 여부가 나타나게 된다.

     

     

    1 : n 관계

    특정 테이블의 1개의 행과 다른 테이블의 여러개의 행이 관계성을 가질 때는 조금 복잡해진다.

    예를 들어서 1개의 주문에는 여러개의 주문된 제품과 제품의 갯수가 존재한다.

    SELECT
    	*
    FROM `order` o
    JOIN order_product oc ON o.order_id = op.order_id

    해당 쿼리문을 실행시키면 1개의 주문 정보와 여러개의 ( 제품, 구매 수량 ) 데이터를 가지기 때문에

    select의 결과로 여러개의 행을 불러온다.

     

    다음과 같은 경우, resultMap을 사용해서 중복되는 데이터 (주문 정보) 를 하나로 만들고

    여러개의 데이터 ( 제품, 구매 수량 ) 을 LIST 형태로 저장해서

    1개의 VO에 저장할 수 있다.

     

    resultMap 사용하기

    <!-- 출하 계획표 불러오기 -->
    	<select id="list" resultMap="adminOrderResultMap">
    		SELECT
    			o.order_id AS orderId,
    			DATE_FORMAT(o.delivery_date, '%Y-%m-%d') AS deliveryDate,
    			DATE_FORMAT(o.order_date, '%Y-%m-%d') AS orderDate,
    			c.hospital AS hospital,
    			c.name AS name,
    			c.address AS address,
    			c.email AS email,
    			c.phone AS phone
    		FROM `order` o
    		JOIN order_cancel oc ON o.order_id = oc.order_id
    		JOIN customer c ON o.customer_id = c.customer_id
    		WHERE oc.state = 'normal'
    			<choose>
    				<when test="orderId != 0">
    					AND o.order_id = #{orderId}
    				</when>
    			</choose>
    		ORDER BY o.order_id DESC
    		<!-- LIMIT ${(pageNum-1)*amount}, #{amount} -->
    	</select>
    	<!-- 주문한 물건 목록 불러오기 (이름, 갯수) -->
    	<select id="selectOrderedProductList" parameterType="control.suppliers.model.AdminOrderVO" resultType="control.suppliers.model.OrderedProductVO">
    		Select
    			op.count AS count,
    			p.name AS product,
    			p.code AS code,
    			p.count AS stock,
    			p.tax AS tax,
    			p.price AS price
    		From ordered_product op
    		LEFT JOIN product p ON op.product_id = p.product_id
    		WHERE op.order_id = #{orderId}
    	</select>

    프로젝트에서 사용했던 쿼리문이다.

    해당 쿼리문을 사용해서, 주문에 대한 정보(1개)와 주문 된 물건들에 대한 정보, 물건의 갯수 등(여러개)을 조회하고 싶었다.

     

    우선은, 주문에 대한 정보를 select 하기 위해 list쿼리의 결과물을 resultMap으로 설정했고

    <!-- 출하 계획표 resultMaps -->
    <resultMap id="adminOrderResultMap" type="control.suppliers.model.AdminOrderVO">
        <id property="orderId" column="orderId" javaType="int"/>
        <result property="deliveryDate" column="deliveryDate" javaType="String"/>
        <result property="orderDate" column="orderDate" javaType="String"/>
        <result property="hospital" column="hospital" javaType="String"/>
        <result property="name" column="name" javaType="String"/>
        <result property="address" column="address" javaType="String"/>
        <result property="email" column="email" javaType="String"/>
        <result property="phone" column="phone" javaType="String"/>
        <collection column="orderId = orderId" property="orderedProduct" javaType="List"
        ofType="control.suppliers.model.OrderedProductVO" select="selectOrderedProductList"/>
    </resultMap>

    resultMap을 작성했다.

     

    id 태그 : 해당 resultMap데이터의 key (index)가 될 column을 로 설정해야한다.

    위의 코드에서는 주문번호로 설정했다.

    property에는 해당 데이터가 저장될 변수명을 작성하고, column에는 데이터를 가져올 열의 이름을 작성했다.

     

    result 태그 : 단 하나의 데이터를 저장하는데 사용했다. 이 코드에서는 주문 1개에 대한 정보를 result 태그에 저장했다

     

    collection 태그 : 해당 태그는 여러개의 데이터를 List 형태로 저장할 수 있다.

    이 코드에서는 collection 태그의 결과물의 타입을 ofType으로 VO를 지정했고, VO에 넣을 데이터를 select 문을 새로 연결해서 가져오도록 만들었다.

    만약 select 문을 사용하지 않으면, list 쿼리문의 테이터를 id 나 result 형태로 가져올 수 있다.

     

    또한 resultMap을 사용할 때는 꼭 태그들의 순서를 지켜야한다 ( 위의 코드에서 id - result - collection 순서가 지켜지지 않으면 에러가 발생한다. )

     

    resultMap의 결과물은

    이 VO에 저장해서 사용할 수 있다.

     

    '기타' 카테고리의 다른 글

    스크래핑 시 쿠키 받아오기  (0) 2023.08.25
    스크래핑 기초  (0) 2023.08.09
    if문과 논리연산자  (0) 2023.06.15
    코드 포맷터 ( Prettier ) 사용하기  (0) 2023.06.15
    ajax를 사용하지 않는 방법 생각해보기  (1) 2023.06.12
Designed by Tistory.