본문 바로가기

DB

mybatis - Data Persistence Framework, SqlSession 사용법, SQL 문에 삽입할 파라미터 전달하기

728x90

Data Persistence Framework

- 데이터의 영속성(지속성; 등록,조회,변경,삭제)을 대신 처리해주는 프레임워크.

 

Mybatis 도입

1) Mybatis 라이브러리 파일을 프로젝트에 등록하기

- mvnrepository.com 또는 search.maven.org에서 mybatis를 검색하여 라이브러리 정보 알아낸다.

- build.gradle 파일에 의존 라이브러리 정보를 추가한다.

- 'gradle eclipse' 실행하여 라이브러리를 다운로드 받고, 이클립스 설정 파일에 등록한다.

- 이클립스 프로젝트를 리프래시하여 변경된 설정 파일의 정보를 반영한다.

2) Mybatis 설정 파일 준비

- mybatis.org 사이트에서 문서 페이지를 참조한다.

- Mybatis 설정 파일(예: mybatis-config.xml)을 생성한다.

- 문서 페이지를 참조하여 설정 파일의 내용을 변경한다.

 

1. mybatis 설정 파일을 읽을 InputStream 도구를 준비한다.

=> 다음과 같이 mybatis 설정 파일의 경로를 직접 지정하면

애플리케이션 배포 경로가 바뀔 때 마다

소스를 변경하고 다시 컴파일 해야 하는 문제가 있다.

InputStream mybatisConfigInputStream = new FileInputStream(

"./bin/main/com/eomcs/mybatis/ex01/a/mybatis-config.xml");

=> 이런 문제를 해결하기 위해 Mybatis는 도우미 객체를 제공한다.

=> Resources 클래스의 메서드를 이용하면

자바 클래스가 있는 패키지 폴더의 mybatis 설정 파일을 바로 지정할 수 있다.

 

2. SqlSessionFactory를 만들어 줄 빌더 객체 준비

3. SqlSession 객체를 만들어 줄 팩토리 객체 준비

4. SQL을 실행시키는 객체 준비

 

SqlSession 사용법 - SQL 문을 실행하는 메서드

SqlSession 객체를 이용하여 SQL 맵퍼 파일에 작성한 SQL 문을 실행하는 방법

=> select 문장

- sqlSession.selectList() : 목록 리턴

- sqlSession.selectOne() : 한 개의 결과 리턴

=> insert 문장

- sqlSession.insert()

=> update 문장

- sqlSession.update()

=> delete 문장

- sqlSession.delete()

 

SqlSession.selectList() 사용법 - select 문 실행하기

selectList()

=> 여러 개의 결과 값을 리턴하는 select를 실행할 때 사용한다.

=> select 실행으로 생성된 각 row의 값은 resultType에 지정한 클래스의 인스턴스에 저장된다.

=> 그리고 그 인스턴스는 List 구현체에 담겨 리턴된다.

=> 결과가 없으면 size 가 0인 List 객체를 리턴한다.

실행 결과가 기대와 같지 않은 이유?

=> mybatis에서 결과 값을 Board 객체에 담을 때 일부 컬럼의 값을 담지 못했기 때문이다.

 

왜 일부 컬럼의 값을 Board에 담지 못했는가?

=> mybatis에서 결과의 컬럼 값을 자바 객체에 담을 때

컬럼 이름과 같은 이름을 가진 프로퍼티(셋터 메서드)를 찾는다.

=> 컬럼 이름과 일치하는 프로퍼티가 없다면,

셋터 메서드를 호출할 수 없기 때문에

해당 컬럼의 값이 자바 객체에 저장되지 못한다.

 

Mybatis에서 select 결과를 자바 인스턴스에 담을 때 규칙

=> 컬럼 이름과 같은 프로퍼티를 찾아서 값을 담는다.

=> 자바에서 '프로퍼티'란?

세터/게터를 가리키는 용어다.

예) setNo()/getNo()

=> 프로퍼티 이름?

세터/게터 이름에서 set/get 이름을 제거한 후, 나머지 이름이다.

단 첫 알파벳은 소문자이다.

예) setNo()/getNo() => no

예) setCreatedDate()/getCreatedDate() => createdDate

=> 주의!

필드 이름이 프로퍼티 이름이 아니다!

 

결론!

- Board 클래스의 프로퍼티 이름을 보면

no, title, content, registeredDate, viewCount 가 있다.

- 이 프로퍼티 중에서 컬럼 이름과 같은 프로퍼티는 title 뿐이다.

- Mybatis는 컬럼 이름과 같은 이름을 가진

프로퍼티(title,contents)에 대해서만 결과 값을 넣어 준다.

- 그래서 Board 객체를 출력해보면 title 값만 정상적으로 출력된다.

 

해결책?

=> 컬럼 이름과 프로퍼티 명을 같게 하면 되지 않겠는가?

- DB의 이름짓는 규칙과 자바의 이름 짓는 규칙은 다르다.

- DBMS 마다 또 이름 짓는 규칙이 다른다.

- 그래서 자바에서 프로퍼티 이름을 지을 때 특정 DBMS에 종속되게 지어서는 안된다.

- 자바는 자바의 명명 규칙을 따르고, DB는 DBMS의 명명 규칙을 따르면 된다.

