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 |