본문 바로가기
seok

프로젝트 MyBatis

by shulk 2024. 6. 3.

1.SELECT @RNUM := @RNUM +1

@RNUM은 sql문에서 임시로 사용하는 변수이고 := 는 일반 프로그래밍 언어에서 = 대입 연산자를 mysql에서는 := 게 한다.

 

2. resultMap 설정에서 property와 column 속성,<association> 태그,<collection> 태그

property는 자바 객체의 필드이고, column은 SQL 쿼리 결과의 열 이름 또는 별칭입니다. MyBatis는 이 이름을 사용하여 SQL 쿼리 결과를 식별합니다.

 

예를들어 DB에 해당 테이블 컬럼 이름은 img_name_check이고 ImageVo객체 반환할때 어떤 필드의 이름이 img_name 일경우 

셀렉문에 img_name_check는 실제 DB의 컬럼 이름이고, AS에 list_img_name_kor은 resultMap에 list_img_name_kor는 img_name으로 매핑하기로 해서 ImageVo의 img_name에 잘 대입된다

<resultMap id="listImgKorResultMap" type="ImageVo">
    <id property="idx" column="list_img_idx_kor"/>
    <result property="img_path" column="list_img_path_kor"/>
    <result property="img_name" column="list_img_name_kor"/> <!-- 매핑된 별칭 사용 -->
    <result property="width" column="list_img_width_kor"/>
    <result property="height" column="list_img_height_kor"/>
</resultMap>

==========================================================================
SELECT
    CONTENTS.*
    ,img_name_check AS list_img_name_kor <!-- resultMap 별칭 사용 -->
FROM 생략

 

만약 resultMap을 사용 안하고 자바 객체의 필드 이름은 img_name이고 DB실제 해당 컬럼의 이름은 ing_gg이면 셀렉문에

Ing_gg As img_name 하면 된다

 

<association> 태그는 MyBatis의 resultMap에서 사용되는 태그로, 복잡한 객체 관계를 매핑할 때 사용됩니다. 주로 한 객체가 다른 객체를 포함하는 경우에 사용됩니다[일대일 관계] .이는 데이터베이스의 여러 테이블 간의 관계를 반영하여, 한 객체가 다른 객체와 연관되어 있는 경우에 해당 연관된 객체를 함께 로드할 수 있도록 합니다.

 

property="commentVO":  CommentUserDTO 객체 내의 commentVO 필드. 이 필드는 다른 객체(CommentVO)를 참조합니다.

 

resultMap 태그안 id는 select,insert,update,delete와 같은 태그에서 resultMap으로 설정한 필드명들을 사용하기위해 하는거다.

예를들어 select에서 저 resultMap 사용할경우 이렇게 한다.

<select id="findAllByString" resultType="Order" resultMap="commentUserDTO"> 
</select>
<resultMap type="com.moviepedia.domain.CommentUserDTO" id="commentUserDTO">
    <result property="userName" column="username"/>
    <result property="starRating" column="starrating"/>
    <association property="commentVO" javaType="com.moviepedia.domain.CommentVO">
        <id property="commentCd" column="commentcd"/>
        <result property="movieCd" column="moviecd"/>
        <result property="userid" column="userid"/>
   </association>
</resultMap>

 

<collection>은 객체 간의 일대다(일대많은) 관계를 매핑할 때 사용됩니다. 예를 들어, Order 객체가 여러 개의 OrderItem 객체를 포함하는 경우에 사용됩니다.

 

3. 임베디드 타입이 있을경우  

resultMap을 사용하여 명시적으로 매핑해야한다.(sql select문에 전체 * 하면 안되고 직접 다 적어야한다 m.city , m.street, m.zipcode)

예를들어 멤버안에 임베디드 주소 있는데 조회할 경우 

