1 / 43

iBATIS 2

iBATIS 2. 이동국 NHN September 28 th , 2008. Overview. 소개 사용하기 iBATIS 3.0 소식 현재 진행중인 이슈. iBATIS..?. 소개. Simple Lightweight. 소개. 소개. 매우 간단한 XML 서술자를 사용해서 클래스와 SQL 구문을 매핑하는 퍼시스턴스 프레임워크. CLASS. SQL. XML. 4. 소개. JDBC 와 iBATIS. JDBC

miette
Download Presentation

iBATIS 2

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. iBATIS 2 이동국 NHN September 28th, 2008

  2. Overview • 소개 • 사용하기 • iBATIS 3.0 소식 • 현재 진행중인 이슈

  3. iBATIS..? 소개 SimpleLightweight

  4. 소개 소개 • 매우 간단한 XML서술자를 사용해서 클래스와 SQL구문을 매핑하는 퍼시스턴스 프레임워크 CLASS SQL XML 4

  5. 소개 JDBC와 iBATIS • 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

  6. 소개 JDBC와 iBATIS • iBATIS sqlMapClient.queryForList("selectEmployees") <select id="selectEmployees" resultClass="Employee"> SELECT * FROM employees </select> 6

  7. 소개 JDBC와 iBATIS • 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

  8. 소개 JDBC와 iBATIS • iBATIS sqlMapClient.insert("insertEmployees", employee) <insert id="insertEmployees" parameterClass="Employee"> insert into employees values(#id#,#name#,#val1#,#val2#) </insert> 8

  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 9

  10. 소개 장점과 단점 • 장점 SQL문과 소스 코드 분리로 소스 코드의 간결함을 유지 할 수 있다. 데이터베이스 자원에 대한 필요이상의 제어를 자동으로 해결해 준다. • 단점 SQL문과 소스 코드를 분리한다는 점에서는 잇점이지만 오히려 지나치게 많은 파일을 생성해서 관리상의 어려움을 초래 할 수도 있다. 클래스 파일에 대한 리로드 기능은 WAS 및 기타 제품에 의해 적절히 보장 받을 수 있으나 XML 리로드에 대해서는 별도의 대책이 요구된다. 10

  11. 사용하기 데이터 타입 11

  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 12

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

  14. 사용하기 Result Map • 일반적인 Result Map <resultMap id="accountMap" class="Account"> <result property="id" column="acc_id" /> <result property="emailAddress" column="acc_email" /> </resultMap> 14

  15. 사용하기 Result Map -account • 복합 Collection Result Map에 사용되는 객체 구조 • public class Account { • private int id; • private String firstName; • ..... • private List<AccountFamily> families = null; 15

  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 처리 16

  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, fromm0@gmail.com, 1] 17

  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++; • } 18

  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, fromm0@gmail.com, 1, HongGilDong] Result: [1, DongGuk, Lee, fromm0@gmail.com, 1, SpiderMan] Result: [1, DongGuk, Lee, fromm0@gmail.com, 1, BatMan] 19

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

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

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

  23. 사용하기 파라미터 처리 • 대개는 인라인 파라미터에서 프로퍼티명만 표기하는 형태로 사용 • 파라미터맵을 명시하는 경우 파라미터 인덱스 값으로 값을 셋팅하기 때문에 쿼리문의 파라미터를 #프로퍼티명# 형태로 처리하지 않고 ? 형태로 처리해야 함 23

  24. 사용하기 동적 SQL • <dynamic> • 이항연산 요소 <isEqual><isNotEqual><isGreaterThan> <isGreaterEqual><isLessThan> <isLessEqual> 24

  25. 사용하기 동적 SQL • 단항연산 요소 <isPropertyAvailable> <isNotPropertyAvailable> <isNull> <isNotNull> <isEmpty> <isNotEmpty> • 파라미터 요소 <isParameterPresent> <isNotParameterPresent> • <iterate> 25

  26. 사용하기 동적 SQL • 단항연산 요소 <isPropertyAvailable> <isNotPropertyAvailable> <isNull> <isNotNull> <isEmpty> <isNotEmpty> • 파라미터 요소 <isParameterPresent> <isNotParameterPresent> • <iterate> 26

  27. 사용하기 동적 SQL <select id="getAccountByDynamicSQL" parameterClass="int" resultClass="Account"> SELECT acc_id, acc_first_name, acc_last_name, acc_email FROM account WHERE acc_id = #id# <isNotEqual compareValue="1"> and acc_email = '' </isNotEqual> </select> 27

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

  29. 사용하기 트랜잭션 • 자동 트랜잭션 메서드 호출 단위의 트랜잭션 • 로컬 트랜잭션 • startTransaction 트랜잭션 시작 • commitTransaction 트랜잭션 커밋 • endTransaction 커밋이 되지 않은 경우 롤백, JDBC자원 회수 • Spring과 같은 서비스 계층에서의 트랜잭션 관리 29

  30. 사용하기 캐시 타입 • GC기반 MEMORY • 시간 기반 LRU FIFO • 외부 캐시 OSCACHE 30

  31. 사용하기 캐시 • 캐시되는 데이터 • SQL맵 구문 아이디 • 실제 쿼리문 • com.ibatis.sqlmap.engine.mapping.statement아래 각각의 Statement객체 내 메서드 명 예) executeQueryForList 이외 iBATIS의 캐시 객체에서 지정하는 몇 가지 값들 31

  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이상의 버전이 필요함 32

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

  34. 사용하기 성능을 향상시키는 방법 • parameterMap이나parameterClass속성을 명시적으로 선언 • <update id="updateAccount" parameterClass="Account"> • </update> • <resultMap>를 명시적으로 정의하고 결과의 재매핑(remapResults = true)옵션은 사용하지 말라. • Map이나XML이 아닌 자바Bean을 사용하라. • 표현이나 배열 또는 혼합된Bean이나Map 프로퍼티가 아닌 간단한 프로터티를 사용하라. • <settings>요소에 바이트코드 향상 기능을 활성화한다. - enhancementEnabled="true" 34

  35. 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); 35

  36. 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(); 36

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

  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-208sqlmap설정파일에 대한 Hot Deploy기능 지원 38

  39. 현재 진행중인 이슈 현재 진행중인 이슈 • Improving startup time (Dynamically loading SQL maps based on namespace) http://issues.apache.org/jira/browse/IBATIS-425 설정파일이 너무 많은 경우 WAS가 정상적으로 시작되는 시간이 너무 오래 걸려서 운영 시 어려움이 있다.namespace기반으로 초기 일부만 로딩하고 나머지는 해당 namespace를 기준으로 차후 로딩을 하는 형태의 기능 요청. 39

  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에서도 버전을 올라가면서 관련 설정을 줄일 수 있는 기능을 하나씩 추가하고 있음. 40

  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이상에서 지원하는 제네릭을 지원해달라는 요청. 41

  42. 현재 진행중인 이슈 참고자료 • 관련 사이트 iBATIS- http://ibatis.apache.org openframework 위키 –http://openframework.or.kr/Wiki.jsp?page=PersistentLayer#refpersistentLayer-2 • 관련 서적 iBATIS 인 액션 (이동국, 위키북스) Pro Spring (Rob Harrop, Jan Machac다) 42

  43. 감사합니다.

More Related