티스토리 뷰
iBatis 사용시 XML상의 reference 관련 error시
이클립스에서 느낌표가 나오면 왠지 모르게 짜증이 난다
[기존]
- <!DOCTYPE sqlMapConfig PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
"http://www.ibatis.com/dtd/sql-map-config-2.dtd">
[수정]
- <!DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
주소가 수정되었나보다. 브라우저에서 주소창에 치면 이전 것도 다운로드 되는데 이클립스에서는 왜 안되지?
다른 sql-map, dao도 올려놓자
- <!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">
<!DOCTYPE dao PUBLIC "-//ibatis.apache.org//DTD DAO Configuration 2.0//EN" "http://ibatis.apache.org/dtd/dao-2.dtd">
아놔~ 그 문제인줄 알았는데,
회사에서는 외부 인터넷에 연결하기 위해서 프록시 서버를 연결해야 하는데 이클립스에 세팅을 해줘야 하기 때문이었다.
네트워크 연결이 안되니 dtd 파일을 다운받을 수 없고 xml validation도 할 수 없는 것이 었다.
iBATIS in Action
(쉽고 강력한 SQL 매핑 프레임워크 아이바티스)
위 책의 필요한 사전 배경지식: Java, JDBC(매핑+), SQL, XML
외부 링크 : 아이바티스 커뮤니티(http://ibatis.apache.org)
SVN : Subversion Source Control
JIRA: for 이슈 트래킹(아틀라시안)
Confluence : wiki 문서 작성
소스 코드 : 매닝 출판사 웹 사이트(www.manning.com/begin)
위키북스 오픈소스 & 웹 시리즈 에디터 일래스틱 온라인(http://web2.0business.or.kr/)
-
머리말
- 프레임워크 - 사전적 의미(뼈대, 틀, 골자)
- 향상 : 가독성, 유지보수성, 생산성
-
퍼시스턴스 계층에 적용할 프레임워크
- 아이바티스 - JDBC
- 객체 관계 매핑 툴(ORM) - 하이버네이트 / TopLink
-
iBATIS : 더 빠른 JDBC 코딩을 위한 일반화된 프레임워크
- SQL 매퍼 + DAO 프레임워크
요약 (iBATIS)
- SQL 매핑으로 객체를 관계형 데이터베이스에 저장
- 애플리케이션이 퍼시스턴스 계층에 일관성있게 접근하는 것을 도와줌
- 전사적인 수준의 퍼스스턴스 계층에 보다 적함(소규모 시스템에 비교하여)
-
특징
- 간단함 - 간단한 퍼시스턴스 프레임워크
- 생산성 - 62%정도 줄어드는 코드(JDBC와 비교하여), 간단한 설정(근거: 이탈리안 자바 사용자 그룹의 연구)
-
성능 - 구조적 강점(데이터 접근 속도 높여주는 JOIN매핑)
- 여러가지 방식의 데이터 가져오기 전략(가져오기 미루기, SQL 줄이기 기법)
-
관심사의 분리 - 설계를 향상(차후 유지보수성 위해)
- 리소스를 관리하여 계층화를 지원(커넥션, PreparedStatement, 결과셋)
-
작업의 분배 - 팀을 세분화하는 것을 도움
- SQL 문이 애플리케이션 소스 코드로부터 완전히 분리
-
이식성 - 어떤 프로그래밍언어로도 구현 가능
- 예) 자바, C#(iBATIS.NET), Ruby(RBATIS)
- 오픈소스 - 무료+ 커뮤니티티
-
언제 사용하지 말아야 하나?
-
개발자가 모든 것에 대해 영원한 결정권 소유
- 애플리케이션 설계와 데이터베이스 설계에 대한 모든 결정권 보유
- iBATIS는 관계형 데이터베이스를 위해 설계
- => 관계 매핑 솔루션(ORM;하이버네이트..) 사용 - 설계시 이점, 생산성 향상
예) JIRA(이슈 트래킹 패키지 소프트웨어 제품)
-
완전히 동적인 SQL을 요구시
- 애플리케이션의 핵심 기능 : SQL을 동적으로 생성일 경우
- iBATIS의 사용이유: 수작업 SQL 구문 작성, 관리
- 애플리케이션 -> 대부분의 SQL 구문이 SQL 자동 생성 클래스 로부터 동적으로 생성시 위의 장점은 무의미
-
비 관계형 데이터베이스 사용
- 파일, 엑셀, XML
- => 순수한 JDBC, 저수준 파일 입출력 API 권장장
- 요구사항과 상반되는 개발 방향, 설계지침 - 복잡도 증가, 프레임워크 자체의 역할 범위 넘어서는 것
-
-
(주로)관계형 데이터베이스를 위해 설계
- 비-관계형 기술(일반적 파일, XML, 엑셀 스프레드 시트)사용시 타 API 이용이 효과적
- 객체 관계 매퍼(ORM) - 애플리케이션~데이터베이스에 대한 결정권 보유
- JDBC - 주로 동적으로 생성되는 SQL 코드로 작업하는 애플리케이션
x설치와 설정 (iBATIS)
-
배포판 얻기
-
바이너리 배포판: 가장 빠르고 쉬운 방법
- 컴파일된 상태 -> 다운받아 압축을 풀고 사용
-
소스로부터 빌드하기
- 프레임워크를 확장, 버그 수정
- 소스코드를 직접 컴파일 결과 확인시
-
배포판의 구조
- 2.3.0.677에서는 jar 파일들(/lib 디렉토리내)가 ibatis-2.3.0.677.jar로 하나로 통합되었다.
-
/doc
- user-javadoc.zip : for iBATIS 프레임워크를 사용해서 개발을 하는 사용자들
- dev-javadoc.zip : for iBATIS 프로젝트의 모든 JavaDoc 문서를 포함하고 있는 파일
-
/lib
- ibatis-common-2.jar : SQL Maps와 DAO 프레임워크 모두가 사용하는 공통 컴포넌트 포함
- ibatis-sqlmap-2.jar : SQL Maps 프레임워크의 컴포넌트들을 포함하고 있는 파일
- ibatis-dao-2.jar : DAO 프레임워크 컴포넌트들을 포함하고 있는 파일
-
/src
- ibatis-src.zip : 프레임워크의 JAR파일을 빌드하는데 사용된 전체 소스를 포함하고 있는 파일
-
-
애플리케이션에 iBATIS 붙이기
-
클래스패스 추가(iBATIS 파일 경로 컴파일시, 실행시)
-
단독 실행 애플리케이션
-
클래스패스 옵션 추가
- java -cp ibatis-sqlmap-2.jar:ibatis-common-2.jar:. MyMainClass
-
-
웹 애플리케이션
- iBATIS의 jar 파일들을 WEB-INF/lib 디렉토리에 둔다
-
-
JRE 공유 디렉토리(lib/ext 디렉토리)에 올려서 사용가능하지만 가급적 피할 것
- 애플리케이션 변경되어 파일 수정시 공유하고 잇는 파일을 참조하는 모든 애플리케이션을 테스트 필요
- 클래스로더 문제((두 개의 서로 다른 클래스로더가 읽으면 서로 다른 클래스로 간주: 정적변수 공유 X)
-
-
SQL Maps 설정 파일
-
<SqlMapConfig.xml>
- <!SqlMapConfig.xml SQL Map configuration file-->
<?xml version="1.0" encoding="UTF-8"?>
<!-- 유효성 체크를 위한 DOCTYPE과 DTD를 적는다 -->
<!DOCTYPE sql-map-config
PUBLIC "-//iBATIS.com//DTD SQL Map Config 1.0//EN"
"http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
<sql-map-config>
<properties resource="db.properties" />
<!-- 전체 설정 옵션 -->
<settings
useStatementNamespaces='false'
cacheModelsEnabled='true'
enhancementEnabled='true'
lazyLoadingEnabled='true'
maxRequests="32"
maxSessions="10"
maxTransactions="5"
/>
<!-- 트랜잭션 매니저 -->
<transactionManager type="JDBC" >
<dataSource type="SIMPLE">
<property name="JDBC.Driver" value="${driver}"/>
<property name="JDBC.ConnectionURL" value="${url}"/>
<property name="JDBC.Username" value="${user}"/>
<property name="JDBC.Password" value="${pword}"/>
</dataSource>
</transactionManager>
<!-- SQL Map을 기술 -->
<sql-map resource="sqlMap.xml" />
</sql-map-config>
- <!SqlMapConfig.xml SQL Map configuration file-->
-
<properties> 요소 - 외부에서 이름/값 쌍의 리스트를 제공
- 장점 : 공통 설정 부분은 모두 한 곳에 두고 각 환경별로 다른 값들을 properties 파일에 독립 가능
-
속성
-
resource - 클래스 패스상에 있는 리소스(or 파일)
- 클래스 로더가 애플리케이션의 클래스패스에서 그 리소스를 찾으려는 시도 함
-
소스(db.properties)
-
driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:orcl
user=scott
pword=tiger
-
- url - URL, java.net.URL에 의해 처리
-
-
<setting> 요소
- useStatementNamespaces - 매핑 구문이 적절한 이름을 가지고 있어야 iBATIS가 실행 가능하도록 하는 옵션, 값(true/false)
- cacheModelsEnabled - 캐시(차후 참조 가정->메모리 계속 저장), 값(true/false)
- enhancementEnabled - CGLIB(실행 시간에 코드를 생성하는 라이브러리)에 최적화된 클래스-> 적재 지연 성능 향상 여부 지정, 값(true/false)
- lazyLoadingEnabled - 적재 지연(필요할 때만 정보를 읽어들이는 기술), 값(true/false)
- maxRequests - SQL작업(입력/수정/삭제/저장 프로시저 호출)의 한번에 수행가능한 개수, 기본값: 512
- maxSessions - 세션(스레드, 관련되어 있는 트랜잭션과 요청의 묶음에 대한 정보 추적 사용), 기본값: 128
- maxTransactions - 데이터 트랜잭션의 개수, 기본값: 32
-
<typeAlias> 요소 - FQCN(완전한 형태의 클래스 이름, Fully Qualified Class Name) 대신 별칭을 붙임
-
예)
- <typeAlias alias="Account"
type="org.apache.ibatis.jgamestore.domain.Account" />
- <typeAlias alias="Account"
-
기본 내장 별칭들
-
트랜잭션 매니저의 별칭
- JDBC <- com.ibatis.sqlmap.engine.transaction.jdbc.JdbcTransactionConfig
- JTA <- com.ibatis.sqlmap.engine.transaction.jta.JtaTransactionConfig
- EXTERNAL <- com.ibatis.sqlmap.engine.transaction.external.ExternalTransactionConfig
-
데이터 타입
- string <- java.lang.String
- byte <- java.lang.Byte
- long <- java.lang.Long
- short <- java.lang.Short
- int <- java.lang.Integer
- integer <- java.lang.Integer
- double <- java.lang.Double
- float <- java.lang.Float
- boolean <- java.lang.Boolean
- decimal <- java.math.BigDecimal
- object <- java.lang.Object
- map <- java.util.Map
- hashmap <- java.util.HashMap
- list <- java.util.List
- arraylist <- java.util.ArrayList
- collection <- java.util.Collection
- iterator <- java.util.Iterator
-
데이터 소스 팩토리 타입
- SIMPLE <- com.ibatis.sqlmap.engine.datasource.SimpleDataSourceFactory
- DBCP <- com.ibatis.sqlmap.engine.datasource.DbcpDataSourceFactory
- JNDI <- com.ibatis.sqlmap.engine.datasource.JndiDataSourceFactory
-
캐시 컨트롤러 타입
- FIFO <- com.ibatis.sqlmap.engine.cache.fifo.FifoCacheController
- LRU <- com.ibatis.sqlmap.engine.cache.Iru.LruCacheController
- MEMORY <- com.ibatis.sqlmap.engine.cache.memory.MemoryCacheController
- OSCACHE <- com.ibatis.sqlmap.engine.cache.OSCacheController
-
XML 결과 타입
- Dom <- com.ibatis.sqlmap.engine.type.DomTypeMarker
- domCollection <- com.ibatis.sqlmap.engine.type.DomCollectionTypeMarker
- Xml <- com.ibatis.sqlmap.engine.type.XmlTypeMarker
- XmlCollection <- com.ibatis.sqlmap.engine.type.XmlCollectionTypeMarker
-
-
-
<transactionManager> 요소
-
type - 어떤 트랜잭션 관리자르 사용할지 결정
- JDBC : 간단한 JDBC 기반 트랜잭션 관리 기능 제공
- JTA : 컨테이너 기반한 트랜잭션 관리 기능 제공
- EXTERNAL : 트랜잭션 관리자를 제공하지 않고 iBATIS 대신 애플리케이션이 직접 트랜잭션을 관리한다고 가정
- commitRequired - 커넥션을 닫기 전에 commit/rollback 제어시, 기본값: false
- <property> 요소 - 각 트랜잭션 관리자 서로 다른 설정 옵션 가능
- <dataSource> 요소 - javax.sql.DataSource 객체를 사용 -> 커넥션 풀 작업을 표준화
-
type 속성 - 어떤 클래스의 객체를 생성해서 데이터 소스 팩토리를 얻어올지를 정하는 속성
- SIMPLE - 간단한 커넥션 풀을 내장한 데이터 소스를 설정하고자 할 때(JDBC 드라이버만 빼고 데이터 소스에 필요한 모든 것을 자체 내장)
- DBCLP - Jakarta Commons Database Connection Pool 구현을 제공
- JNDI - JNDI(Java Naming and Directory Interface)를 통해 할당된 컨테이너 기반의 데이터 소스를 공유하도록 사용
-
<typeHandler>
- 타입 핸들러 이용: JDBC 데이터베이스 전용 데이터형 -> 애플리케이션의 데이터형 변환(번역기)
-
-
<sqlMap> 요소
- resource - SQL Map 파일을 자바 클래스패스에 두고 리소스로서 참조
- url - java.net.URL 클래스가 인식하는 임의의 URL 값 이용
-
-
SQL Map API
-
SqlMapClient 인터페이스
-
queryForObject() - 데이터베이스로부터 한 개의 레코드를 가져다가 자바 객체에 저장
-
Object queryForObject(String id, Object parameter) throws SQLException;
- 디폴트 생성자를 가진 객체를 생성(보편적 방법)
- 디폴트 생성자가 없으면 throws "런타임 예외"
-
Object queryForObject(String id, Object parameter, Object result) throws SQLException;
- 반환하는 값으로 사용될 객체를 받음
- 결과값 -> 파라미터의 형태로 객체에 지정
- 생성자가 protected / 디폴트 생성자가 없어서 객체를 쉽게 생성할 수 없을 때 유용
-
-
queryForList() - 한 개 이상의 레코드를 가져와서 자바 객체의 List를 만드는 데 사용
-
List queryForList(String id, Object parameter) throws SQLException;
- 매핑 구문이 반환하는 모든 객체를 반환
-
List queryForList(String id, Object parameter, int skip, int max) throws SQLException;
- 전체 결과의 일부만을 반환
- skip : 지정된 개수만큼 건너뛰고
- max : 지정된 개수의 레코드만 반환
- 2.3버전부터 비권장
-
-
queryForMap() - 데이터베이스로부터 한 개 혹은 그 이상의 레코드를 가져올 때 자바 객체의 Map을 반환
-
Map queryForMap(String id, Object parameter, String key) throws SQLException;
- 퀴리 실행후 Map 객체를 생성하여 반환
-
key : 결과 객체를 가리키는 키, -> 지정된 프로퍼티의 값
-
Map accountMap = sqlMap.queryForMap(
"Account.getAll", null, "accountId");
System.out.println(accountMap);
-
-
Map queryForMap(String id, Object parameter, String key, String value) throws SQLException;
-
결과값 객체 -> value 파라미터에 지정된 프로퍼티 값이 됨
-
accountMap = sqlMap.queryForMap(
"Account.getAll", null, "accountId", "username");
System.out.println(accountMap);
-
-
-
-
-
-
non-query 구문
-
데이터 갱신
-
insert 메소드
-
Object inser(String id, Object parameterObject) throws SQLException;
- 파라미터 : 실행할 매핑 구문의 이름, 파라미터 객체(데이터베이스에 데이터 삽입하는 데 사용)
- 반환 : 객체
-
-
update 메소드
-
int update(String id, Object parameterObject) throws SQLException;
- 파라미터: 실행할 매핑 구문의 이름, 값을 제공하는 데 사용할 파라미터 객체
- 반환: update 구문에 의해 영향을 받은 레코드의 개수
-
-
delete 메소드
-
int delete(String id, Object parameterObject) throws SQLException;
- 파라미터: 실행할 매핑 구문의 이름, 값을 제공하는 데 사용할 파라미터 객체
- 반환: 삭제된 레코드의 개수
-
-
-
매핑 구문
-
<insert> | id, parameterClass, parameterMap
- <parameterMap id="fullParameterMapExample" class="Account">
<parameter property="accountId" jdbcType="NUMBER" />
<parameter property="username" jdbcType="VARCHAR" />
...
</parameterMap>
<insert id="insertWithExternalInfo"
parameterMap="fullParameterMapExample">
insert into account (
account Id,
username, ...
) values (
?, ? , ...
)
</insert> -
in Java 사용
sqlMap.insert("Account.insertWithExternalInfo", account);
- <parameterMap id="fullParameterMapExample" class="Account">
- <update> | id, parameterClass, parameterMap
- <delete> | id, parameterClass, parameterMap
- <procedure> | id, parameterClass, resultClass, parameterMap, resultMap, xmlResultName
-
<sql> | id
- 매핑 구문은 아니지만, 매핑 구문 내에서 사용될 수 있는 컴포넌트를 만들기 위해
-
<include> | refid
- 매핑 구문은 아니지만, 매핑 구문에 <sql>타입으로 생성된 컴포넌트를 삽입하기 위해
-
-
-
iBATIS에서 XML 사용
-
XML 파라미터
- <select id="getByXmlId" resultClass="Account" parameterClass="xml">
...
- <select id="getByXmlId" resultClass="Account" parameterClass="xml">
-
XML로 결과 생성
- <select id="getByValueXml" resultClass=""xml" xmlResultName="account">
...
- <select id="getByValueXml" resultClass=""xml" xmlResultName="account">
-
MVC 모델
-
비지니스 객체 모델(도메인 클래스) : 처리할 도메인을 객체 지향적으로 묘사
- 특정 비지니스 로직의 기능을 수행하기 위해 사용
- 명사 -> 이름 -> 클래스
- 약간의 로직 포함 가능(다른 계층에 접근하는 코드 금지)
- 퍼시스턴스 계층의 메소드들의 파라미터의 반환값
-
프리젠테이션 계층 : 출력(애플리케이션의 데이터/제어화면)하는 역할
- 모든 정보의 레이아웃, 출력 형식을 정의
- 예. HTML + JavaScript
-
웹 애플리케이션
- 장점: 플래폼에 독립적, 배포와 확장이 쉬움
-
단점: 높은 수준의 사용자 제어 방식, 복잡한 데이터 처리 어려움
- => 운영 시스템 위젯 사용하는 리치 클라이언트 방식(탭, 표, 트리, 내장 객체)
-
리치 클라이언트 방식
- 장점: 강력한 사용자 인터페이스
- 단점: 배포의 어려움, 성능, 보안에 손이감
- 예> Swing(자바), WinForms(.NET)
-
복합적 리치 클라이언트(웹 애플리케이션 + 리치 클라이언트 방식)
- 웹 서비스 <= 겉 모양, 비지니스 기능
- XML <= 리치 클라이언트와 서버 간의 매개체
-
단점: 애플리케이션의 개발과 배치에 더 많은 소프트웨어 필요
- 예) Flex(매크로미디어), Flash 브라우저 플러그인(Laszlo시스템), Ajax(Asynchoronous JavaScript And XML)
-
비지니스 로직 계층(서비스 클래스) - 애플리케이션이 제공하는 포괄적인 서비스들을 표현
- 큰 덩어리 비지니스 기능을 관련된 비지니스 객체 모델에서 분리
- 명사-동사 분리(예. 계좌(도메인) 메소드 분리 -> 은행서비스(비지니스 로직-계좌를 개설하다)
- 서비스를 열어준다는 것은 클래스의 메소드를 사용할 수 있게 권한을 부여한다는 의미가 될 수 있음
-
퍼시스턴스 계층 - 객체에 저장된 데이터(저장소, 객체 가져오기)
- 데이터 저장 방식은 다양(관계형 데이터베이스 스스템, 쉼표로 분리된 텍스트, XML 등)
- 추상화 필요 - 세부사항(데이터가 어떻게 저장/전송) 숨김
-
내부 계층
-
추상 계층 : 퍼스스턴스 계층에 일관성 있고 의미 있는 인터페이스 제공
- 클래스와 메소드의 집합
- 세부 구현 사항은 감싸서 꾸며줌
- 적절히 추상 계층 구현을 도와주는 패턴 존재 : 예) 데이터 접근 객체(DAO;Data Access Object)
-
퍼시스턴스 프레임워크 : 드라이버(or 인터페이스)와 소통하는 책임
- 데이터 저장/가져옴/수정/검색/관리 메소드들 제공
- 기반 저장소 클래스에 종속적
-
표준API - 반복적이고 부차적인 코드가 필요
- JDBC(자바 애플리케이션 -데이터베이스에 접근~표준 프레임워크)
- ADO.NET(.NET 애플리케이션을 위한 표준 데이터베이스 퍼시스턴스 프레임워크)
-
드라이버 / 인터페이스
- 기반 저장소는 종류 다양(구현, 규모, 행동 상이) -> 소프트웨어 드라이버 사용
- 드라이버와 통신하여 차이점들을 최소화 간소화하는 역할
-
데이터베이스
-
관계형 데이터베이스의 사용 이유? - 무결성, 성능, 보안
-
무결성 - 데이터의 일관성, 신뢰, 값의 정확성 보장
-
VARCHAR(25) NOT NULL
- 데이터 타입 엄격히 준수 - 예) 값이 문자열 데이터, 길이가 25이하
- 제약조건 엄수 - 예) UNIQUE
- 트랜잭션 사용 - 연관(관련)된 데이터들의 일관성 있는 수정 방식(여러 사용자)
-
-
성능 - 설계, 소프트웨어 튜닝, 하드웨어
- 설계: 최고 중요!!!
- 튜닝 고려사항: 캐시, 파일 관리자, 인덱스 알고리즘, 운영체제 등
- 하드웨어 고려사항: 고속 디스크 어레이, 고속I/O 컨트롤러, 고속 하드웨어 캐시, 네트워크 인터페이스
- 보안 - 기밀 데이터 유지
-
-
데이터베이스 형태(4가지)
-
애플리케이션 데이터베이스 - 작고 단순한 형태, 외부 영향 적음
- 해당 프로젝트의 일보로 애플리케이션과 나란히 설계/구현
- 예) 웹 애프리케이션 -> 데이터베이스(MySQL,PostgreSQL) -> 리포팅 툴(크리스탈 리포트)
-
기업용 데이터베이스 - 큰 규모, 외부의 영향 큼
- 통합 데이터베이스 - 트랜잭션처리 데이터베이스 - 리포팅 데이터베이스
- 독점적 데이터베이스 - 직접 제작 vs 구입(패키지 소프트웨어)
-
레거시 데이터베이스 - 오래된 데이터베이스(보잡성, 뒤죽박죽 설계, 의존성. age)
- 수년간에 걸친 수정, 긴급한 수리 작업, 오류 은폐작업, 오류 피해가기, 땜질식 문제 해결, 기술적 제약 극복 패치..
-
iBATIS
-
iBATIS - 데이터 매퍼
-
매퍼계층: 객체와 데이터베이스 그리고 매퍼 자체를 독립적으로 유지 + 객체와 데이터베이스 간에 데이터를 이동
- SQL 구문의 파라미터와 결과(입력/출력)를 클래스에 매핑
-
매핑방법
-
SQL 구문 - 입력과 출력으로 구분
-
예) 입력 first_name, last_name / 출력 1234
- select first_name, last_name
from employee
where employee_number=1234;
- select first_name, last_name
-
XML 서술 파일 : SQL 구문의 입력과 출력을 매핑
- <select id="getAddress" parameterClass="int" resultClass="Address">
- select
- ADR_ID as id,
- ADR_DESCRIPTION as description,
- ADR_STREET as street,
- ADR_CITY as city
- from address
- where ADR_ID = #id#
- </select>
- 별칭 idsms id라고 불리는 Address 클래스의 프로퍼티에 매핑
- #id# - 파라미터(Integer 형)
-
위 코드를 수행하는 자바 코드
- Address addr = (Address) sqlMap.queryForObject("getAddress", new Integer(5));
-
위 코드를 수행하는 C# 코드
- Address addr = (Address) sqlMap.queryForObject("getAddress", 5);
-
-
JDBC, ADO.NET 코드 작성 대신
-
예) JDBC vs iBATIS
-
JDBC
- public Employee getEmployee (int id) throws SQLException {
Employee employee = null;
String sql = "SELECT * from employee " +
"where employee_number = ?";
Connection conn = null;
PreparedStatemnent ps = null;
ResultSet rs = null;
try {
conn = datasource.getConnection();
ps = conn.prepareStatement(sql);
ps.setInt(1, id);
rs = ps.executeQuery();
while (rs.next()) {
employee = new Employee();
employee.setId(rs.getInt("ID"));
employee.setEmployeeNumber(rs.getInt("EMPLOYEE_NUMBER"));
employee.setFirstName(rs.getString("FIRST_NAME"));
employee.setLastName(rs.getString("LAST_NAME"));
employee.setTitle(rs.getString("TITLE"));
}
} finally {
try {
if(rs != null) rs.close();
} filnally {
try {
if (ps != null) ps.close();
} filnally {
if (conn != null) conn.close();
}
}
}
return employee;
}
- public Employee getEmployee (int id) throws SQLException {
-
iBATIS
- <select id="getEmployee" parameterClass="java.lang.Integer" resultClass="Employee">
- select
- ID as id,
- EMPLOYEE_NUMBER as description,
- FIRST_NAME as street,
- LAST_NAME as city
- TITLE as title
- from employee
- where EMPLOYEE_NUMBER = #empNum#
- </select>
-
실행 코드
- Employee emp = (Employee) sqlMap.queryForObject("getEmployee", new Integer(5));
-
-
-
-
- (추가내용)
자바빈즈를 PreparedStatement 파라미터와 ResultSet으로 맵핑시켜주는 기능을 담당
-
디미터 법칙(Law of Demeter) "각 계층은 다른 계층에 대해 오직 제한된 정보만을 가질 수 있다: 오직 현재 계층에 인접한 계층에 대해서만."
- 각 계층이 오직 자기 바로 아래 계층과만 소통 가능
- 의존성이 한 방향으로만 흐르는 것을 조장(스파게티 코드 피하기)
- iBATIS는 퍼시스턴스 계층 프레임워크(위: 비지니스 로직 / 아래: 데이터베이스)
Spring과 iBATIS
-
왜 iBATIS대신에 Spring을 사용할까?
-
iBATIS DAO 계층
- 장점: 빠르고 쉬운 솔루션
- BATIS SQL Maps / iBATIS DAO 계층 분리(2.3~)
- 요구사항: 트랜잭션/커넥션 관리 -> Spring보다 훨씬 간단하게 사용가능한 프레임워크
- 단점: 간결함
-
DAO 패턴을 사용: 결함도가 낮아짐(decoupling) -> 테스트하기 쉽다
- Action에서 필요한 코드의 구현을 알 필요 없이 오직 필요한 인터페이스만 알면 됨.
- 구현체는 설정을 통해 기워 넣게 됨
- Spring : 커넥션과 트랜잭션 관리, 애플리케이션의 모든 부분에 적용(iBATIS DAO는DAO계층에만 적용)
-
-
효율적인 DAO 계층
-
구현체에서 인터페이스 분리
-
이유
- 구현체 바꿔 치기가 가능(다른 형태의 데이터 접근 지원 가능)
- 테스트가 쉽고 빨리짐(실제 DB에 접근하는 객체 대신 가상의 DAO 객체를 끼워 넣을 수 있으므로)
-
IDE : 분리 과정 쉽게 처리 가능
- 리팩토링 툴(클래스에서 인터페이스를 분리 가능)
-
인터페이스를 만들 때 구현 클래스를 어떤 다른 데잍터베이스를 다루는 툴에 종속적인 부분에 노출 가능성 높음
-
노출: DAO가 아닌 데이터 접근 구현체에 애플리케이션을 묶어버림
-
예) 'Fast Lane Reader'패턴을 사용하는 웹 애플리케이션 - JDBC 코드가 뷰 계층과 직접 소통 (테스트 어려워짐)
- -> 콜백을 사용해서 코드를 작성(뷰가 요청한 데이터를 처리하는 RowHanlder 같은 것)
-
-
SQL Maps API를 직접 사용하는 애플리케이션 -> 캡슐화된 API
-
예) sqlMapClient 객체의 queryForList() 메소드를 호출하는 클래스 - > 작성한 DAO 클래스를 호출하게 리팩토링, 클래스의 메소드에서는 List 객체를 반환
- 데이터 사용자 - 작성한 DAO하고만 소통 가능
-
-
-
-
외부에서 설정된 팩토리(factory)를 사용하여 구현체의 결합도 낮추기
-
인터페이스와 구현체 둘 다 DAO를 사용하는 클래스에 노출(인터페이스에 대한 의존성을 DAO를 사용하는 클래스에 추가한 셈)시키면 안됨
-
[구현체]-[DAO]-[interface]-> 구현체를 어떻게 사용할 수 있을 것인가?
- AccountDao accountDao = new AccountDaoImpl(); // DAO를 구현에서 분리, 구현체를 직접 참조하고 있음
- AccountDao accountDao = (AccountDao)DaoFactory.get(AccoutDao.class); // 초점: DaoFacotry가 AccountDao 인테페이스를 구현한 객체를 반환
-
DAO factory
-
public인테피이스는 getInstance()와 getDao() 두개의 메소드로 이루어져 있음
- public class DaoFactory {
- private static DaoFatory instance = new DaoFactory();
- private final String defaultConfigLocation = "DaoFactory.properties"; // 프로퍼티 화일(인터페이스, 구현체 이름)
- private Properties daoMap;
- private Properties instanceMap;
- private String configLocation = System.getProperty(
-
"dao.factory.config",
defaultConfigLocation
);
- private DaoFactory() { // 1. private 생성자 선언(single tone; 오직 단 한 개의객체만 생성할 수 있는 클래스)
- daoMap = new Properties();
- instanceMap = new Properties();
- try {
- daoMap.load(getInputStream(configLocation));
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- private InputStream getInputStrream(String configLocation)
- {
- return Thread
- .currentThread()
- .getContextClassLoader()
- .getResourceAsStream(configLocation);
- }
- public static DaoFactory getInstance() { // 2. 간단한 팩토리 메소드를 선언 (이 클래스의 유일한 인스턴스 반환)
- return instance;
- }
- public Object getDao(Class daoInterface) { // 3. DAO를 가져온다 (인터페이스의 구현체를 반환)
- if (instanceMap.containsKey(daoInterface)) {
- return instanceMap.get(daoInterface);
- }
- return createDao(daoInterface);
- }
- private synchoronized Object createDao (Class daoInterface) { // 4. 타입 별로 단 하나의 DAO만 생성함을 보장
- Class implementationClass;
- try {
- implementationClass = Class.forName((String)daoMap.get(daoInterface));
- Object implementation = implementationClass.newInstance();
- instanceMap.put(implementationClass, implementation);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- return instanceMap.get(daoInterface); // DAO에 대한 실제 요청이 발생할 때에 생성
- }
- }
-
-
-
- 트랜잭션과 커넥션 관리기능 제공(chap. 7)
-
-
스프링: 데이터 매퍼의 두 가지 버전(1.3, 2.0)을 지원
- 버전 1.3 : SqlMapXxx (SqlMapTemplate 클래스 사용)
-
버전 2.0 : SqlMapClientXxx (SqlMapClientTemplate 클래스 사용: 내부적으로 iBATIS의 SqlMapClient 사용)
-
SqlMapClient를 스프링 빈으로 설정 : SqlMapClientFactoryBean 클래스 이용
-
<bean id="sqlMapClinet" class="org.springframework.orm.ibatis.SqlMapClinetFactoryBean"
- p:dataSource-fef="dataSource"
- p:configLocation="WEB-INF/sqlMap/sqlMapConfig.xml">
- </bean>
-
-
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">
- <sqlMapConifg>
- <sqlMap resource="GuestBook.xml" />
- </sqlMapConifg>
-
GuestBook.xml
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE sqlMap
- PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
- "http://ibatis.apache.org/dtd/sql-map-2.dtd">
- <sqlMap namespace="Guestbook">
-
<typeAlias alias="Message" type="kame.spring.questbook.service.Message" />
<parameterMap id="messageParamMap" class="Message">
- <parameter property="guestName" />
- </parameterMap>
- <resultMap id="messageResultMap" class="Message">
- <result property="id" column="GUESTBOOK_MESSAGE_ID" />
- <result property="guestName" column="GUEST_NAME" />
- <result property="content" column="CONTENT" />
- </reslutMap>
- ..
- <select id="selectList" resultMap="messageReusltMap" resultClass="Message" parameterCalss="map">
- select * from GUESTBOOK_MESSAGE order by GUESTBOOK_MESSAGE_ID desc limit #startRow#, #fetchSize#
- </select>
- </sqlMap>
- limit 는 mySql에 있다.
-
바깥고리
JDeveloper에서 iBATIS 실행하기
자동으로 클래스패스를 잡아주니 라이브러리에 추가만 해주면 된다.
1. Library Name에 알기 쉬운 이름을 붙여준다(iBATIS2.3.0.677)
iBATIS를 통해 더 즐겁게 개발하고, 또 개발의 재미도 느끼고 야근도 덜 할 수 있기를 기원한다. - xx
불가지론자(경험해보지 않은 것은 믿을 수 없다) - xxi
"망치를 가진 사람은 모든 것을 못으로 본다" , 환경이 다양하면 다양한 도구가 필요한 법 - xxii
책을 쓰는 것은 (소프트웨어를 작성)하는 것보다 더 어렵다. - xxiv
돈을 위해 낮에는 일을 하고 명성과 영광을 얻기 위해 밤에는 오픈소스 소프트웨어(또는 책)를 작성하기 위해 시간을 보낸다.(클린턴 비긴) - xxiv
긱(geek: 학업이나 일, 컴퓨터 등에 몰두하다 보니 세상물정과는 거리가 멀어진 사람 / 특정 분야에 대해 광적인 사람), 우리는 첫 번째 컴퓨터를 가졌을때의 좋은 기억이 있고 그 컴퓨터를 사주는 투자가 나중에 좋은 결과를 낳게 된다는 것을 아는 부모님을 신뢰한다. - xxv
책은 무언가를 배우는 최고의 방법, 종이책이 전자책으로 대체되거나 뒤통수에 잭을 꼽아서 몇 초안에 정보를 업로드하는 방식으로 바뀔 거라는 등 많은 억측, 나는 책을 좋아한다. 책은 편리하게 갖고 다닐 수 있고, 다루기도 쉽기 때문이다. 책에 메모를 남기고, 종이를 접고, 반으로 쪼개서 갖고 다닐 수도 있다.(클린턴 비긴) - xxvii
사람들은 스스로 동기를 부여받아 탐구하는 동안 배운 것들을 기억(인지 과학), 인류는 행동하며(in action) 배운다. - xxxii
노하우
db.properties 위치
- Total
- Today
- Yesterday
- gmlduqrhdwn
- judyOh blog
- naplez.net [ SCJP 1.4 ]
- DB
- web
- 한글 Mozilla 포럼 [실전웹표준가이드]
- (블로그)웹표준연구소 [마루아라소프트]
- 웹 프로그램 및 디자인관련 강좌 사이트
- (블로그)검색엔진 최적화 | 검색엔진 마케팅
- DB 툴 [DB에 대한 정보]
- PHP( 객체 지향 언어로써의 PHP )
- w3c표준규격 번역
- 서버 주무르기
- 검색엔진 마스터
- apache-kr.org
- 한국 썬 개발자 네트워크
- 검색엔진 최적화 블로그
- 피라시스닷컴(SVN관련)
- 웹기반 DNS 서비스 DNSEver.com
- JEUS / Tmax / WebtoB
- 웹기반 무료 DNS서버
- JAVA 강좌
- 少年易老學難成, 一寸光陰不可輕. 未覺池塘春草夢, 階前梧…
- MyJavaServer ( JSP 무료 호스팅 )
- I GOT IT (IT`S CRADLE & INCUBA…
- Todayis(HS)
- oracleclub.com
- Prototype (JavaScript Framewor…
- JSPWiki (openframework.or.kr)
- 제갈장비(JAVA_BLOG)
- jakartaproject
- Oracle_download
- jQuery plugin
- Test
- 안드로이드 앱 개발
- 행복한 개발자입니다.
- Flex & etc
- Flex & Design
- (iBatis)참고
- FLEX참고 사이트
- 대용량파일에 대한 watchservice 참고
- win7 update pack
- mysql
- ASP
- DOM
- 롤링
- 비교문
- apache
- vi
- find
- 정보보호전문자격
- 자동증가
- 뚜비
- 다운로드
- SEO
- Eclipse
- 구글
- php
- 오라클
- mybatipse #egovframework3.8
- excel
- Linux
- GD
- Ajax
- 머먹구사냐
- flex
- CSS
- sw기술자 경력관리
- iBatis
- java
- 시퀀스생성
- derby
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |