슬라이드 1

Similar documents
< 목차 > 1. Data Access Service 개요 (ibatis 활용 ) 3. DBIO 소개

슬라이드 1

Spring Boot/JDBC JdbcTemplate/CRUD 예제

Connection 8 22 UniSQLConnection / / 9 3 UniSQL OID SET

표준프레임워크로 구성된 컨텐츠를 솔루션에 적용하는 것에 문제가 없는지 확인

10.ppt

- JPA를사용하는경우의스프링설정파일에다음을기술한다. <bean id="entitymanagerfactory" class="org.springframework.orm.jpa.localentitymanagerfactorybean" p:persistenceunitname=

쉽게 풀어쓴 C 프로그래밊

슬라이드 1

4 주차 - SPRING 환경설정및구현 Spring 기반의웹프로젝트를구성하고싶어요 T^T Spring 기반의웹환경구축 1. web.xml 수정으로 Spring 을설정하는방법 2. eclipse Spring Plug-In 을활용한템플릿프로젝트자동구성필수는아니지만해놓으면편

iBATIS-SqlMaps-2-Tutorial

untitled

13주-14주proc.PDF

(jpetstore \277\271\301\246\267\316 \273\354\306\354\272\270\264\302 Spring MVC\277\315 iBatis \277\254\265\277 - Confluence)

Intro to Servlet, EJB, JSP, WS

ALTIBASE 사용자가이드 Templete

@OneToOne(cascade = = "addr_id") private Addr addr; public Emp(String ename, Addr addr) { this.ename = ename; this.a

목차 BUG DEQUEUE 의 WAIT TIME 이 1 초미만인경우, 설정한시간만큼대기하지않는문제가있습니다... 3 BUG [qp-select-pvo] group by 표현식에있는컬럼을참조하는집합연산이존재하지않으면결괏값오류가발생할수있습니다... 4

Microsoft PowerPoint - ibatis.pptx

ALTIBASE 사용자가이드 Templete

C# Programming Guide - Types

<property name="configlocation" value="classpath:/egovframework/sqlmap/example/sql-map-config.xml"/> <property name="datasource" ref="datasource2"/> *

Spring Boot

Microsoft PowerPoint - GUI _DB연동.ppt [호환 모드]

파워포인트 템플릿

슬라이드 1

I. Introduction... 1 II. Jdbc Support 구현배경 사용자요구사항 p6spy Architecture Architecture InjectionPa

1

* Factory class for query and DML clause creation * tiwe * */ public class JPAQueryFactory implements JPQLQueryFactory private f

J2EE Concepts

슬라이드 1

Microsoft PowerPoint - CSharp-10-예외처리

<C0CCBCBCBFB52DC1A4B4EBBFF82DBCAEBBE7B3EDB9AE2D D382E687770>

ALTIBASE 사용자가이드 Templete

목차 BUG offline replicator 에서유효하지않은로그를읽을경우비정상종료할수있다... 3 BUG 각 partition 이서로다른 tablespace 를가지고, column type 이 CLOB 이며, 해당 table 을 truncate

I T C o t e n s P r o v i d e r h t t p : / / w w w. h a n b i t b o o k. c o. k r

PowerPoint Presentation

ORANGE FOR ORACLE V4.0 INSTALLATION GUIDE (Online Upgrade) ORANGE CONFIGURATION ADMIN O

USER GUIDE

Spring Data JPA Many To Many 양방향 관계 예제

Interstage5 SOAP서비스 설정 가이드

서현수

ALTIBASE 사용자가이드 Templete

MyBatis

Mobile Service > IAP > Android SDK [ ] IAP SDK TOAST SDK. IAP SDK. Android Studio IDE Android SDK Version (API Level 10). Name Reference V

MyBatis

Microsoft PowerPoint - JCO2007_Spring2.0_발표자료_Rev-A.ppt [호환 모드]

목차 BUG 문법에맞지않는질의문수행시, 에러메시지에질의문의일부만보여주는문제를수정합니다... 3 BUG ROUND, TRUNC 함수에서 DATE 포맷 IW 를추가지원합니다... 5 BUG ROLLUP/CUBE 절을포함하는질의는 SUBQUE

No Slide Title

DBMS & SQL Server Installation Database Laboratory

PowerPoint 프레젠테이션

iBATIS-SqlMaps-2

Microsoft PowerPoint - Smart CRM v4.0_TM 소개_ pptx

NoSQL

다른 JSP 페이지호출 forward() 메서드 - 하나의 JSP 페이지실행이끝나고다른 JSP 페이지를호출할때사용한다. 예 ) <% RequestDispatcher dispatcher = request.getrequestdispatcher(" 실행할페이지.jsp");

FileMaker 15 ODBC 및 JDBC 설명서

Analytics > Log & Crash Search > Unity ios SDK [Deprecated] Log & Crash Unity ios SDK. TOAST SDK. Log & Crash Unity SDK Log & Crash Search. Log & Cras

thesis

InsertColumnNonNullableError(#colName) 에해당하는메시지출력 존재하지않는컬럼에값을삽입하려고할경우, InsertColumnExistenceError(#colName) 에해당하는메시지출력 실행결과가 primary key 제약에위배된다면, Ins

JUNIT 실습및발표

Spring Batch 2.0 시작하기

歯JavaExceptionHandling.PDF

rmi_박준용_final.PDF

iBATIS-SqlMaps-2

JAVA PROGRAMMING 실습 08.다형성

PowerPoint 프레젠테이션

Microsoft PowerPoint - 04-UDP Programming.ppt

chap 5: Trees

ETL_project_best_practice1.ppt

단계

유니티 변수-함수.key

JVM 메모리구조

API STORE 키발급및 API 사용가이드 Document Information 문서명 : API STORE 언어별 Client 사용가이드작성자 : 작성일 : 업무영역 : 버전 : 1 st Draft. 서브시스템 : 문서번호 : 단계 : Docum

PowerPoint 프레젠테이션

혼자서일을다하는 JSP. 이젠일을 Servlet 과나눠서한다. JSP와서블릿의표현적인차이 - JSP는 <html> 내에서자바를사용할수있는수단을제공한다. - 서블릿은자바내에서 <html> 을작성할수있는수단을제공한다. - JSP나서블릿으로만웹페이지를작성하면자바와다양한코드가

歯sql_tuning2

<4D F736F F F696E74202D20C1A63038C0E520C5ACB7A1BDBABFCD20B0B4C3BC4928B0ADC0C729205BC8A3C8AF20B8F0B5E55D>

슬라이드 1

제11장 프로세스와 쓰레드

SQL Developer Connect to TimesTen 유니원아이앤씨 DB 기술지원팀 2010 년 07 월 28 일 문서정보 프로젝트명 SQL Developer Connect to TimesTen 서브시스템명 버전 1.0 문서명 작성일 작성자

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션

U.Tu System Application DW Service AGENDA 1. 개요 4. 솔루션 모음 1.1. 제안의 배경 및 목적 4.1. 고객정의 DW구축에 필요한 메타정보 생성 1.2. 제품 개요 4.2. 사전 변경 관리 1.3. 제품 특장점 4.3. 부품화형

MS-SQL SERVER 대비 기능

FileMaker ODBC and JDBC Guide

Chap7.PDF

웹연동 } 웹 (Web) 환경에서데이터베이스시스템을연동하는방법은다음과같다 } Server Client 구조의통신 (2-Tier) } Server Middleware Client 구조의통신 (3-Tier) 2

Eclipse 와 Firefox 를이용한 Javascript 개발 발표자 : 문경대 11 년 10 월 26 일수요일

JDBC 소개및설치 Database Laboratory

슬라이드 1

Design Issues

슬라이드 1

PowerPoint Presentation

FileMaker ODBC 및 JDBC 가이드

예제 2) Test.java class A intvar= 10; void method() class B extends A intvar= 20; 1"); void method() 2"); void method1() public class Test 3"); args) A

Cluster management software

q 이장에서다룰내용 1 객체지향프로그래밍의이해 2 객체지향언어 : 자바 2

(Microsoft PowerPoint - java1-lecture11.ppt [\310\243\310\257 \270\360\265\345])

PowerPoint Presentation

MyBatis 3 사용자가이드

Transcription:

1. 개요 - 실행환경데이터처리레이어 (1/3) 데이터베이스에대한연결및영속성처리, 선언적인트랜잭션관리를제공하는 Layer 임 서비스그룹 설명 Presentation Layer 전자정부개발프레임워크실행환경 Business Logic Layer Persistence Layer Batch Layer Integration Layer Mobile Presentation Layer Layer Mobile Device API Presentation Layer Business Logic Layer Persistence Layer 업무프로그램과사용자간의 Interface 를담당하는 Layer 로서, 사용자화면구성, 사용자입력정보검증등의기능을제공함 업무프로그램의업무로직을담당하는 Layer 로서, 업무흐름제어, 에러처리등의기능을제공함 데이터베이스에대한연결및영속성처리, 선언적인트랜잭션관리를제공하는 Layer 임 Batch Layer 대용량데이터처리를위한기반환경을제공하는 Layer 임 Foundation Layer ( 공통기반레이어 ) Integration Layer 타시스템과의연동기능을제공하는 Layer 임 환경 서비스그룹 Foundation Layer 실행환경의각 Layer 에서공통적으로사용하는공통기능을제공함 Page l 3 3

