[2022/11/08 TUE] Spring - MyBatis

kangsun·2022년 11월 8일
0

Spring

목록 보기
5/24

JDBC
MyBatis Framework
데이터베이스를 따로 관리

JPA - ORM 방식
자바 안에서 데이터베이스를 관리. (테이블생성, 제약조건 모두)



- 1인칭, 2인칭, 3인칭 관점
- 프로그램을 완성을 한 뒤 (A,B,C,D,E,F) 배치까지 끝난 상태에서 Z라는 기능을 추가하고싶다면 (재배치) 중간중간 원하는 곳에 넣을 수 있다.
- Z라는 기능이 A 입장에선 after, B입장에선 before

  • before, after라는 개념으로 사용할 수 있다.

잘 활용하진 않는다.


MyBatis

https://sm-studymemo.tistory.com/95


지금까지 sql을 연결 할 땐 모두 string으로 불러온다.
실시간으로 에러를 확인할 수 없다.


MyBatis에서는 이 부분을 외부로 들어낸다.
여기서 sql문이 틀리면 프로그램이 오류를 잡아준다.
그렇게 되면 데이터베이스를 더 쉽게 접근하고 관리할 수 있다.


대신 .xml문서에 작성해야한다. (여는태그, 닫는태그에 코드를 작성한다)
따로 설정을 해줘야한다.
xml문서를 객체화 시켜주는 annotation이 있다.

Mapper XML File

https://www.egovframe.go.kr/wiki/doku.php?id=egovframework:rte2:psl:dataaccess:mapper_xml_files



- 이렇게 작성해준다.

Dynamic SQL

https://www.egovframe.go.kr/wiki/doku.php?id=egovframework:rte2:psl:dataaccess:mybatis_dynamic_sql

  • if 태그도 있다.

    전달된 인자의 특정 property에 대해 if로 비교하는 경우가 가장 많이 사용된다.
	..
	<select id="selectEmployerList" parameterType="egovframework.rte.psl.dataaccess.vo.EmpVO" resultType="egovframework.rte.psl.dataaccess.vo.EmpVO">
		<![CDATA[
			select
				EMP_NO as empNo,
				EMP_NAME as empName,
				JOB as job,
				MGR as mgr,
				HIRE_DATE as hireDate,
				SAL as sal,
				COMM as comm,
				DEPT_NO as deptNo
			from EMP
		]]>
		<where>
			<if test="empNo != null">
				EMP_NO = #{empNo}
			</if>
			<if test="empName != null">
				EMP_NAME LIKE '%' || #{empName} || '%'
			</if>
		</where>
	</select>
  • choose (when, otherwise)
두 가지 값을 모두 제공하지 않는다면 HIRE 상태인 Employee 정보가 리턴될 것이다.

	<select id="selectEmployeeList" parameterType="egovframework.rte.psl.dataaccess.vo.EmpVO" resultType="egovframework.rte.psl.dataaccess.vo.EmpVO">
		SELECT * FROM EMP WHERE JOB = ‘Engineer’
		<choose>
			<when test=”mgr ! null>
				AND MGR like #{mgr}
			</when>
			<when test=”empNo ! null and empName ! =null>
				AND EMP_NAME like #{empName}
			</when>
			<otherwise>
				AND HIRE_STATUS = ‘Y’
			</otherwise>
		</choose>
	</select>
  • trim (where, set)
	..
	<select id="selectEmployerList" parameterType="egovframework.rte.psl.dataaccess.vo.EmpVO"
		resultType="egovframework.rte.psl.dataaccess.vo.EmpVO">
		<![CDATA[
			select
				EMP_NO as empNo,
				EMP_NAME as empName,
				JOB as job,
				MGR as mgr,
				HIRE_DATE as hireDate,
				SAL as sal,
				COMM as comm,
				DEPT_NO as deptNo
			from EMP
		]]>
		<trim prefix="WHERE" prefixOverrides="AND|OR ">
			<if test="empNo != null">
				EMP_NO = #{empNo}
			</if>
			<if test="empName != null">
				EMP_NAME LIKE '%' || #{empName} || '%'
			</if>
		</trim>
	</select>
  • foreach
	<select id="selectJobHistListUsingDynamicNestedIterate" parameterType="egovframework.rte.psl.dataaccess.util.EgovMap" resultMap="jobHistVO">
		<![CDATA[
			select EMP_NO     as empNo,
			       START_DATE as startDate,
			       END_DATE   as endDate,
			       JOB        as job,
			       SAL        as sal,
			       COMM       as comm,
			       DEPT_NO    as deptNo
			from   JOBHIST
		]]>
			where
			<foreach collection="condition" item="item" open="(" separator="and" close=")">
				${item.columnName} ${item.columnOperation} 
				<if test="item.nested == 'true'">
					<foreach item="item" index="index" collection="item.columnValue" open="(" separator="," close=")">
					      '${item}'
					</foreach>
				</if>
				<if test="item.nested != 'true'">
					#{item.columnValue}
				</if>
			</foreach>		
			order by EMP_NO, START_DATE
	</select>
  • 마이바티스 아이디 비번 작성하는 곳