<resultMap id="MemberResultMap" type="Member">
        <id property="id" column="member_id"/>
        <result property="name" column="name"/>
        <association property="address" javaType="Address">
            <result property="city" column="city"/>
            <result property="street" column="street"/>
            <result property="zipcode" column="zipcode"/>
        </association>
    </resultMap>

    <select id="findMember" resultMap="MemberResultMap">
        SELECT
            m.member_id,
            m.name,
            m.city,
            m.street,
            m.zipcode
        FROM Member m
        WHERE m.member_id = 1
    </select>

 

4.  MyBatis에서 객체를 생성할 때 사용하는 생성자의 인자를 매핑하는 역할 <constructor>

예를들어 반환타입이 DTO이고 생성자에 이렇게 받는다면 resultmap에서 <constructor> 이용한다.  

Long orderId, String name, LocalDateTime orderDate, Address address
<resultMap id="OrderDtoResultMap" type="OrderSimpleQueryDto">
        <result property="orderId" column="order_id"/>
        <result property="name" column="name"/>
        <result property="orderDate" column="ORDER_DATE"/>
        <association property="address" javaType="Address">
            <constructor>
                <arg column="city" javaType="java.lang.String"/>
                <arg column="street" javaType="java.lang.String"/>
                <arg column="zipcode" javaType="java.lang.String"/>
            </constructor>
        </association>
</resultMap>

<arg>는 SQL 쿼리 결과의 특정 컬럼을 해당 생성자 인자에 바인딩한다.

 

5.  MyBatis로 조회후 반환 객체에 생성자 방식 말고 setter로 할경우 

4번 처럼 DTO에 생성자가 없고 setter만 있는경우

<result> 태그를 사용하여 매핑하면, MyBatis가 SQL 쿼리 결과에서 읽은 데이터를 자동으로 각각의 필드를 해당 setter 메소드를 호출하여 설정한다.

<resultMap id="OrderDtoResultMap" type="OrderSimpleQueryDto">
    <result property="orderId" column="order_id"/>
    <result property="name" column="name"/>
    <result property="orderDate" column="ORDER_DATE"/>
    <association property="address" javaType="Address">
        <result property="city" column="city"/>
        <result property="street" column="street"/>
        <result property="zipcode" column="zipcode"/>
    </association>
</resultMap>

 

6.  <choose>, <when>, <otherwise>

 

<choose>, <when>, <otherwise>는 MyBatis에서 조건부 논리를 구현하기 위해 사용되는 태그이고 

<choose>

<choose>는 여러 개의 조건문 중 하나를 선택하여 실행할 수 있는 태그입니다. Java의 switch문이나 XML의 <xsl:choose>와 유사합니다. <choose> 안에는 <when> 태그와 <otherwise> 태그가 포함됩니다.

<when>

<when> 태그는 조건을 정의하는 데 사용됩니다. 각 <when> 태그는 test 속성을 가지고 있으며, 이 속성에는 평가될 조건이 포함됩니다. test 속성이 참일 경우, 해당 <when> 블록 안의 SQL이 실행됩니다.

<otherwise>

<otherwise> 태그는 모든 <when> 조건이 거짓일 때 실행될 SQL을 정의합니다. Java의 default문과 유사합니다.

 

7.  DB의 여러 컬럼에 해당값 데이터 있는지 검색할때 => OR 사용

예를들어 Search_text가 이메일 아니면 이름 일때 DB의 이메일 이랑 이름 컬럼에 동시에 Search_text값이 있는지 검색한다면

NAME = #{search_text} OR EMAIL = #{search_text}

8.  MYSQL일때 DB에 암호화상태로 저장, 복호화해서 가져오기

암호화 하면서 저장할땐 AES_ENCRYPT 함수 이용하고,복호화 할땐 AES_DECRYPT 함수 이용한다.

하지만 MySQL에서 AES_DECRYPT 함수는 바이너리 데이터를 반환하므로, 이 반환값을 문자열로 변환해야 합니다. 이를 위해 MySQL의 CONVERT 함수를 사용하여 UTF-8 문자열로 변환할 수 있습니다.