1. 개요 - 실행환경데이터처리레이어 (2/3) 데이터처리레이어는 DataSource, Data Access 등총 4 개의서비스를제공함 실행환경 화면처리레이어 업무처리레이어 데이터처리레이어 배치처리레이어 연계통합레이어 모바일화면처리 모바일디바이스 API Ajax Support MVC UI Adaptor Internationalization Security Biz. Process Management Exception Handling Data Access ORM Transaction DataSource Batch Core Batch Support Batch Execution Message Service Naming Service Web Service UX/UI Component Device API 공통기반레이어 AOP Cache Compress/Decompress Encryption/Decryption Excel File Handling File Upload/Download FTP ID Generation IoC Container Logging Mail Marshalling/Unmarshalling Object Pooling Property Resource Scheduling Server Security String Util XML Manipulation 공통기반레이어살펴보기 Page l 4 4

1. 개요 - 실행환경데이터처리레이어 (3/3) 데이터처리레이어는 Spring, ibatis, MyBatis, Hibernate 등총 4 종의오픈소스 SW 를사용하고있음 서비스오픈소스 SW 버전 DataSource Spring 4.1.2 Data Access ibatis SQL Maps 2.3.4 MyBatis 3.3.0 ORM Hibernate 4.3.11 Transaction Spring 4.1.2 Page l 5 5

2. DataSource 개요 DataSource 서비스 데이터베이스에대한연결을제공하는서비스이다. 다양한방식의데이터베이스연결을제공하고, 이에대한 추상화계층을제공함으로써, 업무로직과데이터베이스연결방식간의종속성을배제한다. DataSource 객체획득방법 DriverManagerDataSource 빈등록 BasicDataSource 빈등록 ComboPooledDataSource 빈등록 JNDI DataSource JNDI Lookup을이용하여 WAS에서제공되는 JNDI tree로부터 DataSource를가져옴 Connection 객체획득방법 : datasource.getconnection(); Page l 6 6

2. DataSource 설명 (1/5) Spring DataSource Spring DataSource 설정 <bean id="datasource" class="org.springframework.jdbc.datasource.drivermanagerdatasource"> <property name="driverclassname" value="${driver}" /> <property name="url" value="${dburl}" /> <property name="username" value="${username}" /> <property name="password" value="${password}" /> </bean> driverclassname : JDBC driver class name 설정 url : DataBase 접근하기위한 JDBC URL username : DataBase 접근하기위한사용자명 password : DataBase 접근하기위한암호 @Resource(name = "datasource") DataSource datasource; 테스트코드 @Test public void testjdbcdatasource() throws Exception { assertnotnull(datasource); assertequals("org.springframework.jdbc.datasource.drivermanagerdatasource", datasource.getclass().getname()); Connection con = null; Statement stmt = null; ResultSet rs = null; try { con = datasource.getconnection(); assertnotnull(con); stmt = con.createstatement(); rs = stmt.executequery("select 'x' as x from dual"); while (rs.next()) { assertequals("x", rs.getstring(1));. } } Page l 7 7

2. DataSource 설명 (2/5) DBCP DataSource } DBCP DataSource 설정 <bean id="datasource" class="org.apache.commons.dbcp.basicdatasource destroy-method="close > <property name="driverclassname" value="${driver}" /> <property name="url" value="${dburl}" /> <property name="username" value="${username}" /> <property name="password" value="${password}" /> <property name="defaultautocommit" value="false" /> <property name="poolpreparedstatements" value="true" /> </bean> @Resource(name = "datasource") DataSource datasource; @Test public void testdbcpdatasource() throws Exception { assertnotnull(datasource); 테스트코드 assertequals("org.apache.commons.dbcp.basicdatasource", datasource.getclass().getname()); Connection con = null; Statement stmt = null; ResultSet rs = null; try { } con = datasource.getconnection(); assertnotnull(con); stmt = con.createstatement(); rs = stmt.executequery("select 'x' as x from dual"); while (rs.next()) { assertequals("x", rs.getstring(1)); } driverclassname : jdbc driver class name 설정 url : DataBase url 설정 username : DataBase 접근하기위한사용자명 password : DataBase 접근하기위한암호 defaultautocommit : DataBase 로부터리턴된 connection 에대한 auto-commit 여부를설정 poolpreparedstatements : PreparedStatement 사용여부 Page l 8 8

2. DataSource 설명 (3/5) C3P0 DataSource C3P0 DataSource 설정 <bean id="datasource" class="com.mchange.v2.c3p0.combopooleddatasource destroy-method="close"> <property name="driverclass" value="${driver}" /> driverclass : jdbc driver <property name="jdbcurl" value="${dburl}" /> jdbcurl : DB URL <property name="user" value="${username}" /> user : 사용자명 <property name="password" value="${password}" /> password : 암호 <property name="initialpoolsize" value="3" /> initalpoolsize : 풀초기값 <property name="minpoolsize" value="3" /> maxpoolsize : 풀최대값 <property name="maxpoolsize" value="50" /> idleconnectiontestperiod : idle상태점검시간 <property name="idleconnectiontestperiod" value="200"/> acquireincrement : 증가값 <property name="acquireincrement" value="1" /> maxstatements : 캐쉬유지여부 <property name="maxstatements" value="0" /> numhelperthreads : HelperThread 개수 <property name="numhelperthreads" value="3" /> </bean> 테스트코드 @Resource(name = "datasource") DataSource datasource; @Test public void testc3p0datasource() throws Exception { assertnotnull(datasource); assertequals("com.mchange.v2.c3p0.combopooleddatasource", datasource.getclass().getname()); Connection con = null; Statement stmt = null; ResultSet rs = null; try { con = datasource.getconnection(); assertnotnull(con); stmt = con.createstatement(); rs = stmt.executequery("select 'x' as x from dual"); while (rs.next()) { assertequals("x", rs.getstring(1)); } } } Page l 9 9

2. DataSource 설명 (4/5) JNDI DataSource JNDI DataSource 설정 1 <jee:jndi-lookup id="datasource" jndi-name="${jndiname}" resource-ref="true"> <jee:environment> java.naming.factory.initial=${jeus.java.naming.factory.initial} java.naming.provider.url=${jeus.java.naming.provider.url} </jee:environment> </jee:jndi-lookup> JNDI DataSource 설정 2 <util:properties id="jndiproperties" location="classpath:/meta-inf/spring/jndi.properties" /> <jee:jndi-lookup id="datasource" jndi-name="${jndiname}" resource-ref="true" environment-ref="jndiproperties" /> 10 Page l 10

2. DataSource 설명 (5/5) @Resource(name = "datasource") DataSource datasource; 테스트코드 @Test public void testjndijeusdatasource() throws Exception { assertnotnull(datasource); assertequals("jeus.jdbc.connectionpool.datasourcewrapper", datasource.getclass().getname()); //assertequals("weblogic.jdbc.common.internal.rmidatasource_922_wlstub", datasource.getclass().getname()); Connection con = null; } Statement stmt = null; ResultSet rs = null; try { con = datasource.getconnection(); assertnotnull(con); stmt = con.createstatement(); rs = stmt.executequery("select 'x' as x from dual"); while (rs.next()) { assertequals("x", rs.getstring(1)); } } 11 Page l 11

2. DataSource 참고자료 Commons DBCP http://commons.apache.org/dbcp/ C3P0 http://www.mchange.com/projects/c3p0/index.html 12 Page l 12

3. Data Access 개요 서비스개요 JDBC 를사용한 Data Access를추상화하여간편하고쉽게사용할수있는 Data Mapper framework 인 ibatis 를 Data Access 기능의기반오픈소스로채택 ibatis 를사용하면관계형데이터베이스에엑세스하기위해필요한일련의자바코드사용을현저히줄일수있으며간단한 XML 기술을사용하여 SQL 문을 JavaBeans ( 또는 Map) 에간편하게매핑할수있음 Data Access 서비스는다양한데이터베이스솔루션및데이터베이스접근기술에일관된방식으로대응하기위한서비스 데이터를조회하거나입력, 수정, 삭제하는기능을수행하는메커니즘을단순화함 데이터베이스솔루션이나접근기술이변경될경우에도데이터를다루는시스템영역의변경을최소화할수있도록데이터베이스와의접점을추상화함 추상화된데이터접근방식을템플릿 (Template) 으로제공함으로써, 개발자들의업무효율을향상시킴. 13 Page l 13

3. Data Access ibatis 개요 (1/3) ibatis 는단순성이라는사상을강조한퍼시스턴스프레임워크로, SQL 맵을이용하여반복적이고 복잡한 DB 작업코드를최소화함 단순성이라는사상을강조하여, XML 을이용하여 Stored Procedure 혹은 SQL 문과자바객체간의매핑을지원 2001 년 Clinton Begin (Apache 소프트웨어재단 ) 에의해개발된퍼시스턴스프레임워크 * Performance Comparison of Persistence Frameworks, Sabu M. Thampi, Ashwin a K. (2007) 14 Page l 14

3. Data Access ibatis 개요 (2/3) ibatis는소스코드외부에정의된 SQL문과설정정보를바탕으로, 객체와테이블간의매핑기능을제공 ibatis Data Mapper API 는 XML을사용하여 SQL문과객체매핑정보를간편하게기술할수있도록지원 자바빈즈객체와 Map 구현체, 다양한원시래퍼타입 (String, Integer..) 등을 PreparedStatement 의파라미터나 ResultSet에대한결과객체로쉽게매핑해줌 구성요소 SqlMapConfig XML File SqlMap XML File SQL Map Mapped Statement Parameter Object Result Object 설명 - ibatis 동작을위한 DataSource, Data Mppaer 및 Thread Management 등과같은공통설정 - XML 방식으로실행할 SQL문과매핑정보를설정 - ibatis는 PreparedStatement 인스턴스를생성하고, 제공파라미터객체를사용해서파라미터를셋팅한후, 를실행하고 ResultSet으로부터결과객체를생성 - Parameter 객체와 Result 객체를이용하여 SQL 로치환 - 파마리터객체는 JavaBean, Map, Primitive 객체로서, 입력값을셋팅하기위해사용되는객체 - 결과객체는 JavaBean, Map, Primitive 객체로서, 쿼리문의결과값을담는객체 15 Page l 15

3. Data Access ibatis 개요 (3/3) 주요기능 추상화된접근방식제공 JDBC 데이터엑세스에대한추상화된접근방식으로, 간편하고쉬운 API, 자원연결 / 해제, 공통에러처리등을통합지원함 자바코드로부터 SQL문분리 소스코드로부터 SQL문을분리하여별도의 repository( 의미있는문법의 XML) 에유지하고이에대한빠른참조구조를내부적으로구현하여관리 / 유지보수 / 튜닝의용이성을보장함. SQL문자동실행, 입 / 출력파라미터자동바인딩지원 쿼리문의입력파라미터에대한바인딩과실행결과 resultset 의가공 ( 맵핑 ) 처리시객체 (VO, Map, List) 수준의자동화를지원함 Dynamic SQL 지원 코드작성, API 직접사용없이입력조건에따른동적인쿼리문변경을지원함 다양한 DB 처리지원 기본질의외에 Batch SQL, Paging, Callable Statement, BLOB/CLOB 등다양한 DB처리를지원함 16 Page l 16

3. Data Access ibatis 개발가이드 ibatis를사용한 Persistence Layer 개발순서 1) [ibatis 설정 1] SQL Mapping XML 파일작성 실행할 SQL문과관련정보설정 SELECT/INSERT/UPDATE/DELETE, Parameter/Result Object, Dynamic SQL 등 2) [ibatis 설정 2] ibatis Configuration XML 파일작성 ibatis 동작에필요한옵션을설정 <sqlmap>: SQL Mapping XML 파일의위치 3) [ 스프링연동설정 ] SqlMapClientFactoryBean 정의 Spring와 ibatis 연동을위한설정 역할 ) ibatis 관련메서드실행을위한 SqlMapClient 객체를생성 datasource: DB Connection 생성 configlocation: ibatis Configuration XML 파일의위치 mappinglocations: 모든 SQL Mapping XML 파일을일괄지정가능. 단, Configuration 파일에중복선언할수없다. 4) DAO 클래스작성 실행할 SQL문을호출하기위한메서드구현 : SQL Mapping XML 내에정의한각 Statement id를매개변수로전달 규칙 ) SqlMapClientDaoSupport를상속하는 EgovAbstractDAO 클래스를상속받아확장 / 구현 17 Page l 17