MyBatis 다운로드

http://blog.mybatis.org/
https://mybatis.org/mybatis-3/ko/java-api.html


factory라는 단어가 많이 나오는데, 어떤 걸 만들어줄테니 사용하라는 의미이다. (공장)

이걸 @Bean이 한번에 처리해준다.
의존성 주입.
이와 관련하여 보통 factory라는 이름이 많이 나온다.

다운로드


  • setup폴더에 압축풀기


dyamic Web Project 생성

  • Dynamic Web Project : mybatisTest
  • mybatis-3.4.1.zip 압축을 풀어 'mybatis-3.4.1.jar' 파일을 복사하여 '/WEB-INF/lib' 폴더에 복사

※ 주의사항 : 맥OS 에서는 oraclepki.jar, osdf_cert.jar, osdf_core.jar 추가해야 함


- 배포할 땐 이 구조가 나와야한다.
- classes는 backend단
- views는 front단

  • mybatis-3.4.1.zip 압축을 풀어 'mybatis-3.4.1.jar' 파일을 복사하여 '/WEB-INF/lib' 폴더에 복사
  • net.mem 팩키지 생성 + config 폴더 생성
  • mem_sql.txt 생성 후 테이블 생성
  • config폴더에 xml 파일 생성


    jdbc.xml - 오라클 정보
    mem.xml - insert, delete, select 등 mapper에 관련된 것

jdbc.xml

DBOpen클래스 + DAO클래스 를 한번에 ㅎㅎ

https://www.egovframe.go.kr/wiki/doku.php?id=egovframework:rte2:psl:dataaccess:configuration_xml

  • getting_started

  • 복붙 긁어오기

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapper resource="org/mybatis/example/BlogMapper.xml"/>
  </mappers>
</configuration>



driver, url, username, password을 오라클 아이디 비밀번호로 변경한다.


※ 비밀번호를 변경하면 ?

xml만 배포해주면 된다.
원하는 곳에 annotation만 선언해서 사용하면 된다.

  • mapper에 데이터베이스 연결해주는 jdbc.xml을 넣어줄 파일 경로를 넣어주면 된다.


    이렇게 여러파일을 넣을 수 있음

jdbc.xml

https://www.egovframe.go.kr/wiki/doku.php?id=egovframework:rte2:psl:dataaccess:getting_started

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper   PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
     "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="egovframework.rte.psl.dataaccess.DeptMapper">
	<select id="selectDept" 
                parameterType="int" 
                     resultType="Dept">
		<![CDATA[
			select *
			from   DEPT
			where  DEPT_NO = #{deptNo}
		]]>
	</select>
</mapper>


net.mem

MemDTO.java
MemMainTest.java
클래스 생성

  • DTO 기본생성자, getter,setter


jdbc.xml 로 돌아와서 typeAliases 추가

클래스에 대한 별칭 부여
매개변수로 MemDTO를 사용하도록 설정하는 것이다.

여기까지 환경설정 완료

이제 비밀번호를 변경하면 이 부분만 바꿔주면 된다.


연결 확인 테스트

MemMainTest.java

1) DB연결 환경 설정 파일 가져오기

  • resources 자동완성은 ibatis가 적혀져 있는 것으로 선택해야함.

2) DB연결하기 위한 팩토리빈(factory bean) 생성
- 이전에 배웠던 DBOpen + DAO와 같은 기능이다.

  • run 실행방법 - Java Application

  • 이렇게 의존성을 주입시켜주는 것이다.

    DB연결 시 비밀번호 등 변경을 하려면 (유지보수) jdbc.xml의 내용만 변경해주면 된다.