<insert id="insertAdminUser" parameterType="AdminUserVo">
    INSERT INTO TB_ADMIN (
        ID, 
        EMAIL, 
        PASSWORD, 
        MOBILE_PHONE, 
        NAME, 
        ROLE_TYPE, 
        STATUS
    ) VALUES (
        #{id}, 
        AES_ENCRYPT(#{email}, 'your_secret_key'), 
        #{password}, 
        #{mobilePhone}, 
        #{name}, 
        #{roleType}, 
        #{status}
    )
</insert>
<select id="getAdminUserById" resultType="AdminUserVo">
    SELECT 
        ID, 
        CONVERT(AES_DECRYPT(EMAIL, 'your_secret_key') USING utf8) AS EMAIL, 
        PASSWORD, 
        MOBILE_PHONE, 
        NAME, 
        ROLE_TYPE, 
        STATUS
    FROM 
        TB_ADMIN
    WHERE 
        ID = #{id}
</select>

 

9.  Where의 In 사용하는 방법

처음에는 그냥 이렇게만 하면 되는줄 알았는데 아니였다.

where TAG_IDX IN #{tagList}

마이바티스는 foreach를 사용해서 컬렉션을 in문에 넣어주는 방식으로 해야한다.

where TAG_IDX IN
        <foreach item="tag" collection="tagList" open="(" separator="," close=")">
            #{tag}
        </foreach>
    • item: 반복 중 각 요소를 가리키는 변수 이름입니다.
    • collection: 반복할 컬렉션입니다.
    • open, separator, close: IN 절의 구문을 구성하는 속성입니다.

이 설정을 통해 tagList의 각 요소가 IN 절에 올바르게 포함되도록 할 수 있습니다. 따라서 #{tagList}를 직접 사용하는 대신 foreach 태그를 사용하여 각 요소를 반복하고 이를 IN 절에 추가합니다.

 

10.  쿼리문에서 사용하는 임시 변수,foreach문의 index

foreach태그안 인덱스라는게 있는데 0부터 시작하고 if 조건문 보면 tagList의 사이즈 -1 이랑 인덱스랑 같으면 조건 걸었는데 -1한 이유는 당연 인덱스가 0부터 시작하니 그렇다.

그러고 이제 조건문 참일때 보면 bind는 쿼리문에서 사용하는 임시변수 설정하는거다. value에 +1 한 이유는 당연 실제 임시변수에 실제 사이즈를 넣을거니 그렇다.

  <if test="tagList != null and tagList.size() > 0">
            AND CONTENTS.IDX IN (
            SELECT EXHIBIT_CONTENTS_IDX
            FROM TB_EXHIBIT_TAG
            WHERE TAG_IDX IN
            <foreach collection="tagList" item="tag" index="index" open="(" separator="," close=")">
                #{tag}
                <if test="index == tagList.size() - 1">
                    <bind name="tagListSize" value="index + 1"/>
                </if>
            </foreach>
            GROUP BY EXHIBIT_CONTENTS_IDX
            HAVING COUNT(DISTINCT TAG_IDX) = #{tagListSize}
            )
        </if>

 

 

IDX //  EXHIBIT_CONTENTS_IDX // TAG_IDX
1                    920                                   10

2                    920                                   17

3                    922                                   10

추가로 위에 데이터로 쿼리문을 해석해보면 예를들어 tagList에는 10,17이 들어있고 일단 foreach문에 의해 10만 있는데이터던 17만 이는 데이터던 10,17있는 데이터 다 가져오니 920,922 다 가져오고,

Group By에 의해 920 내부에는 2개가 있는데 그다음 Having의 갯수 비교로 인해 920은 참이니 가져오고

922은 Group By에 의해 내부에 한개만 있는데 Having에서 거짓이니 안가져온다

'seok' 카테고리의 다른 글

결합도와 응집도  (0) 2024.06.25
테스트용-데이터베이스를 임베디드 모드  (0) 2024.05.31
Querydsl프로젝트 설정,여러팁/비공개  (0) 2024.03.27