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



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

잘 활용하진 않는다.

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

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

대신 .xml문서에 작성해야한다. (여는태그, 닫는태그에 코드를 작성한다)
따로 설정을 해줘야한다.
xml문서를 객체화 시켜주는 annotation이 있다.
https://www.egovframe.go.kr/wiki/doku.php?id=egovframework:rte2:psl:dataaccess:mapper_xml_files


- 이렇게 작성해준다.
https://www.egovframe.go.kr/wiki/doku.php?id=egovframework:rte2:psl:dataaccess:mybatis_dynamic_sql

	..
	<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>

두 가지 값을 모두 제공하지 않는다면 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>

	..
	<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>

	<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>

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

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

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




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

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






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만 선언해서 사용하면 된다.


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>

MemDTO.java
MemMainTest.java
클래스 생성


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

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

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


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

run 실행방법 - Java Application


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

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

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

4) 다시 와서 쿼리문 작성

















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

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






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

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




※ 연산자 작성 시 유의사항

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>



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

















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