3. Data Access ibatis 설명 (1/21) [ibatis 설정 1] SQL Mapping XML 파일작성 (1/2) 실행할 SQL 문과 Parameter Object 와 Result Object, Dynamic SQL 등을설정 SQL Mapping XML 설정 <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE sqlmap PUBLIC "-//ibatis.com//dtd SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map-2.dtd"> <sqlmap namespace="dept"> <typealias alias="deptvo" type= x.y.z.deptvo" /> <resultmap id="deptresult" class="deptvo"> <result property="deptno" column="dept_no" /> <result property="deptname" column="dept_name" /> <result property="loc" column="loc" /> </resultmap> 루트요소 <sqlmap>, namespace 는옵션 현파일내에서자주사용되는객체에 alias 를지정하여풀네임대신사용 객체변수명과테이블컬럼명이다른경우, 두관계를정의하기위한요소로, SQL 문외부에정의하고 SQL 문에서 resultmap 속성으로참조 <select id="selectdept" parameterclass="deptvo" resultmap="deptresult"> <![CDATA[ select DEPT_NO, DEPT_NAME, LOC from DEPT where DEPT_NO = #deptno# ]]> </select> ResultSet 에저장된쿼리결과값을컬럼명 = 변수명기준으로, Result Object 에바인딩할때사용한다. 이예제에서는객체변수명과테이블컬럼명이다르므로, resultmap 요소를이용하여변수명 - 컬럼명관계정보를제공 <! 참고 ) Result Object 의변수명과 Table 의컬럼명이동일하다면, resultclass 속성을이용하여직접 deptvo 를지정해도된다 parametermap 속성사용은권장하지않음 --> <insert id="insertdept" parameterclass="deptvo"> <![CDATA[ insert into DEPT (DEPT_NO,DEPT_NAME,LOC) values (#deptno#,#deptname#,#loc#) ]]> </insert> 데이터입력을위해 Parameter Object 로부터값을전달받아 SQL 문에바인딩 18 Page l 18

3. Data Access ibatis 설명 (2/21) [ibatis 설정 1] SQL Mapping XML 파일작성 (2/2) 실행할 SQL 문과 Parameter Object 와 Result Object, Dynamic SQL 등을설정 <update id="updatedept" parameterclass="deptvo"> update DEPT set DEPT_NAME = #deptname#, LOC = #loc# where DEPT_NO = #deptno# </update> <delete id="deletedept" parameterclass="deptvo"> delete from DEPT where DEPT_NO = #deptno# </delete> <sql id="columns">dept_no, DEPT_NAME, LOC</sql> SQL Mapping XML 설정 <select id="selectdeptlist" parameterclass="deptvo" resultmap="deptresult"> select <include refid="columns" /> from DEPT <dynamic prepend="where"> <isnotnull prepend="and" property="deptno"> DEPT_NO = #deptno# </isnotnull> <isnotnull prepend="and" property="deptname"> DEPT_NAME LIKE '%' #deptname# '%' </isnotnull> </dynamic> </select> </sqlmap> 반복되는구문을재사용하기위한요소로, 다른 Statement 에서 <include> 의 refid 속성으로참조 SQL 문실행전, 다양한조건에따라동적으로 SQL 문을변환하여실행하는요소로, deptno 혹은 deptname 변수가 NotNull 이면, 두변수값을파라미터로 WHERE 조건절을만들고, 모두 Null 이면 SELECT 절 ~FROM 절까지수행한다 19 Page l 19

3. Data Access ibatis 설명 (3/21) [ibatis 설정 2] ibatis Configuration XML 파일 (1/3) ibatis 공통설정파일로, SqlMapClient 설정관련상세내역을제어할수있는메인설정 주로 transaction 관리관련설정및다양한옵션설정, Sql Mapping 파일들에대한 path 설정등을포함한다. ibatis Configuration XML 설정 <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE sqlmapconfig PUBLIC "-//ibatis.com//dtd SQL Map Config 2.0//EN "http://www.ibatis.com/dtd/sql-map-config- 2.dtd"> <sqlmapconfig> 루트요소 <sqlmapconfig> <sqlmap resource="meta-inf/sqlmap/mappings/testcase-basic.xml" /> <sqlmap../> <settings cachemodelsenabled="true" enhancementenabled="true lazyloadingenabled="true" maxrequests="128" maxsessions="10" maxtransactions="5" usestatementnamespaces="false" defaultstatementtimeout="1" /> <typehandler javatype="java.util.calendar" jdbctype="timestamp" callback="egovframework.rte.psl.dataaccess.typehandler.calendartypehandler" /> SQL Mapping File 의위치설정 ( 필수 ) SqlMapClient 객체생성옵션 javatype 과 jdbctype 간타입핸들링 <properties resource="meta-inf/spring/jdbc.properties" /> <transactionmanager type="jdbc"> <datasource type="dbcp"> <property name="driverclassname" value="${driver}" /> <property name="url" value="${dburl}" /> <property name="username" value="${username}" /> <property name="password" value="${password}" /> <!-- OPTIONAL PROPERTIES BELOW --> placeholder 사용을위한 Properties 파일참조설정 TransactionManager 와 DataSource 설정 20 Page l 20

3. Data Access ibatis 설명 (4/21) [ibatis 설정 2] ibatis Configuration XML 파일 (2/3) <property name="maxactive" value="10" /> <property name="maxidle" value="5" /> <property name="maxwait" value="60000" /> <!-- validation query --> <!--<property name="validationquery" value="select * from DUAL" />--> <property name="logabandoned" value="false" /> <property name="removeabandoned" value="false" /> <property name="removeabandonedtimeout" value="50000" /> <property name="driver.driverspecificproperty" value="somevalue" /> </datasource> </transactionmanager> </sqlmapconfig> 요소 properties settings 설명표준 java properties (key=value 형태 ) 파일에대한연결을지원하며설정파일내에서 ${key} 와같은 properties 형태로외부화놓은실제의값 ( 여기서는 DB 접속관련 driver, url, id/pw) 을참조할수있다. resource 속성으로 classpath 지정가능, url 속성으유효한 URL 상에있는자원을지정가능이설정파일을통해생성된 SqlMapClient instance 에대하여다양한옵션설정을통해최적화할수있도록지원한다. 모든속성선택사항 (optional) 이다. typehandler javatype 과 jdbctype 일치를위해 TypeHandler 구현체를등록하여사용할수있다. sqlmap 매핑할 SQL 구문이정의된파일을지정한다. 21 Page l 21

