목차 >> Data Access Object(DAO)  
+- GlueGenericDao  
+- GlueJdbcDao  
+- GlueMyBatisDao  
----+- Mapper XML 파일  
----+- Parameters/Result Maps  
----+- GlueParameter  
----+- Audit Data 처리  
----+- Reuse Activity

6장 Data Access Object(DAO)

GlueMyBatisDao

GlueMyBatisDao는 Mybatis를 이용해서 추상화된 CRUD 오퍼레이션을 사용할 수 있는 Database Access Object 구현체입니다. GlueGenericDao를 상속받아 구현된 Dao클래스로 데이타베이스 CRUD(Create, Read, Update, Delete) 작업을 수행하는 Method를 제공합니다.
본 가이드에서는 Glue와 MyBatis 연계 관련된 기본적이 내용에 대해서만 다룰 것이므로, MyBatis에 대한 자세한 내용은 MyBatis공식 사이트의 매뉴얼을 참고하시기 바랍니다.
영문 사이트
한글 사이트

그림 : GlueMybatisDao
GlueMybatisDao
그림 : GlueMyBatisDao의 bean들과의 관계
GlueMyBatisDao의 bean들과의 관계

GlueMybatisDao를 사용하기 위해서는 설정파일(applicationContext.xml)에 SqlSessionFactoryBean, SqlSessionTemplate를 필요로 합니다.

  • SqlSessionFactory Bean : MyBatis에서는 SqlSessionFactoryBuilder 클래스를 사용하여 session factory를 생성하는데 MyBatis-Spring은 SqlSessionFactoryBuilder 클래스 대신 SqlSessionFactoryBean 클래스를 사용하여 생성합니다. SqlSessionFactoryBean은 dataSource, mapperLocation property를 통해, JDBC DataSource정보와 MyBatis mapper 파일(쿼리 파일)의 위치를 지정합니다.
  • SqlSession Bean : SqlSessionTemplate 클래스는 MyBatis-Spring의 핵심 기능이며 MyBatis SqlSessions 관리 및 MyBatis SQL method 호출을 담당합니다. SqlSessionTemplate 클래스는 SqlSessionFactory를 생성자의 인자로 받을수 있습니다.

다음은 설정파일(applicationContext.xml)의 일부입니다.

<bean id="dao-1" class="com.poscoict.glueframework.dao.mybatis.GlueMybatisDao">
    <property name="sqlSession" ref="sqlSession-1" />
</bean>
<bean id="sqlSession-1" class="org.mybatis.spring.SqlSessionTemplate">
    <constructor-arg index="0" ref="sqlSessionFactory-1" />
</bean>
<bean id="sqlSessionFactory-1" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource-1" />
    <property name="mapperLocations" value="classpath*:mybatis/mapper/*.xml" />
</bean>
<bean id="dataSource-1" class= . . ./>

<bean id="dao-2" class="com.poscoict.glueframework.dao.mybatis.GlueMybatisDao">
    <property name="sqlSession" ref="sqlSession-2" />
</bean>
<bean id="sqlSession-2" class="org.mybatis.spring.SqlSessionTemplate">
    <constructor-arg index="0" ref="sqlSessionFactory-2" />
</bean>
<bean id="sqlSessionFactory-2" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource-2" />
    <property name="mapperLocations" value="classpath*:mybatis/mapper/*.xml" />
</bean>
<bean id="dataSource-2" class= . . ./>

<bean id="transactionManager-1" 
      class="com.poscoict.glueframework.transaction.GlueDataSourceTransactionManager">
    <property name="dataSource" ref="dataSource-1"/>
</bean>
<bean id="transactionManager-2" 
      class="com.poscoict.glueframework.transaction.GlueDataSourceTransactionManager">
    <property name="dataSource" ref="dataSource-2"/>
</bean>

Mapper XML 파일