=> 그러면 어떻게 하자는 것인가?

- select 할 때 컬럼의 별명을 자바 프로퍼티 이름과 같게 하라!

 

SqlSession.selectList() 사용법 - <resultMap>을 통해 자바 객체의 프로퍼티 이름과 일치시키기

 

<mapper namespace="BoardMapper">
  
  <!-- 컬럼명과 자바 객체의 프로퍼티 명을 미리 연결한다.
       type: 자바 객체의 클래스명 또는 별명
       id: 연결 정보를 가리키는 식별자. SQL 문을 설정할 때 사용한다. 
  -->
  <resultMap type="Board" id="BoardMap">
    <!-- 컬럼명과 자바 객체의 프로퍼티명을 연결한다.
         column="테이블 컬럼명"
         property="자바 객체의 프로퍼티명"
         시작태그와 끝태그 사이에 추가 내용이 없다면 끝태그를 생략하고
         대신에 시작태그의 끝에 /를 붙인다.
   
         PK 컬럼을 지정할 때는 id 엘리먼트를 사용하고, 
         일반 컬럼을 지정할 때는 result 엘리먼트를 사용하라! -->
         
    <id column="board_id" property="no"/> 
    <!-- 의미 => board_id 컬럼 값은 Board.setNo()을 호출해서 넣으라는 의미 -->
    
    <!-- 컬럼 이름과 자바 객체의 프로퍼티 이름이 같을 경우 생략해도 된다. -->
    <!--  
    <result column="title" property="title"/>
    -->
    
    <result column="contents" property="content"/>
    <result column="created_date" property="registeredDate"/>
    <result column="view_count" property="viewCount"/>
  </resultMap>
  
  <!-- 위에서 정의한 연결 정보를 사용하고 싶다면,
       resultMap="컬럼과 프로퍼티의 연결을 정의한 resultMap 아이디" 를 설정하라! 
       참고!
       resultType="클래스명 또는 별명"
  -->
  <select id="selectBoard" resultMap="BoardMap">
    select 
      board_id, <!-- BoardMap의 연결정보를 참조하기 때문에 별명을 주지 않아도 된다. -->
      title,    
      contents,
      created_date, 
      view_count  
    from x_board
  </select>
</mapper>

 

SqlSession.selectOne() 사용법 - 결과 값을 Map 객체로 받기

 

<mapper namespace="BoardMapper">
  
  <!-- select 결과를 Map 객체에 받을 수 있다. 
       - 각각의 레코드 값은 각각의 Map 객체에 보관된다.
       - 그리고 List에 Map 객체 목록이 보관된다.
  -->
  <select id="selectBoard" resultType="map">
    select 
      board_id,
      title,    
      contents,
      created_date, 
      view_count  
    from x_board
  </select>
</mapper>
Map 객체로 받으려면 SQL 매퍼에서 다음과 같이 resultType을 설정해야 한다.
       <select id="selectBoard3" resultType="map" parameterType="int">
         select 
           board_id,
           title,    
           contents,
           created_date, 
           view_count  
         from x_board
         where board_id=#{no}
       </select>
    
    - 컬럼 이름(이나 별명)으로 컬럼 값을 저장하기 때문에 
      map 객체에 컬럼 값을 꺼낼 때 컬럼 이름(이나 별명)을 사용해야 한다.

 

SQL 문에 삽입할 파라미터 전달하기 - 한 개의 int 값 넘기기

 

in-parameter에 int 값 넘기기

=> SQL을 실행할 때 파라미터 값을 전달하려면

두 번째 파라미터로 전달해야 한다.

예) selectOne(sql, in-parameter 값)

=> in-parameter 값의 타입은 Object이다.

자바 원시 타입의 값을 지정하면 자동으로 오토 박싱되어 mybatis에 전달된다.

=> 여러 개의 값을 전달해야 한다면,

도메인 객체나 Map 객체에 담아 전달하라!

 

SQL 문에 삽입할 파라미터 전달하기 - XML Entity를 사용할 때

 

XML 파서가 혼동을 일으킬 수 있는(XML 파싱 오류 발생) 문자를 사용할 때

- 그 문자 대신 XML Entity를 사용하라.

" => &quot;

' => &apos;

& => &amp;

< => &lt;

> => &gt;

 

SQL 문에 삽입할 파라미터 전달하기 - CDATA 섹션을 사용할 때 : <[!CDATA[ SQL 문 []]>

 

CDATA 섹션

- XML 파서(parser)에게 해당 블록의 내용물이 단순 텍스트임을 알려주는 명령이다.

- 문법

<![CDATA[ 내용물 ]]>

- 내용물 안에 XML 파서가 혼동을 일으킬 문자가 많을 때 사용하기 적합하다.

 

SQL 문에 삽입할 파라미터 전달하기 - Map을 이용하여 여러 개의 값 넘기기

 

selectList(),selectOne(),insert(),update(),delete()

- selectList(SQL ID)

- selectList(SQL ID, 파라미터)

- 위와 같이 SQL을 실행할 때 오직 한 개의 파라미터만 넘길 수 있다.

- 여러 개의 파라미터를 넘기고 싶다면 객체에 담아서 넘겨라!