3. Data Access ibatis 설명 (5/21) [ibatis 설정 2] ibatis Configuration XML 파일 (3/3) <settings> 에서사용가능한속성들 속성 설명 예시및디폴트값 maxrequests 같은시간대에 SQL 문을실행할수있는 thread 의최대갯수지정 maxrequests= 256, 512 maxsessions 주어진시간에활성화될수있는 session( 또는 client) 수지정 maxsessions= 64, 128 maxtransactions cachemodelsenabled lazyloadingenabled 같은시간대에 SqlMapClient.startTransaction() 에들어갈수있는최대갯수지정 SqlMapClient 의모든 cachemodel 에대한사용여부를 global 하게지정 SqlMapClient 의모든 lazy loading 에대한사용여부를 global 하게지정 maxtransactions= 16, 32 cachemodelsenabled= true, true (enabled) lazyloadingenabled= true, true (enabled) enhancementenabled runtime bytecode enhancement 기술사용여부지정 enhancementenabled= true, false (disabled) usestatementnamespaces Statement 호출시 namespace 값사용여부 usestatementnamespaces= false, false (disabled) defaultstatementtimeout 모든 JDBC 쿼리에대한 timeout 시간 ( 초 ) 지정, 각 statement 의 설정으로 override 가능함. 모든 driver 가이설정을지원하는것은 아님에유의할것. 지정하지않는경우 timeout 없음 (cf. 각 statement 설정에따라 ) classinfocacheenabled introspected(java 의 reflection API 에의해내부참조된 ) class 의 캐쉬를유지할지에대한설정 classinfocacheenabled= true, true (enabled) statementcachingenabled prepared statement 의 local cache 를유지할지에대한설정 statementcachingenabled= true, true (enabled) 22 Page l 22

