티스토리 뷰
[01] iBATIS 개론
- SQL Maps 프레임워크는 관계형 데이터베이스에 접근할 때 필요한 자바코드를 현저하게 줄일수 있도록 도와줍니다.
- SQL Maps는 간단한 XML서술자를 사용해서 간단하게 자바빈즈를 SQL statement에 맵핑시킵니다.
- SQL Map API는 프로그래머에게 자바빈즈를 PreparedStatement파라미터와 ResultSets으로 쉽게 맵핑할수 있도록 함.
- SQL과 비즈니스 로직이 분리되어 있어 배포 및 유지보수, 재활용성이 뛰어납니다.
- 일반 SQL뿐만 아니라 저장 프로시져까지 iBATIS는 처리할 수 있습니다.
- 파라미터를 기반으로 동적으로 실행할 SQL을 지정할 수 있습니다.
1. - iBATIS의 위치
JSP ---> Spring(Struts2)---> Manager ---> DAO ---> iBATIS ---> SQL ---> ORACLE
| |
| |
+----- DTO(Value Object, Domain Object ------------+
- iBATIS의 설정의 핵심 개념
- iBATIS의 설정파일
. SqlMapConfig 파일: 최상단에 위치 하며 전체옵션을 설정하고 각각의 SQL Map파일들의 위치를 지정합니다.
. Sql Map 파일 : 애플리케이션이 데이터베이스와 소통하기 위해 제공하는 입력 파라미터 값과 조합되는 매핑 구문을 정의 합니다.
2. 다운 로드 및 설치 (현재는 MyBATIS로 변경됨)
- http://ibatis.apache.org
- ibatis-2.3.4.726.jar 파일을 복사하여 'lib' 폴더에 복사합니다.
3. SQL Maps 설정 파일 형식
-sql맵 파일 위치 명시
>>>>> ibatis-2.3.0.677/simple_example/com/mydomain/data/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>
<!-- Configure a built-in transaction manager. If you're using an
app server, you probably want to use its transaction manager and a managed datasource -->
<transactionManager type="JDBC" commitRequired="false">
<dataSource type="SIMPLE">
<property name="JDBC.Driver" value="org.hsqldb.jdbcDriver"/>
<property name="JDBC.ConnectionURL" value="jdbc:hsqldb:."/>
<property name="JDBC.Username" value="sa"/>
<property name="JDBC.Password" value="sa"/>
</dataSource>
</transactionManager>
<!-- List the SQL Map XML files. They can be loaded from the classpath, as they are here (com.domain.data...) -->
<sqlMap resource="com/mydomain/data/Account.xml"/>
<!-- List more here...
<sqlMap resource="com/mydomain/data/Order.xml"/>
<sqlMap resource="com/mydomain/data/Documents.xml"/>
-->
</sqlMapConfig>
sqlMapConfig파일의 구체적인 설명을 보려면 클릭
4. SQL Map 파일 형식
-sql문
>>>>>> ibatis-2.3.0.677/simple_example/com/mydomain/data/Account.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="Account">
<!-- Use type aliases to avoid typing the full classname every time. -->
<typeAlias alias="Account" type="com.mydomain.domain.Account"/> 간단한 형식선언
<!-- Result maps describe the mapping between the columns returned
from a query, and the class properties. A result map isn't
necessary if the columns (or aliases) match to the properties exactly. -->
<resultMap id="AccountResult" class="Account">
<result property="id" column="ACC_ID"/>
<result property="firstName" column="ACC_FIRST_NAME"/>
<result property="lastName" column="ACC_LAST_NAME"/>
<result property="emailAddress" column="ACC_EMAIL"/>
</resultMap>
<!-- Select with no parameters using the result map for Account class. -->
<select id="selectAllAccounts" resultMap="AccountResult">
select * from ACCOUNT
</select>
<!-- A simpler select example without the result map. Note the
aliases to match the properties of the target result class. -->
<select id="selectAccountById" parameterClass="int" resultClass="Account"> DTO
select한 결과가 resultClass Account에 저장됨
id는 여러개의 select가 있을 때 구분하기 위해서..쓴다
select
ACC_ID as id, 컬럼명 as ailias(Account DTO의 property필드명과 왼쪽 DB컬럼값 이 둘의 이름은 같아야 한다,
다르다면 alias 별명을 붙여서 같게 만들어 주어야 한다)
ACC_FIRST_NAME as firstName,
ACC_LAST_NAME as lastName,
ACC_EMAIL as emailAddress
from ACCOUNT
where ACC_ID = #id# 파라미터 클래스는 int이고 여기서는 ? 가 아니다.
</select>
<!-- Insert example, using the Account parameter class -->
<insert id="insertAccount" parameterClass="Account">
insert into ACCOUNT (
ACC_ID,
ACC_FIRST_NAME,
ACC_LAST_NAME,
ACC_EMAIL
)values (
#id#, #firstName#, #lastName#, #emailAddress# Account에 있는 컬럼들이 자동으로 ##getter이용해서 들어감
)
</insert>
<!-- Update example, using the Account parameter class -->
<update id="updateAccount" parameterClass="Account">
update ACCOUNT set
ACC_FIRST_NAME = #firstName#,
ACC_LAST_NAME = #lastName#,
ACC_EMAIL = #emailAddress#
where
ACC_ID = #id#
</update>
<!-- Delete example, using an integer as the parameter class -->
<delete id="deleteAccountById" parameterClass="int">
delete from ACCOUNT where ACC_ID = #id#
</delete>
</sqlMap>
5. SqlMapClient API를 통해 statement를 수행하기.
- buildSqlMap()메소드는 간단하게 sqlMap-config.xml의 내용을 읽을수 있는 Reader인스턴스를 가져온다.
- SqlMapClient는 이것에 관련된 모든 맵핑된 statement를 수행하기 위한 API를 제공한다. 그 메소드들은 아래와 같다.
:
SQL Map XML 파일
<sql>
refid - <sql>로 생성된 쿼리문을 refid=id 로 해서 <include>로 가져온다.
<sql id="boardWhere">
<isNotEmpty property="keyword" prepend="AND">
<isEqual property="keytype" compareValue="title">
title LIKE '%' || #keyword# || '%'
</isEqual>
<isEqual property="keytype" compareValue="content">
contents LIKE '%' || #keyword# || '%'
</isEqual>
<isEqual property="keytype" compareValue="userid">
userid LIKE '%' || #keyword# || '%'
</isEqual>
<isEqual property="keytype" compareValue="all">
(
title LIKE '%' || #keyword# || '%'
OR
contents LIKE '%' || #keyword# || '%'
OR
userid LIKE '%' || #keyword# || '%'
)
</isEqual>
</isNotEmpty>
</sql>
<select id="getList" parameterClass="boardCmd" resultMap="domain">
SELECT
boardSeq, categoryId, userid, title, contents, hit, regDate, grp, dep, stp,
commCnt, attachCnt, isReply, rowNum
FROM (
SELECT
boardSeq, categoryId, userid, title, contents, hit, regDate, grp, dep, stp,
commCnt, attachCnt, isReply,
ROW_NUMBER() OVER(ORDER BY grp DESC, stp) as rowNum
FROM
board
WHERE
categoryId = #categoryId#
<dynamic>
<include refid="boardWhere" />
</dynamic>
)
WHERE rowNum BETWEEN #start# AND #end#
</select>
<parameterMap>
parameterMap - ?,? 표시로 접근, parameterMap 태그를 따로 선언해야함 ,
맵형식의 값을 파라미터로 전달해야 할 때 사용. (한번에 많은 값 전달 시에 쓰는 것 같음)
<parameterMap id="boardColumn" class="Board">
<parameter property="boardSeq" jdbcType="NUMBER" /> 1번째 물음표 값
<parameter property="title" jdbcType="NVARCHAR" /> 2번째 물음표 값
<parameter property="contents" jdbcType="NTEXT" /> 3번째 물음표 값
</parameterMap>
<insert id="insert" parameterMap="boardColumn">
INSERT INTO board (
boardSeq, title, contents
) VALUES (
?, ?, ?
)
</insert>
<selectKey>
- 자동 key 생성 , 자동증가
<insert id="" parameterClass="BoardDTO" .. >
<selectKey keyProperty="boardSeq" resultClass="int">
keyProperty : DTO 필드(멤버변수)/boardSeq는 num같은거
SELECT nextVal(#sequence#)
selectKey값을 사용하면 리턴형이 시퀀스번호의 객체형이다 (10이면 Integer 10)
안썼다면 null 반환,
</selectKey>
INSERT (....) VALUES (#boardSeq#, ...) Table
</insert>
insert후에 그 Primary 키가 필요할 떄 사용
보통의 경우에는 insert한 개수를 얻어오기 위해 update태그 안에 넣어 준다. 이런경우에는 update 태그를 호출해 주어야 함
<Result Map> Collection (한방쿼리)
resultMap - resultClass와 같은 역할하며 resultMap 태그를 따로 선언해야함
- 컬럼의 이름과 저장할 객체에 필드가 이름이 다를때 사용
- BoardDTO.java
private int boardSeq ;
private String title;
private String contents;
private List<Attachment> attachList;
:
- BoardDao.java
getSqlMapClientTemplate().queryForObject("Board.get", 10); //namespace명.id,
parameterClass int형식의 #value#의 값
:
<sqlMap namespace="Board">
<resultMap id="boardView" class="BoardDTO">
<result property="boardSeq" column="boardSeq" />
<result property="title" column="title" />
<result property="contents" column="contents" />
<result property="attachList" select="Board.getAttachList" column="boardSeq" />
//namespace명.id
</resultMap>
<select id="get" parameterClass="int" resultMap="boardView">
SELECT boardSeq, title, contents FROM board
WHERE boardSeq = #value#
</select>
<select id="getAttachList" parameterClass="int" resultClass="Attachment">
SELECT boardSeq, attachSeq, fileName FROM attachment WHERE boardSeq = #value#
</select>
</sqlMap>
resultMap의 <result> 프로퍼티 들은 자바 객체의 변수로 선언되어 잇어야 하며, get/set 메소드가 설정되어 있어야 한다
- property : 자바빈 객체(BoardDTO)의 멤버변수이름
- column : 쿼리 결과 ResultSet 내의 칼럼의 이름
참고: http://hyeonstorage.tistory.com/285 [개발이 하고 싶어요]
<parameterMap> 동적맵핑 문장 (다이나믹 쿼리)
<select id="get" parameterClass="cmd" resultClass="board">
SELECT *
FROM board
<dynamic prepend=" WHERE " open="(" close=")">
<isNotEmpty property="keyword">
<isEqual property="keytype" compareValue="title">
title LIKE '%' || #keyword# || '%'
</isEqual>
<isEqual property="keytype" compareValue="content">
contents LIKE '%' || #keyword# || '%'
</isEqual>
</isNotEmpty>
</dynamic>
</select>
<select id="board parameterClass="cmd" resultClass="Board">
SELECT * FROM board
<dynamic prepend=" WHERE ">
<isEqual property="userType" compareValue="ADMIN">
userType = 'ADMIN'
</isEqual>
<isNotEqual property="userType" compareValue="ADMIN">
userType <> 'ADMIN'
</isNotEqual>
</dynamic>
</select>
dynamic 요소
property – 비교되는 프라퍼티(필수)
[prepend] – statement에 붙을 오버라이딩 가능한 SQL부분
[open] – 결과적인 전체내용물을 열기위한 문자열
[close] – 결과적인 전체내용물을 닫기위한 문자열
이항연산
removeFirstPrepend - 처음으로 내용을 출력하는 자식 요소의 prepend속성 값을 출력할지 여부
comparePreperty - property 속성과 비교할 파라미터 객체의 프로퍼티
compareValue - property 속성과 비교할 정적인 값
<isEqual> / <isNotEqual>
<isGreaterThan> - 값이 큰지
<isGreaterEqual> - 값이 크거나 같은지
<isLessThan> - 값이 작은지
<isLessEqual> - 값이 작거나 같은지
단항연산
removeFirstPrepend - 처음으로 내용을 출력하는 자식 요소의 prepend속성 값을 출력할지 여부
<isPropertyAvailable> - 프로퍼티가 파라메터에 존재하는지 검사, domain에서는 프로퍼티를, Map에서는 key를 찾는다.
<isNotPropertyAvailable> - 프로퍼티가 파라메터에 존재하지 않는지 검사, domain에서는 프로퍼티를, Map에서는 key를 찾는다.
<isNull> / <isNotNull>
<isEmpty> / <isNotEmpty>
파라미터 요소 (parameterClass, parameterMap)
<isParameterPresent> - 파라메터가 존재하는지
<isNotParameterPresent> - 파라메터가 존재하지 않는지
<select id="board" resultClass="Board">
SELECT * FROM board
<isParameterPresent prepend=" WHERE ">
<isNotEmpty property="category">
category = #category#
</isNotEmpty>
</isParameterPresent>
</select>
ibatis/board.xml
board.xml
<delete id="deleteXE" parameterClass="map">
DELETE FROM board
<dynamic prepend=" WHERE ">
<iterate property="boardSeqs" open=" num IN (" close=")" conjunction=",">
#boardSeqs[]#
</iterate>
</dynamic>
</delete>
->dynamic 문장: where문에 iterate로 반복처리하면서 num IN(으로 시작할거고 ,를 중간마다 붙여주면서 )으로 끝낼거야.
그 값들은 boardSeqs[]안에 있는 값들 일거야. 여기서 property의 boardSeqs는 단지 for문의 i나 iterater의 value..?같이 의미없는 것 같음
sql 결과: delete from board
where num in (2,4,6,8);
BoardDAO.java
:
@Autowired
private SqlMapClientTemplate ibatis;
public void setIbatis (SqlMapClientTemplate ibatis) {
this.ibatis = ibatis;
}
public int deleteXE() throws Exception {
int boardSeqs[] = {2,4,6,8};
Map map = new HashMap();
map.put("boardSeqs", boardSeqs);
return ibatis.delete("board.deleteXE", map) ; ② sqlmap 파일(board.xml)의 delete id가 deleteXE인 태그를
호출하여 결과값 리턴받은것을 리턴함
}
BoardTest.java
package spring.sts.model;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
public class BoardTest {
public static void main(String[] args) throws Exception {
Resource rs = new ClassPathResource("board.xml");
BeanFactory factory = new XmlBeanFactory(rs);
BoardDAO dao = (BoardDAO) factory.getBean ("dao"); board.xml에서 객체생성한 DAO객체를 가져온다
int cnt = dao.deleteXE(); ① DAO 메소드 호출
System.out.println("cnt:"+cnt);
if(cnt>0){
System.out.println("성공");
}else{
System.out.println("실패");
}
}
}
>>>>> src/main/resources/ibatis-config.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">
<!-- SQL Mapping file list -->
<sqlMapConfig>
<settings
useStatementNamespaces="true"
/>
<sqlMap resource="ibatis/board.xml" />
</ sqlMapConfig>
sqlMapConfig: 전역정보 설정파일, sql Map파일의 위치 명시 등
sql Map 파일 : sql문
porm.xml에 추가
<!-- iBATIS setting -->
<dependency>
<groupId>org.apache.ibatis</groupId>
<artifactId>ibatis-sqlmap</artifactId>
<version>2.3.4.726</version>
</dependency>
<!-- DBCP setting -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- Oracle JDBC Driver-->
:
:
<repositories>
root-context.xml에 추가
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p" (4번째줄에 추가)
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dao" class="spring.model.board.BoardDAO" 사용할 DAO 객체 생성
p:ibatis-ref = "sqlMapClientTemplate"
/>
<!-- 데이터베이스 접속 설정 -->
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource"
p:driverClassName="oracle.jdbc.driver.OracleDriver"
p:url="jdbc:oracle:thin:@127.0.0.1:1521:XE"
p:username="soldesk"
p:password="1234"
p:maxActive="2"
p:maxIdle="1"
p:defaultAutoCommit="true"
/>
<!-- iBATIS SQL 실행 클래스 -->
<bean id="sqlMapClient"
class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"
p:dataSource-ref="dataSource"
p:configLocation="WEB-INF/spring/ibatis-config.xml" />
<!-- Spring과 iBATIS 연결자 -->
<bean id="sqlMapClientTemplate"
class="org.springframework.orm.ibatis.SqlMapClientTemplate"
p:sqlMapClient-ref="sqlMapClient" />
'IBATIS MYBATIS' 카테고리의 다른 글
[MyBatis] MyBatis 특징, SqlSession생성, SQL 문장 실행 (0) | 2018.04.23 |
---|