3) 쿼리문 생성 및 변환

4) 쿼리문 실행
↓ DTO에 생성자 추가 후 다시 작성


MemDTO.java에 생성자 추가


4) 다시 와서 쿼리문 작성


mem.xml

  • 매개변수의 자료형 지정

  • sql 구문 작성


    이렇게 사용할 수 있는 이유 = getter, setter가 있기 때문

  • 확인결과 - ⚠️ 에러남


    오라클 드라이버 연결 안해놔서 그런 것 같습니다.
    sql중 어떤 query인지 모르는거 아닐까요?

    → lib 폴더에 ojdbc8.jar를 추가해준다.

  • 다시 확인



  • SELECT sql문

    원래 하던 방법
    이제 이렇게 하지 않는다
    ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

  • 결과값을 담아준 후
  • rs 이름을 붙여서 매핑시켜준다.
  • 변수가 담겨지는 흐름


MemMainTest.java 에서 결과 확인

  • 변수 담아와서 출력해주기
  • 결과확인

※ type을 다르게 줘도 실행이 된다 하지만 밑에있는 걸 추천

https://www.egovframe.go.kr/wiki/doku.php?id=egovframework:rte2:psl:dataaccess:mapper_xml_files


※ 에러 : 변수 이름을 다르게 주었을 때

  • insert 문의 DTO 변수 이름과 다르게 주었을 때




  • resultMap의 property에 DTO명을 다르게 주었을 때


==> DTO 설정이 굉장히 중요하다.

DTO가 없었으면 그냥 #{n} 으로 작성해도 되는데
매개변수가 DTO이기 때문에 반드시 DTO에서 설정한 변수이름을 사용해줘야 한다


행수정

1) MemMainTest.java 수정할 값 먼저 작성

오류


행삭제

1) MemMainTest.java 수정할 값 먼저 작성

2) mem.xml 에서 sql문 작성


※ 연산자 작성 시 유의사항

xml 페이지에서는 열고닫는 태그를 이용해서 구성을 하는데, 연산자를 넣게되면 태그인지, 연산자인지 구분을 해줘야한다.

이걸 사용해주면 꺽쇠기호를 연산자로 처리해준다.

  • 실행 결과

검색

1) MemMainTest.java

2) mem.xml

  • '화' 변수처리

행 상세보기

1) MemMainTest.java

2) mem.xml



전체 행 개수


 MyBatis3 동적 SQL (Oracle, MySQL)
 
[MyBatis-3 Dynamic SQL]

 

※ Dynamic SQL

  - 일반적으로 JDBC API를 사용한 코딩에서 다양한 조건에 따라 다양한 형태의 쿼리의 실행이 필요한 경우가 존재하며
    이에 MyBatis는 강력한 동적 SQL 언어를 제공한다.

  - MyBatis에서 제공하는 동적 SQL 요소들은 JSTL 이나 XML 기반의 텍스트 프로세서와 유사한 형태로 제공되며
    OGNL 기반의 표현식을 제공함으로써 보다 유연하고 편리하게 Dynamic 요소를 사용할 수 있다.

  - 전자정부 표준 프레임워크 참조

    http://www.egovframe.go.kr/wiki/doku.php?id=egovframework:rte2:psl:dataaccess:mybatis_dynamic_sql

 

 