3. Data Access ibatis 설명 (6/21) [ 스프링연동설정 ] SqlMapClientFactoryBean 정의 Spring과 ibatis 연동을위한설정으로, ibatis 관련메서드실행을위해 SqlMapClient 객체가필요 스프링에서 SqlMapClient 객체를생성하고관리할수있도록, SqlMapClientFactoryBean을정의 Id와 class는고정값 datasource : 스프링에서설정한 Datasource Bean id를설정하여 ibatis가 DataSource를사용하게한다. configlocation : ibatis Configuration XML 파일이위치하는곳을설정한다. mappinglocations : SQL Mapping XML 파일을일괄지정할수있다. 단, Configuration 파일에중복선언할수없다. 실행환경 3.5 부터는 Spring 4 변경사항에의해 org.springframework.orm.ibatis.sqlmapclientfactorybean 클래스가 egovframework.rte.psl.orm.ibatis.sqlmapclientfactorybean 로변경됨. SqlMapClientFactoryBean 설정 <!-- SqlMap setup for ibatis Database Layer --> <bean id="sqlmapclient" class="egovframework.rte.psl.orm.ibatis.sqlmapclientfactorybean"> <property name= datasource ref=" datasource /> <property name= configlocation value="classpath:/egovframework/sqlmap/rte/sql-map-config.xml" /> <!-- <property name="mappinglocations" value="classpath:/meta-inf/sqlmap/mappings/*.xml" /> --> </bean> 23 Page l 23

3. Data Access ibatis 설명 (7/21) ibatis 를활용한자바클래스작성 EgovAbstractDAO 클래스를상속받아 DAO 클래스를작성 DAO class 샘플코드 @Repository("empDAO") public class EmpMapper extends EgovAbstractDAO { public void insertemp(empvo vo) { insert("insertemp", vo); } EgovAbstractDAO 는 SqlMapDaoSupport 의하위클래스로, SqlMapClient 설정과메소드호출의편리함을제공한다. public int updateemp(empvo vo) { return update("updateemp", vo); } public int deleteemp(empvo vo) { return delete("deleteemp", vo); } SQL Mapper XML 내에정의한각 Statement id 를이용하여실행할 SQL 문을호출하도록작성한다. public EmpVO selectemp(empvo vo) { return (EmpVO) selectbypk("selectemp", vo); } } public List<EmpVO> selectemplist(empvo searchvo) { return list("selectemplist", searchvo); } 24 Page l 24

3. Data Access ibatis 설명 (8/21) 세부사항설명 ibatis Configuration ibatis 의메인설정파일인 SQL Map XML Configuration 파일 ( 이하 sql-map-config.xml 설정파일 ) 작성과상세한옵션 설정 Data Type 데이터베이스를이용하여데이터를저장하고조회할때 Java 어플리케이션에서의 Type 과 DBMS 에서지원하는관련매핑 jdbc Type 의정확한사용이필요 parametermap 해당요소로 SQL 문외부에정의한입력객체의속성에대한 name 및 javatype, jdbctype 을비롯한옵션을설정할수있 는매핑요소 Inline parameters prepared statement 에대한바인드변수매핑처리를위한 parametermap 요소 (SQL 문외부에정의한입력객체 property name 및 javatype, jdbctype 을비롯한옵션을설정매핑요소 ) 와동일한기능을처리하는간편한방법 resultmap resultmap 은 SQL 문외부에정의한매핑요소로, result set 으로부터어떻게데이터를뽑아낼지, 어떤칼럼을어떤 property 로매핑할지에대한상세한제어를가능케해줌 Dynamic SQL SQL 문의동적인변경에대한상대적으로유연한방법을제공하는 ibatis 의 Dynamic 요소 25 Page l 25

3. Data Access ibatis 설명 (9/21) 세부사항설명 - Data Type 어플리케이션을작성할때 Data Type 에대한올바른사용과관련처리는매우중요함 데이터베이스를이용하여데이터를저장하고조회할때 Java 어플리케이션에서의 Type 과 DBMS 에서지원하는관련매핑 jdbc Type 의정확한사용이필요함 기본 Data Type 사용방법 ibatis SQL Mapper 프레임워크는 Java 어플리케이션영역의표준 JavaBeans 객체 ( 또는 Map 등 ) 의각 Attribute 에대한 Java Type 과 JDBC 드라이버에서지원하는각 DBMS의테이블칼럼에대한 Data Type 의매핑을기반으로 parameter / result 객체에대한바인딩 / 매핑을처리함 각 javatype 에대한매칭되는 jdbctype 은일반적인 Ansi SQL 을사용한다고하였을때아래에서대략확인할수있음 특정 DBMS 벤더에따라추가적으로지원 / 미지원하는 jdbctype 이다를수있고, 또한같은 jdbctype 을사용한다하더라도타입에따른사용가능한경계값 (boundary max/min value) 은다를수있음 26 Page l 26

3. Data Access ibatis 설명 (10/21) 세부사항설명 - parametermap 해당요소로 SQL 문외부에정의한입력객체의속성에대한 name 및 javatype, jdbctype 을비롯한옵션을설정할수있는매핑요소임. JavaBeans 객체 ( 또는 Map 등 ) 에대한 prepared statement 에대한바인드변수매핑을처리할수있음. 유사한기능을처리하는 parameterclass 나 Inline Parameter 에비해많이사용되지않지만더기술적인 (descriptive) parametermap( 예를들어 stored procedure 를위한 ) 이필요함 XML 의일관된사용과순수성을지키고자할때좋은접근법이될수도있음. Dynamic 요소와함께사용될수없고바인드변수의갯수와순서를정확히맞춰야하는불편이있는등일반적으로사용을추천하지않음. 27 Page l 27

3. Data Access ibatis 설명 (11/21) 세부사항설명 - Inline Parameters prepared statement 에대한바인드변수매핑처리를위한 parametermap 요소 SQL 문외부에정의한입력객체 property name 및 javatype, jdbctype 을비롯한옵션을설정매핑요소와동일한기능을처리하는간편한방법을 Inline Parameters 방법으로제공보통 parameterclass 로명시된입력객체에대해바인드변수영역을간단한 #property# 노테이션으로나타내는 Inline Parameter 방법은기존 parametermap 에서의? 와이의순서를맞춘외부 parametermap 선언으로처리하는방법에비해많이사용되고일반적으로추천하는방법 Dynamic 요소와함께사용될수있고별도의외부매핑정의없이바인드변수처리가필요한위치에해당 property 를직접사용가능하며, 필요한경우 jdbctype 이나 nullvalue 를간단한추가노테이션과같이지정할수있음 (ex. #empname:varchar:blank# ) (ex. #comm,javatype=decimal,jdbctype=numeric,nullvalue=-99999# ),(comma) 로구분된필요한속성 = 값을상세하게기술할수도있음. 28 Page l 28

3. Data Access ibatis 설명 (12/21) 세부사항설명 - resultmap resultmap 은 SQL 문외부에정의한매핑요소 result set 으로부터어떻게데이터를뽑아낼지, 어떤칼럼을어떤 property로매핑할지에대한상세한제어를가능케해줌. resultmap 은일반적으로가장많이사용되는중요한매핑요소로 resultclass 속성을이용한자동매핑접근법에비교하여칼럼타입의지시, null value 대체값, typehandler 처리, complex property 매핑 ( 다른 JavaBean, Collections 등을포함하는복합객체 ) 등을허용함. 29 Page l 29

3. Data Access ibatis 설명 (13/21) 세부사항설명 - Dynamic SQL 일반적으로 JDBC API 를사용한코딩에서한번정의한쿼리문을최대한재사용하고자하나단순파라메터변수의값만변경하는것으로해결하기어렵고다양한조건에따라조금씩다른쿼리의실행이필요한경우많은 if~else 조건분기의연결이필요한문제가있음. 1-1 Dynamic SQL mapping xml 파일 SQL Mapping XML Dynamic SQL 설정 <typealias alias="jobhistvo" type="egovframework.rte.psl.dataaccess.vo.jobhistvo" /> <select id="selectjobhistlistusingdynamicelement" parameterclass="jobhistvo" resultclass="jobhistvo"> <![CDATA[ select EMP_NO as empno, START_DATE as startdate, END_DATE as enddate, JOB as job, SAL as sal, COMM as comm, DEPT_NO as deptno from JOBHIST ]]> <dynamic prepend="where"> <isnotnull property="empno" prepend="and"> EMP_NO = #empno# </isnotnull> </dynamic> order by EMP_NO, START_DATE </select> 30 Page l 30

3. Data Access ibatis 설명 (14/21) 세부사항설명 - Dynamic SQL Unary 비교연산 (1/2) 1-2 Sample Unary 비교연산 SQL Mapping XML Dynamic SQL 설정 <typealias alias="egovmap" type="egovframework.rte.psl.dataaccess.util.egovmap" /> <select id="selectdynamicunary" parameterclass="map" remapresults="true" resultclass="egovmap"> select <dynamic> <isempty property="testemptystring"> 'empty String' as IS_EMPTY_STRING </isempty> <isnotempty property="testemptystrinag"> 'not empty String' as IS_EMPTY_STRING </isnotempty>.. <ispropertyavailable prepend=", " property="testproperty"> 'testproperty Available' astest_property_available </ispropertyavailable> <isnotpropertyavailable prepend=", " property="testproperty"> 'testproperty Not Available' as TEST_PROPERTY_AVAILABLE </isnotpropertyavailable> </dynamic> from dual </select> 31 Page l 31

3. Data Access ibatis 설명 (15/21) 세부사항설명 - Dynamic SQL Unary 비교연산 (2/2) Unary 비교연산태그 태그 isempty isnotempty isnull isnotnull ispropertyavailable isnotpropertyavailable 설명 Collection, String( 또는 String.valueOf()) 대상속성이 null 이거나 empty( 또는 size() < 1) 인경우 true Collection, String( 또는 String.valueOf()) 대상속성이 not null 이고 not empty( 또는 size() < 1) 인경우 true 대상속성이 null 인경우 true 대상속성이 not null 인경우 true 파라메터객체에대상속성이존재하는경우 true 파라메터객체에대상속성이존재하지않는경우 true Unary 비교연산태그속성 속성 설명 prepend 동적구문앞에추가되는 override 가능한 SQL 영역. property 필수. 파라메터객체의어떤 property 에대한체크인지지정. removefirstprepend open close 첫번째로내포될내용을생성하는태그의 prepend 를제거할지여부 (true/false) 전체결과구문에대한시작문자열 전체결과구문에대한닫는문자열 32 Page l 32

3. Data Access ibatis 설명 (16/21) 세부사항설명 - Dynamic SQL Binary 비교연산 (1/2) 1-3 Sample Binary 비교연산 SQL Mapping XML Dynamic SQL 설정 <typealias alias="egovmap type="egovframework.rte.psl.dataaccess.util.egovmap" /> <select id="selectdynamicbinary" parameterclass="map remapresults="true" resultclass="egovmap"> select <dynamic> <isequal property="teststring" comparevalue="test"> '$teststring$' as TEST_STRING, 'test : equals' as IS_EQUAL </isequal> <isnotequal property="teststring" comparevalue="test"> '$teststring$' as TEST_STRING, 'test : not equals' as IS_EQUAL </isnotequal>.. <islessthan property="testotherstring" prepend=", compareproperty="teststring"> '''$testotherstring$'' <![CDATA[<]]> ''$teststring$''' as COMPARE_PROPERTY_LESS_THAN </islessthan> </ispropertyavailable> </dynamic> from dual </select> 33 Page l 33

3. Data Access ibatis 설명 (17/21) 세부사항설명 - Dynamic SQL Binary 비교연산 (2/2) Binary 비교연산태그 태그 isequal isnotequal isgreaterequal isgreaterthan islessequal 설명대상속성이 comparevalue 값또는 compareproperty 로명시한대상속성값과같은경우 true 대상속성이 comparevalue 값또는 compareproperty 로명시한대상속성값과다른경우 true 대상속성이 comparevalue 값또는 compareproperty 로명시한대상속성값보다크거나같은경우 true 대상속성이 comparevalue 값또는 compareproperty 로명시한대상속성값보다큰경우 true 대상속성이 comparevalue 값또는 compareproperty 로명시한대상속성값보다작거나같은경우 true islessthan Binary 비교연산태그속성 대상속성이 comparevalue 값또는 compareproperty 로명시한대상속성값보다작은경우 true 속성 설명 prepend 동적구문앞에추가되는 override 가능한 SQL 영역. property 필수. 파라메터객체의어떤 property 에대한비교인지지정. compareproperty 파라메터객체의다른 property 와대상 property 값을비교하고자할경우지정. (comparevalue 가없는경우필수 ) comparevalue 대상 property 와비교될값을지정. (compareproperty 가없는경우필수 ) removefirstprepend open close 첫번째로내포될내용을생성하는태그의 prepend 를제거할지여부 (true/false) 전체결과구문에대한시작문자열 전체결과구문에대한닫는문자열 34 Page l 34

3. Data Access ibatis 설명 (18/21) 세부사항설명 - Dynamic SQL ParameterPresent 비교 (1/2) 1-4 Sample ParameterPresent 비교 SQL Mapping XML Dynamic SQL 설정 <typealias alias="egovmap" type="egovframework.rte.psl.dataaccess.util.egovmap" /> <select id="selectdynamicparameterpresent" parameterclass="map" remapresults="true resultclass="egovmap"> select <isparameterpresent> 'parameter object exist' as IS_PARAMETER_PRESENT </isparameterpresent> <isnotparameterpresent> 'parameter object not exist' as IS_PARAMETER_PRESENT </isnotparameterpresent> from dual </select> 35 Page l 35

3. Data Access ibatis 설명 (19/21) 세부사항설명 - Dynamic SQL ParameterPresent 비교 (2/2) ParameterPresent 비교태그 태그 설명 isparameterpresent isnotparameterpresent 파라메터객체가전달된 (not null) 경우 true 파라메터객체가전달되지않은 (null) 경우 true ParameterPresent 비교태그속성 속성 설명 prepend 동적구문앞에추가되는 override 가능한 SQL 영역. removefirstprepend 필수. 파라메터객체의어떤 property 에대한비교인지지정. open close 전체결과구문에대한시작문자열 전체결과구문에대한닫는문자열 36 Page l 36

3. Data Access ibatis 설명 (20/21) 세부사항설명 - Dynamic SQL iterate 연산 (1/2) 1-5 Sample iterate 연산 SQL Mapping XML Dynamic SQL 설정 <typealias alias="jobhistvo" type="egovframework.rte.psl.dataaccess.vo.jobhistvo" /> <typealias alias="empincludesemplistvo" type="egovframework.rte.psl.dataaccess.vo.empincludesemplistvo" /> <select id="selectjobhistlistusingdynamiciterate" parameterclass="empincludesemplistvo" resultclass="jobhistvo"> <![CDATA[ select EMP_NO as empno, START_DATE as startdate, END_DATE as enddate, JOB as job, SAL as sal, COMM as comm, DEPT_NO as deptno from JOBHIST ]]> <dynamic prepend="where"> <iterate property="emplist" open="emp_no in (" conjunction=", " close=")"> #emplist[].empno# </iterate> </dynamic> order by EMP_NO, START_DATE </select> 37 Page l 37

3. Data Access ibatis 설명 (21/21) 세부사항설명 - Dynamic SQL iterate 연산 (2/2) iterate 연산태그 태그 iterate collection 형태의대상객체에대하여포함하고있는각개별요소만큼반복루프를돌며해당내용을수행함 설명 iterate 연산태그속성 속성 설명 prepend 동적구문앞에추가되는 override 가능한 SQL 영역. property 필수. 파라미터객체의어떤 property 에대한비교인지지정. removefirstprepend open Close conjunction 첫번째로내포될내용을생성하는태그의 prepend 를제거할지여부 (true/false/iterate) 전체결과구문에대한시작문자열전체결과구문에대한닫는문자열각 iteration 사이에적용될문자열. AND, OR 연산자나 ',' 등의구분자필요시유용함 38 Page l 38

3. Data Access MyBatis 개요 (1/4) MyBatis 데이터매퍼서비스 개발자가작성한 SQL문혹은저장프로시저결과값을자바오브젝트에자동매핑하는서비스 수동적인 JDBC 방식의데이터처리작업코드와는달리쿼리결과와오브젝트간자동매핑을지원 SQL문과저장프로시저는 XML 혹은어노테이션방식으로작성가능 구성요소 설명 MapperConfig - MyBatis 동작을위한기본적인설정을 Mapper Annotations MapperConfig.xml Mapper.xml XML File 공통으로정의 Mapper - 실행할 SQL 문및매핑정보를 XML 방 XML File 으로정의 Mapper Annotations - 자바코드내에서실행할 SQL문및매정보를어노테이션을이용하여정의 - SQL 문의조건절에서값을비교하거나 Parameter Object INSERT, UPDATE 절등에서필요한입력 값을받아오기위한오브젝트 Result Object - 쿼리결과를담아리턴하기위한오브 젝트 39 Page l 39

3. Data Access MyBatis 개요 (2/4) 주요변경사항 ibatis의 SqlMapClient SqlSession 변경 SqlSession 인터페이스 MyBatis를사용하기위한기본적인인터페이스로, SQL문처리를위한메서드를제공 구문실행메서드, 트랜잭션제어메서드등포함 - selectlist(), selectone(), insert(), update(), delete(), commit(), rollback(), SqlSessionFactory 클래스를통해 MyBatis Configuration 정보에해당 SqlSession 인스턴스를생성 어노테이션방식설정도입 MyBatis 는본래 XML 기반의프레임워크였으나, Mybatis 3.x 부터어노테이션방식의설정을지원 Mapper XML File 내 SQL 문및매핑정보를, 자바코드내에서어노테이션으로그대로적용가능 ibatis 의 RowHandler ResultHandler 변경 ResultHandler 인터페이스 Result Object에담겨리턴된쿼리결과를핸들링할수있도록메서드제공 사용예시 ) 대량의데이터처리시, 처리결과를 File로출력하고자할때혹은 Result Object의형태를 Map 형태로가져올때 40 Page l 40

3. Data Access MyBatis 개요 (3/4) Migrating from ibatis (1/2) 변경또는추가사항 ibatis 사용시 MyBatis 사용시 소스 패키지 변경 com.ibatis.* org.apache.ibatis.* 변경 SqlMapClient SqlSession 클래스 변경 SqlMapClientFactory SqlSessionFactory 변경 RowHandler ResultHandler DTD 변경 <!DOCTYPE sqlmapconfig PUBLIC //ibatis.com//dtd SQL Map Config 2.0//EN "http://www.ibatis.com/dtd/sqlmap-config-2.dtd"> <!DOCTYPE configuration PUBLIC "-//mybatis.org//dtd Config 3.0//EN "http://mybatis.org/dtd/mybatis-3- config.dtd"> Configuration XML File 요소와속성 변경 <sqlmapconfig> <configuration> 변경 <settings /> 변경 <typehandler callback= /> 추가 추가 <transactionmanager type= > <datasource type= /> </transactionmanager> 변경 <sqlmap resource= /> <settings> <setting /> </settings> <typehandlers> <typehandler handler= /> </typehandlers> <environment id= > <transactionmanager type= /> <datasource type= /> </environment> <typealiases> <typealias alias= type= /> </typealiases> <mappers> <mapper resource= /> </mappers> 41 Page l 41

3. Data Access MyBatis 개요 (4/4) Migrating from ibatis (2/2) Mapper XML File 변경또는추가사항 ibatis 사용시 MyBatis 사용시 DTD 요소와속성 변경 <!DOCTYPE sqlmap PUBLIC "-//ibatis.com//dtd SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map- 2.dtd"> <!DOCTYPE mapper PUBLIC "-//mybatis.org//dtd Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3- mapper.dtd"> 변경 <sqlmap namespace= > <mapper namespace= > 변경 <cachemodel /> <cache /> 변경 변경 / 추가 스프링연동빈생성변경 쿼리호출파라미터추가 -- SQL Statement <select id= resultclass resultmap= > SELECT * FROM EMP </select> <insert id= parameterclass parametermap= > INSERT INTO EMP VALUES (#empno#, #empname#); </insert> <dynamic> <isequal /> <isnotnull /> </dynamic> <bean id="sqlmapclient" class="egovframework.rte.psl.orm.ibatis.sqlmapclientfac torybean > -- Statement ID 로실행할 SQL 문을호출 List list = selectlist(queryid, parameterobject); <select id= resulttype resultmap= > SELECT * FROM EMP </select> <insert id= parametertype parametermap= > INSERT INTO EMP VALUES (#{empno}, #{empname}); </insert> <if test= /> <choose><when /> <otherwise /> <trim prefixoverrides suffixoverrides= /> <foreach collection= item= /> <bean id="sqlsession" class="org.mybatis.spring.sqlsessionfactorybean"> -- Statement ID 로실행할 SQL 문을호출 List list = selectlist(queryid, parameterobject); -- 메서드명으로실행할쿼리호출 List list = selectlist(parameterobject); 42 Page l 42

3. Data Access MyBatis 개발가이드 MyBatis를활용한 Persistence Layer 개발 1) [MyBatis 설정 1] SQL Mapper XML 파일작성설정 실행할 SQL문과관련정보설정 SELECT/INSERT/UPDATE/DELETE, Parameter/Result Object, Dynamic SQL 등 2) [MyBatis 설정 2] MyBatis Configuration XML 파일작성 MyBatis 동작에필요한옵션을설정 <mapper>: SQL Mapper XML 파일의위치 3) [ 스프링연동설정 ] SqlSessionFactoryBean 정의 Spring와 MyBatis 연동을위한설정 역할 ) MyBatis 관련메서드실행을위한 SqlSession 객체를생성 datasource, configlocation, mapperlocations 속성설정 4) DAO 클래스작성 방법1) SqlSessionDaoSupport를상속하는 EgovAbstractMapper 클래스를상속받아확장 / 구현 실행할 SQL문을호출하기위한메서드구현 : SQL Mapping XML 내에정의한각 Statement id를매개변수로전달 방법2) DAO 클래스를 Interface로작성하고, 각 Statement id와메서드명을동일하게작성 (Mapper Interface 방식 ) Annotation을이용한 SQL문작성가능 메서드명을 Statement id로사용하기때문에, 코드최소화가능 43 Page l 43

3. Data Access MyBatis 설명 (1/12) [MyBatis 설정 1] SQL Mapper XML 파일작성 (1/5) 실행할 SQL 문과 Parameter Object 와 Result Object 정보등을설정 SQL Mapper XML 설정 <?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= Dept"> <resultmap id="deptresult" type= deptvo"> <result property="deptno" column="dept_no" /> <result property="deptname" column="dept_name" /> <result property="loc" column="loc" /> </resultmap> <sql id= columns"> DEPT_NO, DEPT_NAME, LOC</sql> <select id="selectdept parametertype= deptvo resultmap="deptresult"> <![CDATA[ select <include refid="columns" /> from DEPT where DEPT_NO = #{deptno} ]]> </select> </mapper> 루트요소 <sqlmap>, namespace 는각 mapper 파일을구분하기위한속성 deptvo 에대한 Alias 설정은 Configuration 파일에정의되어있음 parameter/resultclass parameter/resulttype 변경됨 파라미터바인딩시, #property# #{property} 변경됨 44 Page l 44

3. Data Access MyBatis 설명 (2/12) [MyBatis 설정 1] SQL Mapper XML 파일작성 (2/5) - Dynamic SQL If if는가장많이사용되는 Dynamic 요소로, test문의 true, false값에따라다양한조건설정이가능 SQL문의다양한위치에서사용가능하고, 선언된 if 조건에따라순서대로 test문을수행 SQL Mapper XML 설정 <select id="selectemplist" parametertype= empvo" resulttype= empvo"> <![CDATA[ select EMP_NO as empno, EMP_NAME as empname from EMP where JOB = Engineer ]]> <if test="empno!= null"> AND EMP_NO = #{empno} </if> <if test="empname!= null"> AND EMP_NAME LIKE '%' #{empname} '% </if> </select> 45 Page l 45

3. Data Access MyBatis 설명 (3/12) [MyBatis 설정 1] SQL Mapper XML 파일작성 (3/5) - Dynamic SQL choose (when, otherwise) 모든조건을적용하는대신한가지조건만을적용해야할필요가있는경우, choose 요소를사용하며이는자바의 switch 구문과유사한개념임 SQL Mapper XML 설정 <select id="selectemplist" parametertype= empvo" resulttype="empvo"> select * from EMP where JOB = Engineer <choose> <when test= mgr!= null > AND MGR like #{mgr} </when> <when test= empno!= null and empname! =null > AND EMP_NAME like #{empname} </when> <otherwise> AND HIRE_STATUS = Y </otherwise> </choose> </select> 46 Page l 46

3. Data Access MyBatis 설명 (4/12) [MyBatis 설정 1] SQL Mapper XML 파일작성 (4/5) - Dynamic SQL trim (where, set) AND, OR,, 와같이반복되는문자를자동적으로 trim( 제거 ) 아래예제의 <trim prefix= WHERE prefixoverrides= AND OR > 은 <where> 와동일하게동작 ` <select id="selectemplist" parametertype= empvo resulttype="empvo"> select * from EMP where <if test="empno!= null"> EMP_NO = #{empno} </if> <if test="empname!= null"> AND EMP_NAME LIKE '%' #{empname} '% </if> </select> 변경 <update id= updateemp" parametertype= empvo > update EMP <trim prefix= SET" suffixoverrides=, "> -- <set> 요소로대체가능 <if test="empno!= null"> EMP_NO = #{empno}, </if> <if test=" empname!= null"> EMP_NAME = #{empname} </if> </trim> </update> 첫번째조건이 false, 두번째조건이 true 일경우, SQL Syntax Error!! <trim prefix="where" prefixoverrides="and OR "> </trim> or <where> 47 Page l 47

3. Data Access MyBatis 설명 (5/12) [MyBatis 설정 1] SQL Mapper XML 파일작성 (5/5) - Dynamic SQL foreach Map, List, Array 에담아넘긴값을꺼낼때사용하는요소 MyBatis Configuration XML 설정 <select id="selectforforeachfromlist" parametertype="map" resultmap="egovmap"> select <!-- List 를넘긴경우, collection= list / Array 를넘긴경우, collection= array 지정 --> <foreach collection="list" item="item" separator=", "> '${item}' as ${item} </foreach> <!-- Map 객체에 collection 이라는키로 List 를넘긴경우 --> <foreach collection="collection" item="item" separator=", "> '${item}' as ${item} </foreach> from dual </select> 48 Page l 48

3. Data Access MyBatis 설명 (6/12) [MyBatis 설정 2] MyBatis Configuration XML 파일작성 MyBatis 공통설정파일로, SqlSession 설정관련상세내역을제어할수있는메인설정 MyBatis Configuration XML 설정 <?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 alias="deptvo" type= x.y.z.service.deptvo" /> <typealias alias="empvo" type="x.y.z.service.empvo" /> </typealiases> <mappers> <mapper resource ="META-INF/sqlmap/mappers/lab-dept.xml" /> <mapper resource ="META-INF/sqlmap/mappers/lab-emp.xml" /> </mappers> </configuration> 요소설명 properties 설정파일내에서 ${key} 와같은형태로외부 properties 파일을참조할수있다. settings typealiases 런타임시 MyBatis 의행위를조정하기위한옵션설정을통해최적화할수있도록지원한다 타입별칭을통해자바타입에대한좀더짧은이름을사용할수있다. 오직 XML 설정에서만사용되며, 타이핑을줄이기위해사용된다. typehandlers javatype 과 jdbctype 일치를위해 TypeHandler 구현체를등록하여사용할수있다. environments 환경에따라 MyBatis 설정을달리적용할수있도록지원한다. Mappers 매핑할 SQL 구문이정의된파일을지정한다. 49 Page l 49

3. Data Access MyBatis 설명 (7/12) [ 스프링연동설정 ] SqlSessionFactoryBean 정의 Spring와 MyBatis 연동을위한설정으로, MyBatis 관련메서드실행을위해 SqlSession 객체가필요 스프링에서 SqlSession 객체를생성하고관리할수있도록, SqlSessionFactoryBean을정의 Id와 class는고정값 datasource : 스프링에서설정한 Datasource Bean id를설정하여 MyBatis가 DataSource를사용하게한다. configlocation : MyBatis Configuration XML 파일이위치하는곳을설정한다. mapperlocations : SQL Mapper XML 파일을일괄지정할수있다. 단, Configuration 파일에중복선언할수없다. SqlSessionFactoryBean 설정 <!-- SqlSession setup for MyBatis Database Layer --> <bean id="sqlsession" class="org.mybatis.spring.sqlsessionfactorybean"> <property name="datasource" ref="datasource" /> <property name="configlocation" value="classpath:/meta-inf/sqlmap/config/sql-mapper-config.xml" /> <!-- <property name="mapperlocations" value="classpath:/meta-inf/sqlmap/mappers/*.xml" /> --> </bean> 50 Page l 50

3. Data Access MyBatis 설명 (8/12) MyBatis 를활용한자바클래스작성 1 EgovAbstractMapper 클래스를상속받아 DAO 클래스를작성 DAO class 샘플코드 @Repository("empMapper") public class EmpMapper extends EgovAbstractMapper { public void insertemp(empvo vo) { insert("insertemp", vo); } EgovAbstractMapper 는 SqlSessionDaoSupport 의하위클래스로, SqlSession 설정과메소드호출의편리함을제공한다 public int updateemp(empvo vo) { return update("updateemp", vo); } public int deleteemp(empvo vo) { return delete("deleteemp", vo); } SQL Mapper XML 내에정의한각 Statement id 를이용하여실행할 SQL 문을호출하도록작성한다 public EmpVO selectemp(empvo vo) { return (EmpVO) selectbypk("selectemp", vo); } } public List<EmpVO> selectemplist(empvo searchvo) { return list("selectemplist", searchvo); } 51 Page l 51

3. Data Access MyBatis 설명 (9/12) MyBatis를활용한자바클래스작성 2 DAO 클래스대신 Interface 작성 (Mapper Interface 방식 ) (1/4) 기존 DAO 클래스의 MyBatis 메서드호출코드를최소화시킨방법으로, 각 Statement id와메서드명을동일하게작성하면 MyBatis가자동으로 SQL문을호출한다. 실제내부적으로 MyBatis는풀네임을포함한메서드명을 Statement id로사용한다. package x.y.z.mapper; Mapper Interface 샘플코드 @Mapper("deptMapper") public interface DeptMapper { Mapper Interface 를자동스캔하기위한기능으로, MapperConfigurer 빈설정과함께사용한다 public void insertdept(deptvo vo); public int updatedept(deptvo vo); public int deletedept(deptvo vo); public DeptVO selectdept(deptvo vo); Serive 클래스에서메소드를호출하면, 메서드명과일치하는 SQL 문을자동실행한다 } public List<DeptVO> selectdeptlist(deptvo vo); 52 Page l 52

3. Data Access MyBatis 설명 (10/12) MyBatis를활용한자바클래스작성 2 DAO 클래스대신 Interface 작성 (Mapper Interface 방식 ) (2/4) 이때 SQL Mapper XML 파일의 namespace값을해당 Mapper의풀네임으로설정해야한다. MyBatis는해당 Mapper의풀네임과일치하는 namespace에서메서드명과동일한 id를가진 Statement를호출한다. namespace : 각 SQL Mapper XML을구분 SQL Mapper XML 설정 1 <mapper namespace= x.y.z.mapper.deptmapper"> <insert id="insertdept" parametertype="deptvo"> </insert> <update id="updatedept" parametertype="deptvo"> </update> <delete id="deletedept" parametertype="deptvo"> </delete> <select id="selectdept" parametertype="deptvo" resultmap="deptresult"> </select> <select id="selectdeptlist" parametertype="deptvo" resultmap="deptresult"> </select> </mapper> SQL Mapper XML 설정 2 <mapper namespace= x.y.z.mapper.empmapper"> <insert id="insertemp" parametertype= empvo"> </insert> <update id="updateemp" parametertype="empvo > </update> <delete id="deleteemp" parametertype="empvo > </delete> <select id="selectemp" parametertype="empvo" resultmap= empresult"> </select> <select id="selectemplist" parametertype="empvo" resultmap= empresult"> </select> </mapper> 53 Page l 53

3. Data Access MyBatis 설명 (11/12) MyBatis를활용한자바클래스작성 2 DAO 클래스대신 Interface 작성 (Mapper Interface 방식 ) (3/4) @Mapper를사용하여 Mapper Interface가동작하도록하려면, MapperConfigurer 클래스를빈으로등록한다. MapperConfigurer는 @Mapper를자동스캔하고, MyBatis 설정의편리함을제공한다. basepackage : 스캔대상에포함시킬 Mapper Interface가속한패키지를지정 MapperConfigurer 설정 <!-- MapperConfigurer setup for MyBatis Database Layer --> <bean class="egovframework.rte.psl.dataaccess.mapper.mapperconfigurer"> <property name="basepackage" value= x.y.z.mapper" /> </bean> 54 Page l 54

3. Data Access MyBatis 설명 (12/12) MyBatis를활용한자바클래스작성 2 DAO 클래스대신 Interface 작성 (Mapper Interface 방식 ) (4/4) 어노테이션을이용한 SQL문작성 인터페이스메소드위에 @Statement(Select, Insert, Update, Delete ) 를선언하여쿼리를작성한다. SQL Mapper XML을작성할필요가없으나, Dynamic 쿼리를사용하지못하고쿼리의유연성이떨어진다. @Mapper("deptMapper") public interface DeptMapper { Mapper Interface 샘플코드 @Select("select DEPT_NO as deptno, DEPT_NAME as deptname, LOC as loc from DEPT where DEPT_NO = #{deptno}") public DeptVO selectdept(bigdecimal deptno); @Insert("insert into DEPT(DEPT_NO, DEPT_NAME, LOC) values (#{deptno}, #{deptname}, #{loc})") public void insertdept(deptvo vo); @Update("update DEPT set DEPT_NAME = #{deptname}, LOC = #{loc} WHERE DEPT_NO = #{deptno}") public int updatedept(deptvo vo); @Delete("delete from DEPT WHERE DEPT_NO = #{deptno}") public int deletedept(bigdecimal deptno); } 55 Page l 55

3. Data Access - 참고자료 ibatis http://ibatis.apache.org ibatis-sqlmaps-2 Developer Guide http://svn.apache.org/repos/asf/ibatis/trunk/java/ibatis-2/ibatis-2-docs/en/ibatis-sqlmaps- 2_en.pdf ibatis-sqlmaps-2 개발자가이드 http://kldp.net/frs/download.php/5035/ibatis-sqlmaps-2_ko.pdf Spring Framework - Reference Documentation http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/htmlsingle/#orm-ibatis MyBatis 개발자가이드 http://mybatis.github.io/mybatis-3/ 56 Page l 56

4. Transaction 개요 서비스개요 트랜잭션서비스는 Spring 트랜잭션서비스를채택 트랜잭션서비스종류ㆍ DataSource Transaction Service ㆍ JTA Transaction Service ㆍ JPA Transaction Service에대해서설명한다. 트랜잭션활용방법ㆍ XML 설정및 Annotation을통해활용할수있는 Declaration Transaction Management ㆍ프로그램에서직접 API를호출하여쓸수있도록하는 Programmatic Transaction Management 57 Page l 57

4. Transaction 설명 (1/12) Transaction Service DataSource Transaction Service DataSource 를사용하여 Local Transaction 을관리할수있다. Configuration <bean id="transactionmanager" class="org.springframework.jdbc.datasource.datasourcetransactionmanager"> <property name="datasource" ref="datasource" /> </bean> <bean id="datasource" class="org.apache.commons.dbcp.basicdatasource destroy-method="close"> <property name="driverclassname" value="com.mysql.jdbc.driver" /> <property name="url" value="dbc:mysql://db2:1621/rte" /> <property name="username" value="rte" /> 사용자명 <property name="password" value="xxx" /> 암호 <property name="defaultautocommit" value="false" /> </bean> 자동 commit 설정 Jdbc driver database url 58 Page l 58

4. Transaction 설명 (2/12) Sample Source @Resource(name="transactionManager") PlatformTransactionManager transactionmanager;... TransactionStatus txstatus = transactionmanager.gettransaction(txdefinition); 59 Page l 59

4. Transaction 설명 (3/12) JTA Transaction Service JTA 를이용하여 Global Transation 관리를할수있도록지원한다. Configuration <tx:jta-transaction-manager /> <jee:jndi-lookup id="datasource" jndi-name="dbmsxads" resource-ref="true"> <jee:environment> java.naming.factory.initial=weblogic.jndi.wlinitialcontextfactory java.naming.provider.url=t3://was:7002 </jee:environment> </jee:jndi-lookup> 위의설정예에서 jndi-name 과 java.naming.factory.initial,java.naming.provider.url 은사이트환경에맞추어변경해야한다. DataSource Transaction Service 와는달리 transationmanager 에대해서따로 bean 정의하지않아도된다. 60 Page l 60

4. Transaction 설명 (4/12) JPA Transaction Service JPA Transaction 서비스는 JPA EntityManagerFactory 를이용하여트랜잭션을관리한다. JpaTransactionManager 는 EntityManagerFactory 에의존성을가지고있으므로반드시 EntityManagerFactory 설정과함께정의되어야한다. 아래에서예를들어서설정방법을설명한다. 사용법은 DataSource Transaction Service 와동일하다. Configuration <bean id="transactionmanager" class="org.springframework.orm.jpa.jpatransactionmanager"> <property name="entitymanagerfactory" ref="entitymanagerfactory" /> </bean> <bean id="entitymanagerfactory" class="org.springframework.orm.jpa.localcontainerentitymanagerfactorybean"> <property name="persistenceunitname" value="oraunit" /> <property name="persistencexmllocation" value="classpath:meta-inf/persistence.xml" /> <property name="datasource" ref="datasource" /> </bean> <bean id="datasource" class="org.apache.commons.dbcp.basicdatasource" destroy-method="close"> <property name="driverclassname" value="com.mysql.jdbc.driver" /> <property name="url" value="dbc:mysql://db2:1621/rte" /> <property name="username" value="rte" /> <property name="password" value="xxx" /> <property name="defaultautocommit" value="false" /> </bean> 위의설정을보면 transactionmanager 의 property 로 entiymanagerfactory 로지정하고 entitymanagerfactory 의 property 로 datasource 를지정하고그에필요한 driver 정보,Url 정보등을지정한것을확인할수있다. 설정한 datasource 기반하에서트랜잭션서비스를제공한다. 사이트환경에맞추어 driverclassname,url,username,password 는변경해서적용한다. 또한 persistenceunitname 과 persistencexmllocation 정보를지정하는것을알수있다 61 Page l 61

4. Transaction 설명 (5/12) Declarative Transaction Management 코드에서직접적으로 Transaction 처리하지않고, 선언적으로 Transaction을관리할수있다. Annotation을이용한 Transaction 관리, XML 정의를이용한 Transaction 관리를지원한다. Configuration <tx:annotation-driven transaction-manager="transactionmanager" /> transactionmanager 선언 Sample Source @Transactional public void removerole(role role) throws Exception { this.roledao.removerole(role); } 트랙잭션처리하고자하는메소드위에기재하여트랜잭션관리 62 Page l 62

4. Transaction 설명 (6/12) Configuration Transaction Management XML 정의설정을이용해서 Transaction 을관리할수있다. Configuration <aop:config> <aop:pointcut id="requiredtx" expression="execution(* egovframework.sample..impl.*impl.*(..))" /> <aop:advisor advice-ref="txadvice" pointcut-ref="requiredtx" /> </aop:config> <tx:advice id="txadvice" transaction-manager="transactionmanager"> <tx:attributes> <tx:method name="find*" read-only="true" /> <tx:method name="createnorbrole" no-rollback-for="norolebacktx" /> <tx:method name="createrbrole" rollback-for="rolebacktx" /> <tx:method name="create*" /> </tx:attributes> </tx:advice> aop:pointcut 를이용하여실행되어 Catch 해야하는 Method 를지정하고 tx:advice 를통해서각각에대한룰을정의하고있다. 이렇게정의하면프로그램내에서는별도의트랜잭션관련한사항에대해기술하지않아도트랜잭션관리가된다. 63 Page l 63

4. Transaction 설명 (7/12) <tx:method> 상세속성정보 속성설명사용예 name 메소드명기술. 와일드카드사용가능함 Name= find* isolation Transaction 의 isolation Level 정의하는요소 Isolation= DEFAULT no-rollback-for 정의된 Exception 목록에대해서는 rollback을수행하지않음 No-rollbackfor= NoRolBackTx propagation Transaction 의 propagation 유형을정의하기위한요소 propagation= REQUIRED read-only 해당 Transaction 을읽기전용모드로처리 (Default=false) read-only= true rollback-for 정의된 Exception 목록에대해서는 rollback 수행 rollback-for=rolebacktx timeout 지정한시간내에해당메소드수행이완료되지않은경우 rollback 수행. timeout= 10 64 Page l 64

4. Transaction 설명 (8/12) Propagation Behavior,Isolation Level( 두가지 Transaction Management 공통적으로사용되는항목 ) Propagation Behavior Isolation Level 65 Page l 65

4. Transaction 설명 (9/12) Programmatic Transaction Management 프로그램에서직접트랜잭션을관리하고자할때사용할수있는방법에대해서설명하고자한다. TransactionTemplate 를사용하는방법과 TransactionManager 를사용하는방법두가지가있다. TransactionTemplate Configuration <bean id="transactiontemplate" class="org.springframework.transaction.support.transactiontemplate"> <property name="transactionmanager" ref="transactionmanager" /> </bean> <bean id="transactionmanager" class="org.springframework.jdbc.datasource.datasourcetransactionmanager"> <property name="datasource" ref="datasource" /> </bean> TransactionTemplate 를정의하고 property 로 transactionmanager 을정의한다. 66 Page l 66

4. Transaction 설명 (10/12) TransactionTemplate 를이용한 Sample Source @Test public void testinsertcommit() throws Exception { transactiontemplate.execute(new TransactionCallbackWithoutResult() { public void dointransactionwithoutresult(transactionstatus status) { try { Role role = new Role(); } role.setroleid("role-001"); role.setrolename("role-001"); role.setroledesc(new Integer(1000)); roleservice.createrole(role); } catch (Exception e) { status.setrollbackonly(); } transactiontemplate.execute 에 TransactionCallbackWithoutResult 를정의하여 Transaction 관리를하는것을확인할수있다. } }); Role retrole = roleservice.findrole("role-001"); assertequals("rolename Compare OK",retRole.getRoleName(),"ROLE-001"); 67 Page l 67

4. Transaction 설명 (11/12) Transaction Manager Configuration <bean id="transactionmanager" class="org.springframework.jdbc.datasource.datasourcetransactionmanager"> <property name="datasource" ref="datasource" /> </bean> 68 Page l 68

4. Transaction 설명 (12/12) Transaction Manager 를이용한 Sample Source @Test public void testinsertrollback() throws Exception { int prevcommitcount = roleservice.getcommitcount(); int prevrollbackcount = roleservice.getrollbackcount(); DefaultTransactionDefinition txdefinition = new DefaultTransactionDefinition(); txdefinition.setpropagationbehavior(transactiondefinition.propagation_required); TransactionStatus txstatus = transactionmanager.gettransaction(txdefinition); try { Role role = new Role(); role.setroleid(thread.currentthread().getname() + "-roleid"); role.setrolename(thread.currentthread().getname() + "-rolename"); role.setroledesc(new Integer(1000)); roleservice.createrole(role); roleservice.createrole(role); transactionmanager.commit(txstatus); } catch (Exception e) { transactionmanager.rollback(txstatus); } finally { assertequals(prevcommitcount, roleservice.getcommitcount()); assertequals(prevrollbackcount + 2, roleservice.getrollbackcount()); } } Transaction 서비스를직접얻어온후에위와같이 try~catch 구문내에서 Transaction 서비스를이용하여, 적절히 begin, commit, rollback 을수행한다. 이때, TransactionDefinition 와 TransactionStatus 객체를적절히이용하면된다. 69 Page l 69

4. Transaction 참고자료 Spring Transaction Management http://docs.spring.io/spring/docs/4.0.x/spring-framework-reference/html/transaction.html 이전버전참조 http://static.springsource.org/spring/docs/2.5.x/reference/transaction.html http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/transaction.html 70 Page l 70

71 Page l 71