IBATIS 2 이동국NHN September 28 th, 2008. Overview 소개 사용하기 iBATIS 3.0 소식 현재...
-
Upload
jesse-jenkins -
Category
Documents
-
view
236 -
download
0
description
Transcript of IBATIS 2 이동국NHN September 28 th, 2008. Overview 소개 사용하기 iBATIS 3.0 소식 현재...
iBATIS 2iBATIS 2
이동국이동국NHNNHN
September 28September 28thth, 2008, 2008
OverviewOverview
• 소개• 사용하기• iBATIS 3.0 소식• 현재 진행중인 이슈
SimpleSimpleLightweightLightweight
iBATIS..?소개소개
매우 간단한 XML 서술자를 사용해서 클래스와 SQL 구문을 매핑하는 퍼시스턴스 프레임워크
4
CLASS SQLXML
소개소개소개
JDBC
conn = DriverManager.getConnection(url, user, pass); stmt = conn.prepareStatement(); String sql = "SELECT * FROM employees"; rs = stmt.executeQuery(sql); while (rs.next()) { rs.getString("..."); rs.getString("..."); ... } rs.close(); stmt.close(); conn.close();
5
JDBC 와 iBATIS소개소개
6
JDBC 와 iBATIS소개소개
iBATIS
sqlMapClient.queryForList("selectEmployees")
<select id="selectEmployees" resultClass="Employee"> SELECT * FROM employees </select>
JDBC
conn = DriverManager.getConnection(url, user, pass); String sql = "insert into employees values(?,?,?,?)"; stmt = conn.prepareStatement(sql); stmt.setString(1, ".."); stmt.setString(2, ".."); stmt.setString(3, ".."); stmt.setString(4, ".."); int result = stmt.executeUpdate();
stmt.close(); conn.close();
7
JDBC 와 iBATIS소개소개
8
JDBC 와 iBATIS소개소개
iBATIS
sqlMapClient.insert("insertEmployees", employee)
<insert id="insertEmployees" parameterClass="Employee"> insert into employees values(#id#,#name#,#val1#,#val2#) </insert>
9
JDBC 와 iBATIS소개소개
3.0 에서 추가될 코드 컨벤션에 따른 SQL 구문 자동생성Employee getEmployee(int id);
→ SELECT id, firstName, lastName FROM Employee WHERE id = #id#
List<Employee> listAllEmployees(); → SELECT id, firstName, lastName FROM Employee
10
장점과 단점소개소개
장점 SQL 문과 소스 코드 분리로 소스 코드의 간결함을 유지 할 수 있다 .
데이터베이스 자원에 대한 필요이상의 제어를 자동으로 해결해 준다 .
단점 SQL 문과 소스 코드를 분리한다는 점에서는 잇점이지만 오히려 지나치게 많은
파일을 생성해서 관리상의 어려움을 초래 할 수도 있다 .
클래스 파일에 대한 리로드 기능은 WAS 및 기타 제품에 의해 적절히 보장 받을 수 있으나 XML 리로드에 대해서는 별도의 대책이 요구된다 .
11
데이터 타입사용하기사용하기
장점 단점
Bean 성능컴파일시 타입및 이름검사리팩토리
코드량 증가
Map 코드량 감소 느림오류가 컴파일 시 체크되지 않고 실행 시 체크됨잦은 형변환
12
# 과 $사용하기사용하기
#
SELECT * FROM account WHERE acc_id = #id# → SELECT * FROM account WHERE acc_id = ?
$ SELECT * FROM account WHERE acc_id = $id$
→ SELECT * FROM account WHERE acc_id = 1
13
SQL 재사용하기사용하기사용하기
<sql id="selectAccount_frag"> SELECT acc_id, acc_first_name, acc_last_name, acc_email FROM account </sql>
<select id="selectAllAccounts" resultClass="Account"> <include refid="selectAccount_frag" />
</select>
14
Result Map사용하기사용하기
일반적인 Result Map
<resultMap id="accountMap" class="Account"> <result property="id" column="acc_id" /> <result property="emailAddress" column="acc_email" />
</resultMap>
15
Result Map사용하기사용하기
-account
복합 Collection Result Map 에 사용되는 객체 구조public class Account {
private int id;private String firstName;.....private List<AccountFamily> families = null;
16
Result Map사용하기사용하기
복합 Collection Result Map 을 JDBC 로 구현한다면String accountSql = "SELECT * FROM account WHERE acc_id = ?";String familySql = "SELECT * FROM Account_family WHERE
acc_id = ?";accountStmt = conn.prepareStatement(accountSql);accountRs = accountStmt.executeQuery();while (accountRs.next()){
accountRs.getString("...");accountRs.getString("...");
familyStmt = conn.prepareStatement(familySql);familyRs = familyStmt.executeQuery();while( familyRs ){
familyRs.getString("");...
}account.setFamilies(...);...
} ResultSet 내에서 하위 ResultSet 처리
17
Result Map사용하기사용하기
복합 Collection Result Map
<resultMap id="get_account_nplus1" class="Account"> <result property="id" column="acc_id" /> <result property="families“ column="{id1=acc_id, id2=acc_id}" select="SubList.selectFamilyList" />
</resultMap>
로그 Connection Executing Statement: SELECT * FROM account WHERE acc_id = ? Executing Statement: SELECT * FROM Account_family WHERE acc_id = ?ResultSet
Header: [id, fullName] Result: [1, HongGilDong] Result: [1, SpiderMan] Header: [acc_id, acc_first_name, acc_last_name, acc_email, acc_id]
Result: [1, DongGuk, Lee, [email protected], 1]
18
Result Map사용하기사용하기
복합 Collection Result Map 에서 테이블조인을 JDBC 로 구현한다면
String sql = "SELECT * FROM account a LEFT JOIN account_family f ON a.acc_id = f.acc_id WHEREa.acc_id=?";
stmt = conn.prepareStatement(sql);rs = stmt.executeQuery();int i = 0;while (rs.next()){
family = new Family();if( i == 0 ){
account.setId();...
}family.setId();
list.add(family);i++;
}
19
Result Map사용하기사용하기
복합 Collection Result Map
<resultMap id="get_account_family_avoidnplus1" class="Account" groupBy="id">
<result property="id" column="acc_id" /> <result property="families" resultMap="Base.get_family_avoidnplus1" />
</resultMap>
로그 Connection Executing Statement: SELECT * FROM account a LEFT JOINaccount_family f ON a.acc_id = f.acc_id WHEREa.acc_id=?
ResultSet Header: [acc_id, acc_first_name, acc_last_name, acc_email, acc_id, family_fullname]
Result: [1, DongGuk, Lee, [email protected], 1, HongGilDong] Result: [1, DongGuk, Lee, [email protected], 1, SpiderMan] Result: [1, DongGuk, Lee, [email protected], 1, BatMan]
20
파라미터 처리사용하기사용하기
인라인 파라미터
문법 #propertyName##propertyName:jdbcType##propertyName:jdbcType:nullValue#
샘플 <insert id="insertAccount"> INSERT INTO account ( acc_id, acc_first_name, acc_last_name, acc_email
) VALUES ( #id,jdbcType = INTEGER, javaType = int,
nullValue =-99999#, #firstName, jdbcType = VARCHAR, javaType = string,nullValue=NULL#,
#lastName, jdbcType = VARCHAR, javaType = string, nullValue = Hong#, #emailAddress, jdbcType = VARCHAR, javaType = string, nullValue = NULL#
) </insert>
21
파라미터 처리사용하기사용하기
파라미터 맵
문법 <parameterMap id=”parameterMapName” [class=”com.domain.Product”]><parameter property =”propertyName” [jdbcType=”VARCHAR”] [javaType=”string”]
[nullValue=“-9999”] [typeName=”{REF or user-defined type}”] [resultMap=someResultMap] [mode=IN|OUT|INOUT] [typeHandler=someTypeHandler] [numericScale=2]/><parameter …… /><parameter …… />
</parameterMap>
22
파라미터 처리사용하기사용하기
샘플 <parameterMap id="accountParam" class="Account"> <parameter property="id" jdbcType="INTEGER" javaType="int“ nullValue="-9999999" /> <parameter property="lastName" jdbcType="VARCHAR" javaType="string" nullValue="Hong" /> <parameter property="firstName" jdbcType="VARCHAR" javaType="string" nullValue="NULL" /> <parameter property="emailAddress" jdbcType="VARCHAR" javaType="string" nullValue="NULL" />
</parameterMap>
<insert id="insertAccount" parameterMap="Base.accountParam"> INSERT INTO account (acc_id, acc_first_name, acc_last_name, acc_email
) VALUES ( ?,?,?,? ) </insert>
23
파라미터 처리사용하기사용하기
대개는 인라인 파라미터에서 프로퍼티명만 표기하는 형태로 사용
파라미터맵을 명시하는 경우 파라미터 인덱스 값으로 값을 셋팅하기 때문에 쿼리문의 파라미터를 # 프로퍼티명 # 형태로 처리하지 않고 ? 형태로 처리해야 함
24
동적 SQL사용하기사용하기
<dynamic> 이항연산 요소
<isEqual><isNotEqual><isGreaterThan>
<isGreaterEqual><isLessThan>
<isLessEqual>
25
동적 SQL사용하기사용하기
단항연산 요소
<isPropertyAvailable> <isNotPropertyAvailable> <isNull> <isNotNull> <isEmpty> <isNotEmpty>
파라미터 요소
<isParameterPresent> <isNotParameterPresent>
<iterate>
26
동적 SQL사용하기사용하기
단항연산 요소
<isPropertyAvailable> <isNotPropertyAvailable> <isNull> <isNotNull> <isEmpty> <isNotEmpty>
파라미터 요소
<isParameterPresent> <isNotParameterPresent>
<iterate>
27
동적 SQL사용하기사용하기
<select id="getAccountByDynamicSQL" parameterClass="int" resultClass="Account">SELECT acc_id, acc_first_name, acc_last_name, acc_emailFROM account WHERE acc_id = #id#<isNotEqual compareValue="1">and acc_email = ''</isNotEqual>
</select>
28
동적 SQL사용하기사용하기
3.0 에서 추가될 동적 SQL
public class GetAccountListSQL extends SQLSource { public String getSQL(Object param) { Account acct = (Account) param; append("select * from ACCOUNT"); prepend("WHERE"); if (exists(acct.getEmailAddress())) { append("AND", "ACC_EMAIL like #EmailAddress#"); } if (greaterThan(0, acct.getID())) { append("AND", "ACC_ID = #ID#"); } } }
<Select id="getAccountList“ source="org.apache.GetAccountListSQL" ...>
29
트랜잭션사용하기사용하기
자동 트랜잭션
메서드 호출 단위의 트랜잭션
로컬 트랜잭션
startTransaction
트랜잭션 시작
commitTransaction
트랜잭션 커밋
endTransaction
커밋이 되지 않은 경우 롤백 , JDBC 자원 회수
Spring 과 같은 서비스 계층에서의 트랜잭션 관리
30
캐시 타입사용하기사용하기
GC 기반 MEMORY
시간 기반 LRU FIFO
외부 캐시
OSCACHE
31
캐시사용하기사용하기
캐시되는 데이터
SQL 맵 구문 아이디
실제 쿼리문
com.ibatis.sqlmap.engine.mapping.statement 아래 각각의 Statement 객체 내 메서드 명
예 ) executeQueryForList
이외 iBATIS 의 캐시 객체에서 지정하는 몇 가지 값들
32
Spring 에서 iBATIS 사용하기사용하기사용하기
SqlMapClientDaoSupport 를 통해 SqlMapClientTemplate 사용하기
mappingLocations
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation“ value="classpath:kr/or/openframework/dao/ibatis/SqlMapConfig.xml"/> <property name="mappingLocations" value="classpath:kr/or/openframework/dao/ibatis/AccountWithFamily*.xml“ />
</bean>
Spring 2.5.5 에서 추가됨 iBATIS 2.3.2 이상의 버전이 필요함
33
Spring 에서 iBATIS 사용하기사용하기사용하기
SqlMapConfig.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
<sqlMapConfig><settings
cacheModelsEnabled="true" enhancementEnabled="true"lazyLoadingEnabled="false" useStatementNamespaces="true" />
<sqlMap resource="openframework/dao/ibatis/Dummy.xml" /><!--sqlMap resource="openframework/dao/ibatis/Account1.xml" /><sqlMap resource="openframework/dao/ibatis/Account2.xml" /><sqlMap resource="openframework/dao/ibatis/Account3.xml" /><sqlMap resource="openframework/dao/ibatis/Account4.xml" /-->
</sqlMapConfig>
34
성능을 향상시키는 방법사용하기사용하기
parameterMap 이나 parameterClass 속성을 명시적으로 선언<update id="updateAccount" parameterClass="Account"> </update>
<resultMap> 를 명시적으로 정의하고 결과의 재매핑(remapResults = true) 옵션은 사용하지 말라 .
Map 이나 XML 이 아닌 자바 Bean 을 사용하라 .
표현이나 배열 또는 혼합된 Bean 이나 Map 프로퍼티가 아닌 간단한 프로터티를 사용하라 .
<settings> 요소에 바이트코드 향상 기능을 활성화한다 . - enhancementEnabled="true"
35
iBATIS 3.0 소식iBATIS 3.0 iBATIS 3.0 소식소식
SQL 구문을 설정하는 애노테이션 추가
@Select("SELECT #id(EMP_ID:NUMERIC), #name(NAME:VARCHAR) ", "FROM EMPLOYEE")
List<Employee> selectAllEmployees(); @Select({"SELECT #id(EMP_ID:NUMERIC), #name(NAME:VARCHAR) ", "FROM EMPLOYEE ", "WHERE EMP_ID = @id"})
Employee selectEmployee(int id);
36
iBATIS 3.0 소식iBATIS 3.0 iBATIS 3.0 소식소식
ResultMap 을 대체하는 애노테이션 @ResultClass (Employee.class)
@PropertyResults({ @Result(property="departments.id", column="D.DEPT_ID"), @Result(property="departments.name", column="D.NAME"),
})
@Collections ({ @Collection(type=Department.class, property="departments", groupBy="id"),
})
@Select("SELECT #id, #name, " + "#departments.id, #departments.name " +
"FROM COMPANY C, DEPARTMENT D " + "WHERE C.COMP_ID = D.COMP_ID")
List<Company> selectAllCompaniesWithJoin();
37
현재 진행중인 이슈현재 진행중인 이슈현재 진행중인 이슈
Support for JDBC 3 Named parameters
http://issues.apache.org/jira/browse/IBATIS-96
이를테면 다음과 같은 형태의 parameterMap 을 사용 .. <parameterMap id="insert-product-param" class="com.domain.Product">
<parameter property="description" parameter="desc" /> <parameter property="id" parameter="productId" /> </parameterMap>
38
현재 진행중인 이슈현재 진행중인 이슈현재 진행중인 이슈
Auto Reloading Sql-map configuration.By Observing modifed date (adding datetime in Variables) or making a method reload conf.
http://issues.apache.org/jira/browse/IBATIS-208
sqlmap 설정파일에 대한 Hot Deploy 기능 지원
39
현재 진행중인 이슈현재 진행중인 이슈현재 진행중인 이슈
Improving startup time (Dynamically loading SQL maps based on namespace)
http://issues.apache.org/jira/browse/IBATIS-425
설정파일이 너무 많은 경우 WAS 가 정상적으로 시작되는 시간이 너무 오래 걸려서 운영 시 어려움이 있다 .
namespace 기반으로 초기 일부만 로딩하고 나머지는 해당 namespace 를 기준으로 차후 로딩을 하는 형태의 기능 요청 .
40
현재 진행중인 이슈현재 진행중인 이슈현재 진행중인 이슈
Ability to build SqlMapClient programmatically without SqlMapConfig.xml file
http://issues.apache.org/jira/browse/IBATIS-416
Spring 과 사용하는 경우 sql-map-config.xml 파일에는 특별히 많은 내용이 들어가지 않기 때문에 별도로 설정파일을 만들 필요 없이 iBATIS 관련 API 호출로 설정파일의 갯수를 줄이는 방안에 대한 요청 .
이미 Spring 에서도 버전을 올라가면서 관련 설정을 줄일 수 있는 기능을 하나씩 추가하고 있음 .
41
현재 진행중인 이슈현재 진행중인 이슈현재 진행중인 이슈
Using Java constants in statements http://issues.apache.org/jira/browse/IBATIS-147
parameterClass 가 아닌 다른 상수만을 가지는 외부 클래스의 값을 SQL 구문에서 그대로 사용하기 위한 기능 요청 .
Support generics http://issues.apache.org/jira/browse/IBATIS-273
JDK 1.5 이상에서 지원하는 제네릭을 지원해달라는 요청 .
42
참고자료현재 진행중인 이슈현재 진행중인 이슈
관련 사이트 iBATIS - http://ibatis.apache.org
openframework 위키 –http://openframework.or.kr/Wiki.jsp?page=PersistentLayer#refpersistentLayer-2
관련 서적 iBATIS 인 액션 ( 이동국 , 위키북스 ) Pro Spring (Rob Harrop, Jan Machac 다 )
감사합니다감사합니다 ..