Mybatis Mapper XML(쿼리 파일) 은 SqlSessionFactoryBean 의 mapperLocations에 정의된 Path에 Mybatis 쿼리를 정의 합니다. Mapper XML(SQL Map XML) 파일은 First Class(첫번째 요소)만을 갖습니다.
다음은 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="emp.mapper">
    <select id="getEmp" parameterType="String" 
                        resultType="sample.vo.EmpVO">
        select * from EMP where DEPTNO=#{deptno}
    </select>
    <select id="getEmp2" parameterType="sample.vo.DeptVO" 
                         resultType="sample.vo.EmpVO">
        select * from EMP where DEPTNO=#{deptno}
    </select>
    <select id="getEmp3" parameterType="sample.vo.EmpVO" 
                         resultType="sample.vo.EmpVO">
        select * from EMP where DEPTNO=#{deptno} and sal>#{sal}
    </select>
    <select id="getDept" resultType="sample.vo.DeptVO">
        select * from DEPT
    </select>
    <delete id="deleteEmp" parameterType="sample.vo.EmpVO">
        delete from EMP where EMPNO=#{empno}
    </delete>
    <insert id="insertEmp" parameterType="sample.vo.EmpVO">
        insert into EMP(EMPNO, ENAME, SAL, DEPTNO)
        values(#{empno}, #{ename}, #{sal}, #{deptno})
    </insert>
    <update id="updateEmp" parameterType="sample.vo.EmpVO">
        update EMP
        set SAL=#{sal}, ENAME=#{ename}
        where EMPNO=#{empno}
    </update>
</mapper>

select 구문은 MyBatis 에서 가장 흔히 사용할 요소로 데이터베이스에서 데이터를 가져오는 기능을 수행합니다. 아마도 대부분의 애플리케이션은 데이터를 수정하기보다는 조회하는 기능을 많이 가질 것입니다. 그래서 MyBatis 는 데이터를 조회하고 그 결과를 매핑하는데 집중하고 있습니다.
select 는 다음 예처럼 단순한 경우에는 단순하게 설정됩니다.

<select id="selectPerson" parameterType="int" resultType="hashmap">
  SELECT * FROM PERSON WHERE ID = #{id}
</select>

이 구문의 이름은 selectPerson 이고 int 타입의 파라미터를 가집니다. 그리고 결과 데이터는 HashMap 에 저장됩니다. 파라미터 표기법은 다음과 같습니다.

#{id}

이 표기법은 MyBatis 에게 PreparedStatement 파라미터를 만들도록 지시합니다. JDBC 를 사용할 때 PreparedStatement 에는 “?” 형태로 파라미터가 전달됩니다. 즉 결과적으로 위 설정은 아래와 같이 작동하게 되는 셈입니다.

String selectPerson = "SELECT * FROM PERSON WHERE ID=?";
PreparedStatement ps = conn.prepareStatement(selectPerson);
ps.setInt(1,id);

데이터를 변경하는 구문인 insert, update, delete 는 Mapper XML 예제와 같이 매우 간단합니다.

Parameters/Result Maps

First Class(첫번째 요소) 인 select, insert, update, delete 는 parameterType 속성을 갖고 select는 resultType 속성도 갖습니다. 이러한 속성의 값은 패키지 경로를 포함한 전체 클래스명이 사용됩니다.
Mapper XML 예제에서는 sample.vo.EmpVO와 sample.vo.DeptVO를 보았을 것이며, 이러한 클래스는 자바빈 형태의 VO 클래스로써, 프로퍼티와 getter setter 메소드로 구성됩니다.
다음은 sample.vo.DeptVO 예입니다.

package sample.vo;
public class DeptVO {
    private String deptno;
    private String dname;
    private String loc;
    public String getDeptno() {
        return deptno;
    }
    public void setDeptno( String deptno ) {
        this.deptno = deptno;
    }
    public String getDname() {
        return dname;
    }
    public void setDname( String dname ) {
        this.dname = dname;
    }
    public String getLoc() {
        return loc;
    }
    public void setLoc( String loc ) {
        this.loc = loc;
    }
}

다음은 sample.vo.EmpVO 예입니다.

package sample.vo;
import java.util.Date;
public class EmpVO {
    private Long empno;
    private String ename;
    private String job;
    private Long mgr;
    private Date hiredate;
    private Long sal;
    private Long comm;
    private Long deptno;
    public Long getEmpno() {
        return empno;
    }
    public void setEmpno( Long empno ) {
        this.empno = empno;
    }
    public String getEname() {
        return ename;
    }
    public void setEname( String ename ) {
        this.ename = ename;
    }
    public String getJob() {
        return job;
    }
    public void setJob( String job ) {
        this.job = job;
    }
    public Long getMgr() {
        return mgr;
    }
    public void setMgr( Long mgr ) {
        this.mgr = mgr;
    }
    public Date getHiredate() {
        return hiredate;
    }
    public void setHiredate( Date hiredate ) {
        this.hiredate = hiredate;
    }
    public Long getSal() {
        return sal;
    }
    public void setSal( Long sal ) {
        this.sal = sal;
    }
    public Long getComm() {
        return comm;
    }
    public void setComm( Long comm ) {
        this.comm = comm;
    }
    public Long getDeptno() {
        return deptno;
    }
    public void setDeptno( Long deptno ) {
        this.deptno = deptno;
    }
}

GlueParameter

GlueMyBatisDao의 실행하고자 하는 Mapped SQL Statement가 input parameter값을 필요로 한다면, GlueParameter를 통해 그 값을 전달합니다. select, insert, update, delete 구분에 parameterType를 근거로 GlueParameter를 생성합니다.
Mapped SQL Statement가 다음과 같다면, GlueParameter는 다음과 같이 생성할 수 있습니다.

<select id="getEmp" parameterType="String" resultType="sample.vo.EmpVO">
    select * from EMP where DEPTNO=#{deptno}
</select>
GlueParameter<String> param = new GlueParameter<String>();
param.setParameter( "10" );

Mapper SQL Statement 의 parameterType이 다음과 같다면, GlueParameter는 다음과 같이 생성할 수 있습니다. EmpVO는 Parameters/Reulst Maps 장의 예제와 같습니다.

<select id="getEmp3" parameterType="sample.vo.EmpVO" resultType="sample.vo.EmpVO">
    select * from EMP where DEPTNO=#{deptno} and sal>#{sal}
</select>
GlueParameter<EmpVO> param = new GlueParameter<EmpVO>();
EmpVO empvo = new EmpVO();
empvo.setDeptno( (long) 10 );
empvo.setSal( (long) 10 );
param.setParameter( empvo );

Audit Data 처리

GlueMyBatisDao 사용시 Audit Data 처리는 GlueJdbcDaoAudit Data 처리 부분을 참고해서 glue.properties를 설정합니다.

  • glue.properties
    audit.insert.key=create_id,create_ip,create_dt#current_timestamp#,update_id,update_ip,update_dt#current_timestamp#
    audit.update.key=update_id,update_ip,update_dt#current_timestamp#
    
  • SQL (Mapper XML 파일) : glue.properties 에 지정한 name과 일치 되도록 합니다.
    <insert id="insertEmp" parameterType="sample.vo.EmpAuditVO">
        insert into EMP_AUDIT(
            EMPNO, ENAME, SAL, DEPTNO, CREATE_ID, CREATE_IP, CREATE_DT, UPDATE_ID, UPDATE_IP, UPDATE_DT
        )values(
            #{empno}, #{ename}, #{sal}, #{deptno}, 
            #{create_id}, #{create_ip}, #{create_dt}, #{update_id}, #{update_ip}, #{update_dt} 
        )
    </insert>
    
  • Java Code : GlueParameter의 setAuditAttributes()를 사용합니다.
    Map paramMap = new HashMap();
    paramMap.put("empno", . . .);
    paramMap.put("ename", . . .);
    paramMap.put("sal", . . .);
    paramMap.put("deptno", . . .);
    GlueParameter<Map> param = new GlueParameter<Map>(args);
    param.setAuditAttributes( audit );
    
    GlueGenericDao  dao = . . .
    dao.insert("insertEmp", param);
    
  • Reuse Activity : is-audit property를 사용합니다.
    <activity name="Insert" class="com.poscoict.glueframework.biz.activity.mybatis.GlueMybatisInsert">
        <property name="dao" value=". . ." />
        <property name="sql-key" value="insertEmp" />
        <property name="param-bindings" value="empno=EMPNO|ename=ENAME|sal=SAL|deptno=DEPTNO" />
        <property name="is-audit" value="true" />
        <transition name="success" value=". . ." />
    </activity>
    

Reuse Activity

GlueMyBatisDao를 사용한 reuse Activity는 다음과 같은 것이 제공되고 있습니다.

  • com.poscoict.glueframework.biz.activity.mybatis.GlueMybatisDelete
  • com.poscoict.glueframework.biz.activity.mybatis.GlueMybatisInsert
  • com.poscoict.glueframework.biz.activity.mybatis.GlueMybatisModify
  • com.poscoict.glueframework.biz.activity.mybatis.GlueMybatisSearch