레이블이 IBatis인 게시물을 표시합니다. 모든 게시물 표시
레이블이 IBatis인 게시물을 표시합니다. 모든 게시물 표시

2012년 8월 24일

Spring 프레임워크와 iBatis를 연동


목적 :
 Spring 프레임워크와 iBatis를 연동한다.

준비물 :
1. JDK : JDK 1.5 이상 설치되어있어야 함
2. 웹서버 : 아파치 톰캣 5.5.23
3. 라이브러리 : Spring프레임워크 1.2.9 (다운로드 : http://www.springframework.org/download)
4. 라이브러리 : iBatis 2.3 (다운로드 : http://ibatis.apache.org/javadownloads.cgi)
5. 개발툴 : WTP (이클립스 플러그인) (다운로드 : http://www.eclipse.org/downloads/) 
               By Project에서 이클립스랑 통합된 All-in-one 버전을 추천
6. 지식 수준 : Java, 서블릿 사용가능, J2EE환경에 대한 기초지식


시작하기 전에 :
1. JDK 1.5 이상이 설치 되어있어야 한다.
2. tomcat 5.5.23 이 설치 되어있어야 한다.
3. 개발툴이 설치되어 있어야 한다.

시작 :
모두 다운로드 받았으면

[1. 프로젝트 생성 및 lib 넣어주기]
이클립스(WTP)에서 다이나믹 웹 프로젝트를 만들고
spring jar와 ibatis 관련 jar등을 lib 폴더에 넣어준다.
그 외에 common 관련 lib 들도 넣어주고..
jdbc용 라이브러리들도 넣어줘야 한다.
(이 부분이 좀.. 불친절해서 시간이 더 소요될지도 모르겠다..)


[2. web.xml  설정]
그리고  WEB-INF 폴더 밑에 있는 web.xml 을 수정한다.

<web-app>
 <display-name>licenceweb</display-name>
노드 아래에

<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>/WEB-INF/dataAccessContext.xml  /WEB-INF/applicationContext.xml</param-value>
 </context-param>
    <listener>
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
어플리케이션 설정과
DB설정을 위해 이 부분을 추가하고

    <servlet>
  <servlet-name>licenceweb</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
 </servlet>

 <servlet-mapping>
        <servlet-name>licenceweb</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
스프링 연동을 위해 서블릿 설정을 한다.

보너스로 톰캣 인코딩 설정을 위해(post, get 파라미터용, 한글이 안 깨지도록)
    <!-- 인코딩 필더 설치 -->
    <filter>
          <filter-name>encodingFilter</filter-name>
          <filter-class>
               org.springframework.web.filter.CharacterEncodingFilter
          </filter-class>
          <init-param>
               <param-name>encoding</param-name>
               <param-value>utf-8</param-value>
          </init-param>
     </filter>
     <filter-mapping>
          <filter-name>encodingFilter</filter-name>
          <url-pattern>/*</url-pattern>
     </filter-mapping>
을 추가한다.


[3. licenceweb-servlet.xml 설정] 
(* licenceweb은 디스플레이 이름과 동일하게..다른 걸로 바꾸었다면 그 이름으로 한다.)
spring을 위한 xml 설정파일이다.
기본적으로 루트는 <beans>로 시작하고
그 하위 노드를 추가한다.

 <!-- ========================= VIEW DEFINITIONS ========================= -->
 <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
  <property name="prefix" value="/WEB-INF/jsp/"/>
  <property name="suffix" value=".jsp"/>
 </bean>

VIEW를 위해서 정의하고.
(이 부분의 역할은 서버의 view에서 넘겨줄 페이지를 위해 prefix랑 suffix를 설정하는 부분..
추후에 자세히 설명하겠다..)


 <!-- ========================= DEFINITIONS OF PUBLIC CONTROLLERS ========================= -->
 <bean 
   id="defaultHandlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

<bean name="/login.do" class="com.comtrue.pc.licenceweb.web.LoginController">
  <property name="licenceWeb" ref="licenceWeb"/>
 </bean>
 <bean name="/logout.do" class="com.comtrue.pc.licenceweb.web.LogoutController">
 </bean>
...

컨트롤러를 위해 이 부분을 정의한다.
(설정에 있어서는 클래스의 public, protected 처럼 지정할 수 있지만
여기서는 일단 public 만 넣어둔다.)


[4. applicationContext.xml 설정]
어플리케이션 컨텍스트를 설정하는 부분이다
db 설정 파일을 스프링에서 쓸 수 있게하고
트랜잭션 등을 설정한다.
밸리데이션 등을 지정할 수도 있다.


<beans>
 <!-- ========================= GENERAL DEFINITIONS ========================= -->
 <!-- Configurer that replaces ${...} placeholders with values from properties files -->
 <!-- (in this case, mail and JDBC related properties) -->
 <bean id="propertyConfigurer"
    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="location">
   <value>WEB-INF/db_mssql.properties</value>
  </property>
 </bean>

스프링의 PropertyPlaceholderConfigurer를 위해
jdbc파일의 경로를 지정하여 쓸 수 있게 하고


 <bean 
    id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
    abstract="true">
  <property name="transactionManager" ref="transactionManager"/>
  <property name="transactionAttributes">
   <props>
    <prop key="insert*">PROPAGATION_REQUIRED</prop>
    <prop key="update*">PROPAGATION_REQUIRED</prop>
    <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
   </props>
  </property>
 </bean>

트랜잭션 매니저를 지정한다.


 <bean id="licenceWeb" parent="baseTransactionProxy">
  <property name="target">
   <bean class="com.comtrue.pc.licenceweb.domain.logic.LicenceWebImpl">
    <property name="accountDao" ref="accountDao"/>
    <property name="licenceDao" ref="licenceDao"/>
   </bean>
  </property>
 </bean>

스프링프레임워크의 서비스 부분을 위한 DAO를 설정하여 트랜잭션 관리를 지정한다.


[5. db_mssql.properties 설정]
####################################
# MSSQL 2000
####################################
jdbc.driverClassName=com.microsoft.jdbc.sqlserver.SQLServerDriver
jdbc.url=jdbc:microsoft:sqlserver://localhost:1433;SelectMethod=cursor;DatabaseName=데이터베이스이름;
jdbc.username=아이디
jdbc.password=비밀번호


[6. dataAccessContext.xml 설정]
<beans>

 <!-- ========================= RESOURCE DEFINITIONS ========================= -->
 <!-- Local Apache Commons DBCP DataSource that refers to a combined database -->
 <!-- (see dataAccessContext-jta.xml for an alternative) -->
 <!-- The placeholders are resolved from jdbc.properties through -->
 <!-- the PropertyPlaceholderConfigurer in applicationContext.xml -->
 <bean id="dataSource"
        class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName"><value>${jdbc.driverClassName}</value></property>
        <property name="url"><value>${jdbc.url}</value></property>
        <property name="username"><value>${jdbc.username}</value></property>
        <property name="password"><value>${jdbc.password}</value></property>
    </bean>

dataSource에 jdbc 설정을 알린다. 이 부분은 5번의 프로퍼티 파일에서 읽어왔기 때문에
${} 식으로 받아서 서버에서 처리하게 된다.


   
    <!-- Transaction manager for a single JDBC DataSource -->
 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dataSource" />
 </bean>

이 부분은.. 트랜잭션 매니저 bean을 설정하는 부분..


 <!-- SqlMap setup for iBATIS Database Layer -->
 <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
     <property name="configLocation" value="WEB-INF/sqlmap-config.xml"/>
     <property name="dataSource" ref="dataSource"/>
   </bean>

이 부분은 iBatis 연동을 위해 sql map 설정파일의 경로를 지정하고
dataSoruce를 지정한다.


 <!-- ========================= DAO DEFINITIONS: IBATIS IMPLEMENTATIONS ========================= -->

 <bean id="accountDao" class="com.comtrue.pc.licenceweb.dao.ibatis.SqlMapAccountDao">
  <property name="sqlMapClient" ref="sqlMapClient"/>
 </bean>


이 부분은 Dao를 구현한 클래스를 정의한다.


[7. sqlmap-config.xml 설정]
iBatis 연동을 위해 sqlmap 설정한다.

<sqlMapConfig>
 <sqlMap resource="com/comtrue/pc/licenceweb/dao/ibatis/maps/Account.xml" />
 <sqlMap resource="com/comtrue/pc/licenceweb/dao/ibatis/maps/Licence.xml" />
</sqlMapConfig>

Dao 클래스들이 사용하는 쿼리를 담은 xml 경로를 지정한다.


[8. Account.xml 설정, 객체마다 해야함]
Dao 클래스에서 사용하는 쿼리를 입력해두는 파일

<sqlMap namespace="Account">
  <resultMap id="result" class="com.comtrue.pc.licenceweb.domain.Account">
   <result property="userid" column="userid" columnIndex="1"/>
    <result property="name" column="name" columnIndex="2"/>
    <result property="email" column="email" columnIndex="3"/>
  </resultMap>
  <select id="getAccountByUseridAndPassword" resultMap="result">
    select userid, name, email
    from ACCOUNT
    where userid = #userid# and password = #password#
  </select>
</sqlMap>

resultMap 은 결과 형태를 지정하는 노드고

select 노드는 select 할 때를 위한 쿼리를 담는 곳이다.
이때 resultMap 속성에 resultMap 의 id를 지정한다. 그러면.. 결과 시에
resultMap 형식으로 결과를 갖고 온다.


[9. SqlMapAccountDao.java 구현 예]

public class SqlMapAccountDao extends SqlMapClientDaoSupport implements AccountDao {
 public Account getAccount(String userid, String password) throws DataAccessException
 { 
  Account account = new Account();
  account.setUserid(userid);
     account.setPassword(password);
    
  return (Account) getSqlMapClientTemplate().queryForObject("getAccountByUseridAndPassword", account);
 }
}

getSqlMapClientTemplate()의 queryForObject()를 사용해서
seletc 쿼리를 수행한다. 결과는 resultMap 형식의 클래스로 돌려받게 된다.

Dao를 구현한 클래스들은 서비스 형식의 클래스에서 사용하는 방식으로 개발을 한다.
Dao를 직접 View부분에서 지정하진 않고..


p.s. 2주전쯤 프레임워크 적용을 했었는데..
혹 도움이 될까해서 올려봅니다..

Java 클래스 부분 설명이 없어서.. 이것만 보고 할 순 없지만요..

출처 -  ITWILLCAMPUS

iBatis 란?


iBatis란 ?

  • SQL 구문의 실행 결과를 객체에 매핑하는 Data Mapper
  • 테이블 구조가 복잡해지고 정규화되어 있지 않더라도 사용이 가능
  • 기존에 사용하던 SQL을 그대로 사용하므로 배우기가 쉽다.

중요한 것은 xml 을 이용하여 sql문을 호출하여서 메모리 캐쉬에 가지고 있다가
결과값을 자바 객체에 맵핑 시켜주는 방법으로 jdbc 코딩시 매번 코딩해주었던
부분들을 모두 줄일수 있고 메모리 또한 효율적으로 관리 할 수 있다.
framework를 사용함으로서 시스템 또한 가벼워질수 있다.

***sql-map-config.xml
<sqlMapConfig>

  <properties resource="jdbc.properties" />

  <settings 
    cacheModelsEnabled="true" 
    enhancementEnabled="true"
    lazyLoadingEnabled="true" 
    maxRequests="32" 
    maxSessions="10"
    maxTransactions="5" 
    useStatementNamespaces="false" />
  
  <typeAlias alias="Account" type="kr.or.openframework.domain.Account"/>
  <typeAlias alias="Family" type="kr.or.openframework.domain.AccountFamily"/>

  <transactionManager type="JDBC">
    <dataSource type="DBCP">
      <property name="JDBC.Driver"
        value="${mysql.jdbc.driverClassName}" />
      <property name="JDBC.ConnectionURL"
        value="${mysql.jdbc.url}" />
      <property name="JDBC.Username"
        value="${mysql.jdbc.username}" />
      <property name="JDBC.Password"
        value="${mysql.jdbc.password}" />
      <property name="JDBC.DefaultAutoCommit" value="true" />
    </dataSource>
  </transactionManager>

  <sqlMap resource="kr/or/openframework/dao/ibatis/MySQLAccount.xml" />
</sqlMapConfig>


이 파일을 통하여 jdbc에 연결하고 sql에서 사용하는 각종 설정들을 셋팅해준다
설정들의 셋팅 정의는 


Property Name비고
enhancementEnabled런타임시 바이트코드 향상을 가능하게 한다.
useStatementNamespacesql 호출시 namespace 사용 여부
maxRequest한꺼번에 SQL문을 수행할 수 있는 쓰레드의 수를 정의
maxSession주어진 시간동안 활성화될 수 있는 세션의 수
maxTransaction한꺼번에 SqlMapClient.startTransaction()에 들어갈 수 있는 쓰레드의 최대 갯수


***sql map 부분
<sql id="selectAccount_frag">
select
  acc_id,
  acc_first_name,
  acc_last_name,
  acc_email
from account
</sql>

<select id="selectAccountById" parameterClass="int" resultClass="Account">
<include refid="selectAccount_frag"/>
where acc_id = #id#
</select>

<insert id="insertAccount" parameterClass="Account">
insert into account (
  acc_id,
  acc_first_name,
  acc_last_name,
  acc_email
) values (
  #id#, #firstName#, #lastName#, #emailAddress#
)
</insert>

<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 id="deleteAccount" parameterClass="int">
delete from account
where acc_id = #id#
</delete>


****자바소스

private static SqlMapClient sqlMapper;

static {
  try {
    // log4j setting
    Properties configProps = new Properties();
    ClassLoader classLoader = ClassLoader.getSystemClassLoader();
    InputStream inputStream = classLoader.getResourceAsStream("log4j.xml");
    configProps.load(inputStream);     
    PropertyConfigurator.configure(configProps);

    // iBATIS SQLMaps setting
    Reader reader = Resources.getResourceAsReader("kr/or/openframework/dao/ibatis/SqlMapConfig.xml");
    sqlMapper = SqlMapClientBuilder.buildSqlMapClient(reader);
    reader.close();
  } catch (IOException e) {
    throw new RuntimeException("Something bad happened while building the SqlMapClient instance." + e, e);
  }
}

public static Account selectAccountById(int id) throws SQLException {
  return (Account) sqlMapper.queryForObject("selectAccountById", id);
}
public static String insertAccount(Account account) throws SQLException {
  sqlMapper.insert("insertAccount", account);
  return "SUCCESS";
}
public static String updateAccount(Account account) throws SQLException {
  sqlMapper.update("updateAccount", account);
  return "SUCCESS";
}

public static String deleteAccount(int id) throws SQLException {
  sqlMapper.delete("deleteAccount", id);
  return "SUCCESS";
}


이렇게 xml파일로 sql문을 생성하고 맵핑 시킨 상태에서
자바소스로 메소드 호출 하듯이 xml tag를 호출시켜서 결과 값을 객체에
맵핑 시킨다 . 때문에 자바소스에서 sql문이 없어졌고 불필요한 부분이
삭제된 간결한 코드가 완성 되었다

2012년 8월 12일

[iBatis] insert 한 데이터의 Key값 리턴 받기


iBatis 에서 insert 메서드를 사용하면, 값이 존재 여부와 상관없이
리턴 값이 "Null" 로 돌아온다.
(이 사실을 몰랐을때는.. 원인도 모르고 다 지우고 스크레치하게 다시 시작하고
 약 일주일을 이것만 찾느라 난리도 아니였다..)
아래 처럼 <selecKey> 를 통해서 Insert 할 때 사용한 마지막 UID (자동증가)
값을 반환한다. 이렇게 되면 쉽게 알수있겟지요?

--------------------------------------------------------------------------------------------

<insert id="insertRNote" parameterClass="RNote">
        INSERT INTO RNOTES (MEMO, CATEGORY, CDATE, UDATE, USERID)    
        VALUES(#memo#, #category#, #cDate#, #uDate#, #userId#)
<selectKey resultClass="int">
               SELECT LAST_INSERT_ID();
      </selectKey>
</insert>

---------------------------------------------------------------------------------------------

[iBATIS] iBATIS를 이용한 매우 간단한 예제


iBATIS를 이용해서 간단한 예제를 만들어봅시다.

웹이랑 섞으면 복잡하니까 콘솔에서 아주 간단하게 해보겠습니다-_-;

iBATIS를 들어보기만 하고 저처럼 어려울 것 같아서 거부하신분들에게 바칩니다-_-; 저는 처음에 상당히 어려울 줄 알았는데 공식홈페이지가니까 이동국님이 번역해 놓으신 문서가 있더라구요. 약간 이상하게(?) 번역해 놓긴 했지만 영어울렁증이 있는 저에게는 정말 도움이 되는 자료 였습니다 ^^

iBATIS공식홈페이지입니다.( 개발자 가이드와 튜토리얼 메뉴얼도 있습니다.)
for Java를 클릭하면 자바용이 나옵니다.
http://ibatis.apache.org/

접근하기 쉽게 하기 위해서 원더걸스멤버를 DB에 저장해놓고 해봅시다-_-;

[code]
CREATE TABLE `WONDERGIRLS` (
  `NUM` int(11) NOT NULL,
  `NAME` varchar(10) NOT NULL,
  `AGE` int(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=euckr;

INSERT INTO `WONDERGIRLS` (`NUM`, `NAME`, `AGE`) VALUES 
(1, '선예', 18),
(2, '선미', 15),
(3, '소희', 15),
(4, '예은', 18),
(5, '유빈', 99);
[/code]

사실 원더걸스가 이렇게 어린지 몰랐습니다-_-; 자 우선 넘어가고-_-;

이클립스를 실행하고 JAVA PROJECT로 프로젝트를 하나 만듭시다.
그리고 패키지를 jyp라고 해서 만듭시다-_-;
iBATIS lib파일인 ibatis-2.3.0.677.jar과 OracleJDBC를 LIB으로 추가합시다.

iBATIS를 사용하기 위한 설정파일을 구성해봅시다.
jyp에다가 new해서 xml파일을 하나 만듭시다. 이름은 SqlMapConfig.xml 이라고 합시다.

SqlMapConfig.xml
[code]
<?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>

 <properties resource="./jyp/SqlMapConfig.properties" />

 <settings
     cacheModelsEnabled="true"
     enhancementEnabled="true"
     lazyLoadingEnabled="true"
     maxRequests="32"
     maxSessions="10"
     maxTransactions="5"
     useStatementNamespaces="false" 
 />
    
 <transactionManager type="JDBC" >
    <dataSource type="SIMPLE">
      <property name="JDBC.Driver" value="${driver}" />
      <property name="JDBC.ConnectionURL" value="${url}" />
      <property name="JDBC.Username" value="${username}" />
      <property name="JDBC.Password" value="${password}" />
    </dataSource>
 </transactionManager>

 <sqlMap resource="./jyp/WonderGirls.xml" />
  
</sqlMapConfig>
[/code]
내용을 보면 환경을 설정하고 JDBC와 연결하기 위한 작업을 하는 듯 합니다. JDBC연결작업은 SIMPLE이라고 되어있는데 DBCP로도 됩니다. 메뉴얼에 보시면 개발자가이드 부분에 보면 하는 법이 있습니다.
그리고 마지막에 sqlMap의 resource를 WonderGirls.xml을 추가해놨는데요 차후 설명하겠습니다.

그다음에 저기 JDBC설정에 ${driver}등 변수형식으로 되어있는데 맨위에 properties파일을 하나 설정한게 있는데 저기에 정의 하면 됩니다.

SqlMapConfig.properties
[code]
driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@127.0.0.1:1521:XE
username=MUDCHOBO
password=1234
[/code]
오라클은 저렇게 하면 되구요. mysql은 mysql에 맞게 바꾸면 돼요.
만약 한 프로그램에서 여러개의 db를 접근한다면 저 파일들을 또 만들면 되겠죠?

그 다음 클래스를 하나 만듭시다. MyAppSqlmapConfig라는 클래스를 만듭시다.
[code]
package jyp;

import java.io.Reader;

import com.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;

public class MyAppSqlMapConfig {

 private static final SqlMapClient sqlMap;

 static {
  try {
   String resource = "./jyp/SqlMapConfig.xml";
   Reader reader = Resources.getResourceAsReader(resource);
   sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);
  } catch (Exception e) {
   e.printStackTrace();
   throw new RuntimeException("Error initializing class. Cause:" + e);
  }
 }

 public static SqlMapClient getSqlMapInstance() {
  return sqlMap;
 }
}
[/code]
방금 설정한 설정파일을 이용해서 sqlMapClient를 만드는 듯 합니다. 저 sqlMap객체를 통해서 db에 접근할 수 있는 듯 합니다. 저도 잘은 모르겠네요 ^^

원더걸스 getter, setter를 만들어 봅시다. WonderGirls라는 이름으로 클래스를 만듭니다.
WonderGirls.java
[code]
package jyp;

public class WonderGirls {

 private int num;
 private String name;
 private int age;

 public int getNum() {
  return num;
 }
 public void setNum(int num) {
  this.num = num;
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public int getAge() {
  return age;
 }
 public void setAge(int age) {
  this.age = age;
 }
}
[/code]
이제 가장 중요한 부분인 Wondergirls에 관련된 sqlMap을 작성해봅시다.
이름은 아까 정의한 WonderGirls.xml파일로 만듭시다.
[code]
<?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="WonderGirls">
  
 <resultMap id="WondergirlsResult" class="jyp.WonderGirls">
  <result column="NUM" property="num" />
  <result column="NAME" property="name" />
  <result column="AGE" property="age" />
 </resultMap>

 <select id="getWondergirls" resultMap="WondergirlsResult">
  SELECT NUM, NAME, AGE
  FROM WONDERGIRLS
  ORDER BY NUM
 </select>

 <select id="selectWondergirl" parameterClass="Integer" 
             resultClass="jyp.WonderGirls">
  SELECT NUM, NAME, AGE
  FROM WONDERGIRLS
  WHERE NUM = #num#
 </select>

 <insert id="insertWondergirl" parameterClass="jyp.WonderGirls">
  INSERT INTO
  WONDERGIRLS (NUM, NAME, AGE)
  VALUES (#num#, #name#, #age#)
 </insert>

 <update id="updateWondergirl" parameterClass="java.util.Map">
  UPDATE WONDERGIRLS SET
  NAME = #name#,
  AGE = #age#
  WHERE NUM = #num# 
 </update>

 <delete id="deleteWondergirl" parameterClass="Integer">
  DELETE FROM WONDERGIRLS
  WHERE NUM = #num#
 </delete>

</sqlMap>
[/code]
sql문을 xml로 뺐습니다. 나중에 고칠 때 편할 듯 싶네요. 
sql이 총 5가지가 있네요. 
전체리스트가져오기, 멤버번호받아서 한명멤버정보 가져오기, 멤버추가하기, 멤버수정하기, 멤버삭제하기

select해서 List를 가져올 때에는 원래 자동맵핑이 되서 알아서 가져오지만 그래도 명시적으로 맵핑을 해줘야돼요. 그래서 resultMap태그를 이용해서 명시해준뒤에 select를 선언해서 그 resultMap의 id를 resultMap속성값에 넣어주면 됩니다.
insert할 때에도 WonderGirls클래스형으로 받아서 넣어주면 되구요.
update할 때 좀 틀린게 parameterClass를 Map으로 선언합니다. 이름, 나이, 번호를 각각 객체로 받아서 Map에 저장한 것을 받아서 사용하는 것이죠.
delete할 때에는 Integer클래스형으로 숫자하나 받아서 해당 멤버를 지우게 됩니다.

이번엔 DAO를 만들어봅시다. WondergirlsDao라는 이름의 클래스를 만들어봅시다.
[code]
package jyp;

import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import com.ibatis.sqlmap.client.SqlMapClient;

public class WondergirlsDao {

 @SuppressWarnings("unchecked")
 public void viewMember(SqlMapClient sqlMap) throws SQLException {
  List<WonderGirls> wonderGirlsList = (List<WonderGirls>) sqlMap
    .queryForList("getWondergirls");
  for (int i = 0; i < wonderGirlsList.size(); i++) {
   WonderGirls wonderGirl = (WonderGirls) wonderGirlsList.get(i);
   System.out.print("번호 : " + wonderGirl.getNum());
   System.out.print("   이름 : " + wonderGirl.getName());
   System.out.println("   나이 : " + wonderGirl.getAge());
  }
 }

 public void insertMember(SqlMapClient sqlMap, WonderGirls wonderGirls) 
    throws SQLException {  
  sqlMap.insert("insertWondergirl", wonderGirls);
  System.out.println("추가에 성공했습니다.");
 }

 public void modifyMember(SqlMapClient sqlMap, Map<String, Object> map) 
    throws SQLException {
  sqlMap.update("updateWondergirl", map);
  System.out.println("수정에 성공했습니다.");
 }

 public void deleteMember(SqlMapClient sqlMap, int num) throws IOException,
   SQLException {
  sqlMap.delete("deleteWondergirl", num);
  System.out.println("삭제에 성공했습니다.");
 }

 public boolean validateMember(SqlMapClient sqlMap, int num) throws SQLException {
  WonderGirls wonderGirls = 
   (WonderGirls) sqlMap.queryForObject("selectWondergirl", num);
  
  if (wonderGirls == null) {
   return false;
  }
  return true;
 }
}
[/code]
DAO를 보면 이상하게 간단합니다. 위에 xml에 다 쿼리를 선언해줬기때문에 그냥 파라메터만 넘겨주면 됩니다. 
List보기는 sqlMap.queryForList("getWondergirls"); getWondergirls는 위에 선언한 쿼리의 id입니다.
insert할 때에는 객체를 받아서 넘겨주고, 수정할 때에는 Map을 넘겨주고, 삭제 할때에는 숫자를 넘겨주면 됩니다.
아 간단해요. 한줄이면 끝나요-_-; 
예전에 Connection을 close()안해줬더니 서버가 다운되려고 한 경험이 있는데 이런일은 절대 없을 것 같군요.

이제 main함수를 작성해봅시다. 이름은 WondergirlsApplication으로 해봅시다.
public static void main(String[] args)에 체크해주시는 것 잊지 마시구요-_-;
WondergirlsApplication.java
[code]
package jyp;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import com.ibatis.sqlmap.client.SqlMapClient;

public class WondergirlsApplication {

 public static void main(String[] args) throws SQLException, IOException {

  BufferedReader bufferedReader = new BufferedReader(
    new InputStreamReader(System.in));
  SqlMapClient sqlMap = MyAppSqlMapConfig.getSqlMapInstance();
  WondergirlsDao wondergirlsDao = new WondergirlsDao();
  WonderGirls wonderGirls = new WonderGirls();
  
  Integer age, num;
  String name;
  
  while (true) {
   try {
    System.out.println("\n1.멤버출력\n2.멤버추가\n3.멤버수정\n4.멤버삭제\n5.종료");
    System.out.print("--> ");
    String temp = bufferedReader.readLine();
    int MenuNum = Integer.parseInt(temp);
    switch (MenuNum) {
    case 1:
     wondergirlsDao.viewMember(sqlMap);
     break;
     
    case 2:
     wonderGirls = new WonderGirls();
     System.out.print("번호을 입력하세요 : ");
     wonderGirls.setNum(Integer.parseInt(bufferedReader.readLine()));
     System.out.print("이름을 입력하세요 : ");
     wonderGirls.setName(bufferedReader.readLine());
     System.out.print("나이을 입력하세요 : ");
     wonderGirls.setAge(Integer.parseInt(bufferedReader.readLine()));
     wondergirlsDao.insertMember(sqlMap, wonderGirls);
     break;
     
    case 3:
     Map<String, Object> map = new HashMap<String, Object>(3);

     System.out.print("수정할 번호을 입력하세요 : ");
     num = new Integer(Integer.parseInt(bufferedReader.readLine()));
     if (!wondergirlsDao.validateMember(sqlMap, num)) {
      System.out.println("없는 멤버번호입니다.");
      break;
     }
     System.out.print("이름을 입력하세요 : ");
     name = bufferedReader.readLine();
     System.out.print("나이을 입력하세요 : ");
     age = new Integer(Integer.parseInt(bufferedReader.readLine()));

     map.put("num", num);
     map.put("name", name);
     map.put("age", age);
     wondergirlsDao.modifyMember(sqlMap, map);
     break;
     
    case 4:
     System.out.print("삭제할 멤버번호를 입력하세요 : ");
     num = Integer.parseInt(bufferedReader.readLine());
     if (!wondergirlsDao.validateMember(sqlMap, num)) {
      System.out.println("없는 멤버번호입니다.");
      break;
     }
     wondergirlsDao.deleteMember(sqlMap, num);
     break;
     
    case 5:
     System.exit(0);
     
    default:
     System.out.println("1~5중에서 선택하세요!");
     break;
    }
   } catch (NumberFormatException e) {
    System.out.println("잘못 입력했습니다. 다시 입력하세요");
   }
  }
 }
}
[/code]
자세히 보시면 뭐 별거없는데 거창하게 만들어놨군요(제가 좀 허접해서-_-) 아 참고로 예외처리 잘 안해놨으니 알아서 버그많아요 알아서 보세요-_-;

1번은 멤버 리스트를 가져오는군요.
[code]
1.멤버출력
2.멤버추가
3.멤버수정
4.멤버삭제
5.종료
--> 1
번호 : 1   이름 : 선예   나이 : 18
번호 : 2   이름 : 선미   나이 : 15
번호 : 3   이름 : 소희   나이 : 15
번호 : 4   이름 : 예은   나이 : 18
번호 : 5   이름 : 유빈   나이 : 5

1.멤버출력
2.멤버추가
3.멤버수정
4.멤버삭제
5.종료
--> 
[/code]
2번은 멤버를 추가하는데 추가해봅시다-_-;
[code]
1.멤버출력
2.멤버추가
3.멤버수정
4.멤버삭제
5.종료
--> 2
번호을 입력하세요 : 6
이름을 입력하세요 : 성종천
나이을 입력하세요 : 25
추가에 성공했습니다.

1.멤버출력
2.멤버추가
3.멤버수정
4.멤버삭제
5.종료
--> 1
번호 : 1   이름 : 선예   나이 : 18
번호 : 2   이름 : 선미   나이 : 15
번호 : 3   이름 : 소희   나이 : 15
번호 : 4   이름 : 예은   나이 : 18
번호 : 5   이름 : 유빈   나이 : 5
번호 : 6   이름 : 성종천   나이 : 25

1.멤버출력
2.멤버추가
3.멤버수정
4.멤버삭제
5.종료
--> 
[/code]
아 멤버가 추가되었어요-_-; (이거 욕먹겠군요-_-;) 
멤버를 수정해봅시다. 유빈양의 나이가 잘못 되었으니 수정해봅시다.
[code]
1.멤버출력
2.멤버추가
3.멤버수정
4.멤버삭제
5.종료
--> 3
수정할 번호을 입력하세요 : 5
이름을 입력하세요 : 유빈
나이을 입력하세요 : 20
수정에 성공했습니다.

1.멤버출력
2.멤버추가
3.멤버수정
4.멤버삭제
5.종료
--> 1
번호 : 1   이름 : 선예   나이 : 18
번호 : 2   이름 : 선미   나이 : 15
번호 : 3   이름 : 소희   나이 : 15
번호 : 4   이름 : 예은   나이 : 18
번호 : 5   이름 : 유빈   나이 : 20
번호 : 6   이름 : 성종천   나이 : 25

1.멤버출력
2.멤버추가
3.멤버수정
4.멤버삭제
5.종료
--> 
[/code]
아.... 유빈양이 제일 마지막에 들어왔는데 나이가 제일 많군요-_-;
그리고 이제 말도 안되는 성종천이라는 멤버를 지워봅시다-_-;
[code]
1.멤버출력
2.멤버추가
3.멤버수정
4.멤버삭제
5.종료
--> 4
삭제할 멤버번호를 입력하세요 : 6
삭제에 성공했습니다.

1.멤버출력
2.멤버추가
3.멤버수정
4.멤버삭제
5.종료
--> 1
번호 : 1   이름 : 선예   나이 : 18
번호 : 2   이름 : 선미   나이 : 15
번호 : 3   이름 : 소희   나이 : 15
번호 : 4   이름 : 예은   나이 : 18
번호 : 5   이름 : 유빈   나이 : 20

1.멤버출력
2.멤버추가
3.멤버수정
4.멤버삭제
5.종료
--> 
[/code]

출처 - 머드초보의 블로그