경제학도의 개발공간
[20180503]Mybatis 본문
출처: http://www.mybatis.org/mybatis-3/ko/getting-started.html
설치
마이바티스를 사용하기 위해 mybatis-x.x.x.jar 파일을 클래스패스에 두어야 한다.
메이븐을 사용한다면 pom.xml에 다음의 설정을 추가하자.
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>x.x.x</version> </dependency>
XML에서 SqlSessionFactory 빌드하기
모든 마이바티스 애플리케이션은 SqlSessionFactory 인스턴스를 사용한다. SqlSessionFactory인스턴스는 SqlSessionFactoryBuilder를 사용하여 만들수 있다. SqlSessionFactoryBuilder는 XML설정파일에서 SqlSessionFactory인스턴스를 빌드할 수 있다.
XML파일에서 SqlSessionFactory인스턴스를 빌드하는 것은 매우 간단한다. 설정을 위해 클래스패스 자원을 사용하는 것을 추천하나 파일 경로나 file:// URL로부터 만들어진 InputStream인스턴스를 사용할 수도 있다. 마이바티스는 클래스패스와 다른 위치에서 자원을 로드하는 것으로 좀더 쉽게 해주는 Resources 라는 유틸성 클래스를 가지고 있다.
String resource = "org/mybatis/example/mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
XML설정파일에서 지정하는 마이바티스의 핵심이 되는 설정은 트랜잭션을 제어하기 위한 TransactionManager과 함께 데이터베이스 Connection인스턴스를 가져오기 위한 DataSource 를 포함한다. 세부적인 설정은 조금 뒤에 보고 간단한 예제를 먼저보자.
<?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>
<typeAliases>
<typeAlias type="com.kosta.DTO.GuestDTO" alias="guest"/> </typeAliases>
<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>
좀 더 많은 XML 설정방법이 있지만 위 예제에서는 가장 핵심적인 부분만을 보여주고 있다. XML 가장 위부분에서는 XML 문서의 유효성체크를 위해 필요하다. environment엘리먼트는 트랜잭션 관리와 커넥션 풀링을 위한 환경적인 설정을 나타낸다. mappers엘리먼트는 SQL 코드와 매핑 정의를 가지는 XML 파일인 mapper 의 목록을 지정한다.
Ibatis와는 달리 Alias를 Config에서 설정한다.
스코프(Scope) 와 생명주기(Lifecycle)
이제부터 다룰 스코프와 생명주기에 대해서 이해하는 것은 매우 중요하다. 스코프와 생명주기를 잘못 사용하는 것은 다양한 동시성 문제를 야기할 수 있다.
참고 객체 생명주기와 의존성 삽입 프레임워크
의존성 삽입 프레임워크는 쓰레드에 안전하도록 해준다. 트랜잭션 성질을 가지는 SqlSessions과 매퍼들 그리고 그것들을 직접 빈에 삽입하면 생명주기에 대해 기억하지 않아도 되게 해준다. DI프레임워크와 마이바티스를 사용하기 위해 좀더 많은 정보를 보기 위해서는 MyBatis-Spring이나 MyBatis-Guice 하위 프로젝트를 찾아보면 된다.
SqlSessionFactoryBuilder
이 클래스는 인스턴스화되어 사용되고 던져질 수 있다. SqlSessionFactory 를 생성한 후 유지할 필요는 없다. 그러므로 SqlSessionFactoryBuilder 인스턴스의 가장 좋은 스코프는 메소드 스코프(예를들면 메소드 지역변수)이다. 여러개의 SqlSessionFactory 인스턴스를 빌드하기 위해 SqlSessionFactoryBuilder를 재사용할 수도 있지만 유지하지 않는 것이 가장 좋다.
SqlSessionFactory
한번 만든뒤 SqlSessionFactory는 애플리케이션을 실행하는 동안 존재해야만 한다. 그래서 삭제하거나 재생성할 필요가 없다. 애플리케이션이 실행되는 동안 여러 차례 SqlSessionFactory 를 다시 빌드하지 않는 것이 가장 좋은 형태이다. 재빌드하는 형태는 결과적으로 “나쁜냄새” 가 나도록 한다. 그러므로 SqlSessionFactory 의 가장 좋은 스코프는 애플리케이션 스코프이다. 애플리케이션 스코프로 유지하기 위한 다양한 방법이 존재한다. 가장 간단한 방법은 싱글턴 패턴이나 static 싱글턴 패턴을 사용하는 것이다. 또는 구글 쥬스나 스프링과 같은 의존성 삽입 컨테이너를 선호할 수도 있다. 이러한 프레임워크는 SqlSessionFactory의 생명주기를 싱글턴으로 관리할 것이다.
SqlSession
각각의 쓰레드는 자체적으로 SqlSession인스턴스를 가져야 한다. SqlSession인스턴스는 공유되지 않고 쓰레드에 안전하지도 않다. 그러므로 가장 좋은 스코프는 요청 또는 메소드 스코프이다. SqlSession 을 static 필드나 클래스의 인스턴스 필드로 지정해서는 안된다. 그리고 서블릿 프레임워크의 HttpSession 과 같은 관리 스코프에 둬서도 안된다. 어떠한 종류의 웹 프레임워크를 사용한다면 HTTP 요청과 유사한 스코프에 두는 것으로 고려해야 한다. 달리 말해서 HTTP 요청을 받을때마다 만들고 응답을 리턴할때마다 SqlSession 을 닫을 수 있다. SqlSession 을 닫는 것은 중요하다. 언제나 finally 블록에서 닫아야만 한다. 다음은 SqlSession을 닫는 것을 확인하는 표준적인 형태다
1 2 3 4 5 6 | SqlSession session = sqlSessionFactory.openSession(); try { // do work } finally { session.close(); } | cs |
위 세가지 함수의 올바른 활용법을 적용한 코드는 다음과 같이 구성할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public class SqlMapClient { private static SqlSessionFactory factory; static { String resource = "SqlMapConfig.xml"; try { Reader reader = Resources.getResourceAsReader(resource); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader); }catch(Exception e) { } } public static SqlSession getSqlSession(){ SqlSession session = factory.openSession(); return session; } } | cs |
MYbatis활용을 위한 파일 구조예시
1. SqlMapConfig.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <?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> <properties resource="SqlMapConfigExample.properties" /> <!-- ibatis mapper : mybatis config --> <typeAliases> <typeAlias type="com.kosta.DTO.GuestDTO" alias="guest"/> </typeAliases> <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="SqlMapper/Guest.xml" /> </mappers> </configuration> | cs |
mapper >> 우리가 session에서 사용할 Mapper의 정보를 입력해 준다.
2. SqlMapConfigExample.properties
1 2 3 4 | driver=oracle.jdbc.driver.OracleDriver url=jdbc:oracle:thin:@localhost:1521:XE username=bituser password=1004 | cs |
우리가 사용할 DB의 정보를 담아줌으로써 SqlMapConfig에서 더 편하게 유지보수할 수 있도록 도와주는 파일이다.
3. Guest.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | <?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="GUEST"> <select id="getAllList" resultType="guest"> select * from guest order by no desc </select> <select id="getDetailByno" parameterType="int" resultType="guest"> select * from guest where no=#{no} </select> <insert id="insertGuest" parameterType="guest"> insert into guest(no,name,pwd,email,home,content,regdate) values(guest_seq.nextval,#{name},#{pwd},#{email},#{home},#{content},sysdate) </insert> <update id="updateGuest" parameterType="guest"> update guest set name=#{name} , email=#{email} , home=#{home} , content=#{content} where no = #{no} </update> <delete id="deleteGuest" parameterType="int"> delete from guest where no=#{no} </delete> <!-- 동적쿼리 parameterType="hashMap" {key:value} 검색하기 이름 선택 검색어 : 홍길동 >where name= '홍길동' 자바코드 Map<String, String> map = new HashMap<>(); // collection map.put("column", column); // column : name or email or home map.put("search", keyvalue); // keyvalue : 홍길동 {"column" , name} {"search" , 홍길동} where name like '%홍길동%' where title like '%스프링%' --> <select id="selectSearch" parameterType="hashMap" resultType="guest"> select * from guest <if test="column != null"> where ${column} like '%' || #{search} || '%' <!-- where ${column} like '%${search}%' --> </if> </select> <select id="selectSearch2" parameterType="hashMap" resultType="guest"> >>>>합집합을 찾는 쿼리문입니다. select * from guest <where> <if test="name != null"> name = #{search} </if> <if test="email != null"> or email = #{search} </if> <if test="home != null"> or home = #{search} </if> </where> </select> <!-- where name=kglim or eamil=kglim or home=kglim --> </mapper> | cs |
namespace의 값을 xml의 파일명과 동일하게 설정하는 것이 일반적이다. 이후, DAO단에서 쿼리문을 실행시킬 때,
1 | session.insert("GUEST.insertGuest",guestobj) |
namespace의 값을 명시함으로써 원하는 SqlMapper의 명령문을 실행시킬 수 있다.
들어오는 parameter가 Map일 때, Key값을 SQL문에 ${column} 와 같은 방식으로 입력하면 value가 자동으로 입력된다.
4. SqlSessionFactoryService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | package com.kosta.Config; import java.io.Reader; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class SqlSessionFactoryService { //private static SqlSession session; private static SqlSessionFactory sqlsessionfactory; static{ String resource = "SqlMapConfig.xml"; try{ Reader reader = Resources.getResourceAsReader(resource); sqlsessionfactory = new SqlSessionFactoryBuilder().build(reader); //session = Factory.openSession(); }catch(Exception e){ } } public static SqlSessionFactory getSqlSession(){ return sqlsessionfactory; } } | cs |
'BackEnd > Spring' 카테고리의 다른 글
[20180510]Spring 비동기처리 (0) | 2018.05.10 |
---|---|
[20180503]Mybatis WIth Spring (1) | 2018.05.03 |
[20180425]AOP(Aspect Oriented Programming) (0) | 2018.05.02 |
[20180501]HandlerInterceptor (0) | 2018.05.01 |
[20180424]Spring_Annotation (0) | 2018.04.30 |