Mybatis는 데이터베이스 작업을 좀 더 편리하게 해주는 프레임워크이다.
현업에서 자주 쓰이는 프레임워크 임으로 잘 알아두자.
◆ myBatis (마이바티스)
개발자가 설정한 SQL문을 처리하는 JDBC서포트 프레임워크
( 실제 개발과정에서 자주 사용되는 프레임워크중 하나이다. )
- 데이터베이스와의 연결을 관리 해줌.
- myBatis는 DBCP라는 Connection Pool을 사용하여 커넥션을 여러 개 생성하여, 관리하기 때문에 그냥 JDBC를 사용하는 것 보다, 작업이 부드럽게 이루어진다.
▶ 라이브러리와 프레임워크의 차이
- 라이브러리 : 만들어놓은 API들을 불러와서 사용할 수 있게 해주는 클래스들의 집합
- 프레임워크 : 라이브러리들을 모아서 만든 사용법이 정해진 큰 틀의 라이브러리 집합
◆ myBatis 사용준비
1. 라이브러리 추가
http:www.mybatis.org에서 mybaits zip파일을 다운을 받아서 압축해제 후 mybatis.jar파일과 lib디렉터리 내부의 라이브러리 파일을 추가해주면 된다.
(WEB-INF/lib)
2. WEB-INF안에 xml파일을 추가해서 연결설정
프로젝트 WEB-INF디렉터리에 xml파일을 하나 생성하여 아래와 같이 연결을 설정한다.
mybatis라이브러리 zip파일 내부의 pdf파일을 통해서도 확인이 가능하다.
※ DB종류와 정보에 따라 입력값(value)이 달라질 수 있다.
3. xml파일을 불러올 InputStream객체 생성
2번에서 만든 xml파일의 경로를 인자로 InputStream객체를 생성한다.
4. SqlSessionFactory 객체생성
3번에서 만든 InputStream객체를 인자로 SqlSessionFactory객체를 생성한다.
5. SqlSession 객체생성 및 작업
4번에서 만든 SqlSessionFactory객체의 openSession()메서드를 이용하여 SqlSession객체를 생성한다.
이렇게 만들어진 SqlSession객체를 통하여 SQL문을 제어할 수 있다.
실제 작업은 SqlSession객체를 통해서만하기 때문에 3,4번의 작업은 보통 어플리케이션 리스너(서블릿컨텍스트리스너)에서 어플리케이션에 SqlSessionFactory객체까지 만들어두고 올려둔 상태로 진행한다.
◆ SQL 작성 등록
위처럼 Mybatis설정 준비가 됐으면, 이제는 사용할 SQL문을 등록시켜 두어야 한다.
1. SQL문을 등록할 xml파일을 생성한다.
처음 mybatis설정했던 xml파일이 아닌 SQL문을 등록할 새로운 xml파일을 생성시켜둔다.
주의할 점은 WEB-INF디렉터리 내부는 인식할 수 없기 때문에 java Resources안에 새로 패키지를 만들어 넣어준다.
2. SQL문 등록
-
- <mapper> 태그의 namespace
- 자바 코드에서 SQL문을 호출할 때 인자로 식별할 이름
-
- sql태그의 id
- 자바코드에서 “namespace명.sql태그id”를 인자로 호출되기 때문에 이를 식별하기 위한 옵션
-
- sql태그의 parameterType
- SQL문을 실행할 때 어떤 타입으로 인자를 넘겨줄 것인지를 설정
-
- sql태그의 resultType
- select태그에서 sql명령문의 결과로 받아올 데이터의 타입을 설정한다.
- 타입의 입력은 전체 클래스명(ex ) java.util.HashMap) 또는 별칭으로도 설정이 가능하다.
- resultType은 반환타입 설정이기 때문에 <select>에서만 설정이 가능한 옵션이다.
- <insert>, <select>, <update>등 사용하고자 하는 명령문에 따라 태그를 다르게 설정해서 사용한다.
▶ resultType, parameterType 별칭사용
별칭은 클래스명 전체를 입력하지 않고, 특정 이름을 통해 등록하는 타입이다.
이를 등록하기 위해서는 처음 mybatis연결을 설정했던 xml파일에 아래와 같이 작성하면 된다.
와 같은 작업을 해주면, type에 해당하는 클래스객체를 alias옵션의 이름으로 resultType에 입력할 수 있게 된다. 단, 이미 잡혀있는 별칭도 존재하기 때문에 중복 사용은 불가능하다.
=> 주의할 점은 DB연결태그 위로 써 주어야 한다.
▶ 이미 잡혀있는 typeAlias별칭들
- java.lang.String = string
- java.lang.Integer = int / integer
- java.lang.Double = double
- java.util.Date = date
- java.util.HashMap = hashmap
- java.util.ArrayList = arraylist
▶ SQL문 파라미터 설정
JDBC에서 where문의 들어갈 조건을 설정할 때 썼던 ? 대신에 #{ 변수 }로 설정해준다.
해당 조건의 변수명이 하나인 경우에는 아무거나 써 주어도 의미가 없지만, 여러 개 일 경우 인자로 맵을 줄 때 맵의 킷값과 일치하는 이름이어야 한다.
3. xml매핑
SQL문xml파일까지 등록이 완료 되었으면, mybatis에서 인식할 수 있도록 매핑작업을 해 주어야 한다.
처음 연결설정 해 두었던 xml파일에서 아래와 같이 SQL문xml파일의 경로를 등록시켜 준다.
◆ SQL 사용
SqlSession sql = factory.openSession();
위 mybatis준비 과정에서 생성시킨 Sqlsession객체를 이용하여 모든 sql문을 실행한다.
▶ 사용하고자 하는 sql문에 따라 메서드가 다르다.
- sql.insert() :
- sql.update() :
- sql.delete() :
- sql.selectOne() :
- sql.selectList() :
▶ SQL문 실행 방법
xml에 등록한 sql문을 사용하기 위해 <mapper>태그의 namespace옵션과 sql태그의 id를 식별자 인자로 사용한다.
ex) sql.selectOne("namespace명.sql태그id");
-
두 번째 인자로는 SQL문의 파라미터
값에 해당하는 값을 넣어준다. 파라미터가 없을 경우 넣지 않으면 된다. (조건은 디폴트 오브젝트 형으로 들어간다. )
파라미터를 하나만 받는 경우에는 해당 값을 인자로 바로 넘겨주면 되지만, 파라미터가 여러 개일 경우 map을 이용해서 넣게 되고, map일 경우 xml파일에서 설정한 변수명(ex) #{변수})과 map의 킷값이 일치해야 한다.
-
- selectOne()
- select문의 결과가 하나밖에 없을 때만 사용하는 메서드 없으면 null을 반환. (결과가 여러개일 경우 오류)
-
- selectList()
- select문의 결과가 여러 개일 때 사용하는 메서드로 resultType으로 설정했던 타입을 제네릭으로 하는 List객체를 반환받는다.
ex ) List<resultType>
- 파라미터 값으로 null이 들어가는 값을 넣을 수 없다.
- 보통 select문의 결과로 여러 개의 컬럼일 때는 resultType으로 map형태로 받아오게 된다.
(키를 컬럼명으로하는 Map) - map으로 받아올 때 키의 값은 컬럼 대문자로 설정하여 불러오게 된다. 따라서 호출할 때 map.get(“NO”)의 형식으로 대문자를 인자로 불러온다.
▶ DB데이터 타입에 따른 변환
오라클 데이터베이스의 데이터타입에 따른 Java의 데이터타입 변환은 아래와 같이 이루어진다.
- VARCHAR2 = String
- DATE = Date
- NUMBER = BigDecimal
▶ BigDecimal객체
BigDecimal타입은 integer, double, long… 등의 숫자 객체를 담당하는 java.Math 소속의 객체로 원하는 타입으로 변환해서 사용할 수 있다.
◆ VO객체를 이용 myBatis
VO(ValueObject)는 데이터를 담을 저장용 객체를 의미하며(직접 만드는 객체), 기존 Map등의 객체로 받던 SQL반환 객체를 VO객체를 통해 받을 수 있다.
1. 객체 클래스 만들기
DB작업의 인자로 넣을 멤버 변수를 설계하고 설계한 멤버 변수에 해당하는 getter와 setter메서드를 추가하여 객체를 만든다. ( 기본 생성자는 필수 )
getter와 setter는 (ctrl+shift+s)단축키로 이클립스에서 지원하는 기능으로 빠르게 생성이 가능하다.
2. 태그 매핑
SQL문을 등록하는 xml파일의 <mapper> 태그안에 <resultMap>태그를 이용하여 VO객체를 아래와 같이 등록한다.
▶ <resultMap>
사용할 VO객체를 정의하고 매핑 시킬 id를 설정하는 태그
-
type
: 사용할 VO객체의 경로
-
id
: sql문 태그의 resultMap의 값으로 사용할 id
▶ <result>
-
column
: DB의 컬럼명
-
property
: DB컬럼과 매칭 시킬 VO객체의 멤버 변수명
ex ) <result colum=“no” property = “number” />
DB테이블의 no컬럼명은 VO객체의 number멤버변수와 매칭된다.
▶ <select> 태그의 resultMap옵션
기존의 Map객체와 같은 기본 객체들은 resultType이라는 옵션으로 사용하였지만, VO객체를 반환형으로 사용하려면 resultMap을 옵션으로 사용하여야 하고, resultMap의 값으로 <resultMap>태그의 id를 입력한다.
▶ resultMap을 사용하는 이유?
VO객체를 꼭 resultMap으로 사용해야 하는것은 아니다. resultType에서도 멤버 변수명과 DB컬럼명이 같다면 VO객체를 사용할 수 있다.
하지만, DB와 JAVA의 변수명 규칙이 달라 객체의 멤버 변수명과 DB컬럼명이 다를 경우 resultMap으로 매핑작업을 해 주어야 한다.
Oracle의 복합단어의 경우 단어의 구분을 언더바(_)를 사용하지만, JAVA의 경우 CAMEL규칙에 따라 복합 단어의 구분을 복합단어 첫문자 대문자로 표시하기 때문에 DB컬럼명과 멤버변수명이 달라질 수 있다.
- DB : ex) phone_no
- JAVA : ex) phoneNo
◆ <resultMap>을 활용한 1:N 데이터 불러오기
resultMap을 정의 할 때 <collection>태그를 통해 다른 쿼리의 결과값을 하나의 변수에 포함시킬 수 있다
즉 하나의 행 데이터에서 하나의 컬럼 변수가 쿼리 리스트로 세팅되는 형태
=> resultMap속성을 prd_banner로 하는 쿼리문은 위 <resultMap>형태로 반환되기 때문에 <collection>태그의 propertiy속성인 banner_list라는 변수에 select속성인 ShopDao.getShopProductTagList쿼리 리스트가 담기게 된다.
- <collection>태그의 select쿼리의 동적 변수는 column컬럼의 값을 사용한다.
◆ insert 작업
insert / update / delete은 데이터를 불러오는 작업이 아니기 때문에 resultType 또는 resultMap을 설정할 수 없다. ( select에서는 resultType 또는 resultMap은 필수 )
1. 매핑
파라미터가 필요할 경우 parameterType을 설정하여 해당 파라미터 타입에 맞는 파라미터를 넘겨줄 수 있다.
2. 작업
- 인자가 여러 개일 경우 컬렉션 계열로 넣어주어야 한다.
( 단, 맵일때는 #{no} 등의 인자로 넣은 변수명이 맵의 키 값과 일치해야 하고, 사용자가 만든 VO객체의 경우 멤버변수와 일치하는 값으로 설정해야 한다. ) - sql작업을 할 때 try~ finally로 묶어서 close를 무조건 해주어야 한다.
- 조건문에서 < 나 > 를 쓸때는 태그로 인식할 수 있기 때문에 < (< ), > ( > )로 쓰면된다.
- 기본적으로 마이바티스의 파라미터로는 null값을 가지고 있는 변수 값을 넣을 수 없다.
( Map이 null이 아닐지라도, Map안의 value값이 null일 경우 불가능 )
▶ null값을 허용하는 방법
마이바티스에서는 null값으로 셋팅이 불가능하기 때문에 null값이 필요할 때는 sql문을 따로 설정해야 하지만, 컬럼 타입에 jdbcType을 지정해주면 null value도 셋팅이 가능하게 된다.
- jdbcType : VARCHAR, NUMERIC, DATE
ex ) #{max, jdbcType=NUMERIC}