1. 일반적인 SQL 사용

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace = "member">
  <select id='checkId' resultType='int' parameterType='String'>
    SELECT COUNT(id) as cnt
    FROM member
    WHERE id=#{id}
  </select>

  <insert id="create" parameterType="MemberVO">
    INSERT INTO member(mno, id, passwd, mname, tel, zipcode, address1, address2, mdate)
    VALUES ((SELECT NVL(MAX(mno), 0)+1 as mno FROM member),
    #{id}, #{passwd}, #{mname}, #{tel}, #{zipcode}, #{address1}, #{address2}, sysdate)
  </insert>
 
  <!-- 검색을하지 않는 전체 목록 -->
  <select id="list" resultType="MemberVO">
    SELECT mno, id, passwd, mname, tel, zipcode, address1, address2, mdate
    FROM member
    ORDER BY mno ASC
  </select>

  <!-- 조회 -->
  <select id="read" resultType="MemberVO" parameterType="int">
    SELECT mno, id, passwd, mname, tel, zipcode, address1, address2, mdate
    FROM member
    WHERE mno = #{mno}
  </select>

  <update id="update" parameterType="MemberVO">
    UPDATE member
    SET mname=#{mname}, tel=#{tel}, zipcode=#{zipcode},
          address1=#{address1}, address2=#{address2}
    WHERE mno=#{mno}
  </update> 

  <select id="passwdCheck" resultType="int" parameterType="Map">
    SELECT COUNT(mno) as cnt
    FROM member
    WHERE mno=#{mno} AND passwd=#{passwd}
  </select>

  <update id="update_passwd" parameterType="Map">
    UPDATE member
    SET passwd=#{passwd}
    WHERE mno=#{mno}
  </update>

  <delete id="delete" parameterType="int">
    DELETE FROM member
    WHERE mno=#{mno}
  </delete> 
 
  <select id="login" resultType="int" parameterType="MemberVO">
    SELECT COUNT(mno) as cnt
    FROM member
    WHERE id=#{id} AND passwd=#{passwd}
  </select>

</mapper>

 


2. 동적인 SQL 사용 (Oracle)

1) WHERE를 분리한 경우
 
  <select id="list3" resultType="BlogVO" parameterType="HashMap">
    SELECT blogno, blogcategoryno, title, content, good, file1, file2, size2, cnt, replycnt, rdate
    FROM blog
    WHERE blogcategoryno=#{blogcategoryno}
   
    <choose>
      <when test="col == 'title'">
        AND title LIKE '%' || #{word} || '%'
      </when>
      <when test="col == 'content'">
        AND content LIKE '%' || #{word} || '%'
      </when>
      <when test="col == 'title_content'">
        AND title LIKE '%' || #{word} || '%' OR content LIKE '%' || #{word} || '%'
      </when>
    </choose>
   
    ORDER BY blogno DESC
  </select>

   
  <select id="count" resultType="int" parameterType="HashMap">
      SELECT COUNT(*) as cnt
      FROM blog
      WHERE blogcategoryno=#{blogcategoryno}
     
    <choose>
      <when test="col == 'title'">
        AND title LIKE '%' || #{word} || '%'
      </when>
      <when test="col == 'content'">
        AND content LIKE '%' || #{word} || '%'
      </when>
      <when test="col == 'title_content'">
        AND title LIKE '%' || #{word} || '%' OR content LIKE '%' || #{word} || '%'
      </when>
    </choose>    
  </select>     
           


  <!-- ********** 검색, 페이징 시작 ********** -->
  <select id="list" resultType="BlogVO" parameterType="HashMap" >
  SELECT blogno, title, good, thumb, file1, size1, cnt, rdate, r
  FROM(
           SELECT blogno, title, good, thumb, file1, size1, cnt, rdate, rownum as r
           FROM(
                    SELECT blogno, title, good, thumb, file1, size1, cnt, rdate
                    FROM blog
                    <choose>
                        <when test="col == 'title'">
                           WHERE title LIKE '%' || #{word} || '%'
                        </when>
                        <when test="col == 'content'">
                           WHERE content LIKE '%' || #{word} || '%'
                        </when>
                        <when test="col == 'title_content'">
                           WHERE title LIKE '%' || #{word} || '%'  OR content LIKE '%' || #{word} || '%'
                        </when>     
                      </choose>
                      ORDER BY blogno DESC
             )
    )
    WHERE <![CDATA[r >=#{startNum} AND r <= #{endNum}]]>
  </select> 
    
  <!-- ********** 검색, 페이징 종료 ********** -->


     

2) WHERE를 명시한 경우

  <select id="list3" resultType="BlogVO" parameterType="HashMap">
    SELECT blogno, blogcategoryno, title, content, good, file1, file2, size2, cnt, replycnt, rdate
    FROM blog
    WHERE blogcategoryno=#{blogcategoryno}
   
    <where>
      <choose>
        <when test="col == 'title'">
          AND title LIKE '%' || #{word} || '%'
        </when>
        <when test="col == 'content'">
          AND content LIKE '%' || #{word} || '%'
        </when>
        <when test="col == 'title_content'">
          AND title LIKE '%' || #{word} || '%' OR content LIKE '%' || #{word} || '%'
        </when>
      </choose>
    <where>
   
    ORDER BY blogno DESC
  </select>
         
  <select id="count" resultType="int" parameterType="HashMap">
      SELECT COUNT(*) as cnt
      FROM blog
      WHERE blogcategoryno=#{blogcategoryno}
     
      <where>
      <choose>
        <when test="col == 'title'">
          AND title LIKE '%' || #{word} || '%'
        </when>
        <when test="col == 'content'">
          AND content LIKE '%' || #{word} || '%'
        </when>
        <when test="col == 'title_content'">
          AND title LIKE '%' || #{word} || '%' OR content LIKE '%' || #{word} || '%'
        </when>
      </choose>
    </where>     
  </select>          

     


     
3. 동적인 SQL 사용 (MySQL)

------------------------------------------------- notice.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 
<!-- namespace는 인터페이스가 와야함.
    interface NoticeMapper{} --> 
<mapper namespace="kr.co.mango.notice.NoticeMapper">
 
  <select id="getArticleList" resultType="NoticeDTO" parameterType="hashmap" >
      SELECT noticeno, nobigclass, nosubclass, subject, content, regDate,hits
      FROM notice
      WHERE  noticeno > 0
      <!-- 공지사항(1)/ FAQ(2) -->
      <choose>
        <when test="nobigclass != '' ">
           AND  nobigclass = #{nobigclass}    
        </when>      
    </choose>
      <!-- 검색조건 -->    
      <choose>
        <when test="word != '' and col.equals('subject')">
           AND  subject like CONCAT('%',#{word},'%')    
        </when>
        <when test="word != '' and col.equals('content')">
           AND content like CONCAT('%',#{word},'%')    
        </when>
        <when test="word != '' and col.equals('subject_content')">
           AND subject like CONCAT('%',#{word},'%') OR content like CONCAT('%',#{word},'%')    
        </when>
    </choose>
      ORDER BY noticeno  DESC       
      LIMIT <![CDATA[#{start}, #{end}]]>
  </select>
  
   <select id="getCount"  resultType="java.lang.Integer" parameterType="hashmap" >   
        SELECT COUNT(*)
        FROM notice     
        WHERE  noticeno > 0
                          
        <if test="col == 'subject'  and word!=''">            
            AND  subject like CONCAT('%',#{word},'%')              
        </if>
        <if test="col == 'content'  and word!=''">           
             AND content like CONCAT('%',#{word},'%')
        </if>
        <if test="col == 'subject_content'  and word!=''">            
             AND subject like CONCAT('%',#{word},'%') OR content like CONCAT('%',#{word},'%')
        </if>     
    </select>
   
  <insert id="create" parameterType="NoticeDTO">     
        INSERT INTO notice (nobigclass, nosubclass, subject, content, regDate, modDate)
        VALUES (#{nobigclass}, #{nosubclass}, #{subject}, #{content}, now(), now())
  </insert>
 
  <select id="read" parameterType="int"  resultType="NoticeDTO">
      SELECT noticeno, nobigclass, nosubclass, subject, content, regDate
      FROM notice
      WHERE noticeno = #{noticeno}
  </select>
 
  <update id="update" parameterType="NoticeDTO">
      UPDATE notice SET
      nobigclass =  #{nobigclass},
      nosubclass = #{nosubclass},
      subject = #{subject},
      content = #{content},
      modDate = now()    
      WHERE noticeno = #{noticeno}
  </update>
 
  <delete id="delete" parameterType="int">
      DELETE FROM notice
      WHERE noticeno = #{noticeno}
  </delete>
  
</mapper>




Spring starter 생성



group과 Artifact 는 저렇게 생성해줘야한다. (이전 것 틀림)


  • 팩키지 생성
  • interface 생성

    추상메서드, 본체가 없는 메소드
  • class 생성 (MessageKO, MessageEN)

  • HelloPOJO.java class 생성해서 출력 확인


  • resources폴더에 springbean.xml파일 생성


  • springbean.xml 등록
  • HelloBean.java 로 결과 출력 값 넣어주기






springbean.xml 에서
kr.co.itwill.di.MessageKO2
kr.co.itwill.di.MessageEN2
내용을 바꾸어도
다른 페이지는 수정할 곳이 없다.

다른 페이지와의 의존성을 줄이는 것이다.

















졸업프로젝트 시 데이터 선택

profile
코딩 공부 💻

0개의 댓글