Spring กับ iBatisDao ภาค2

January 23rd, 2009 by roofimon Leave a reply »

ต่อจากตอนที่แล้วเราพบว่าทำไม mothod ใน DAO มันเยอะจังก็อย่าเพิ่งไปสนใจมากครับเพราะเพื่อความยืดหยุ่นเราจะสร้างมันไว้ก่อนนอกจากนี้ยังทะลึ่งมี พวกที่ลงท้าย
ด้วย Expression อีก method ที่ลงท้ายด้วย Expression นั้นจะเป็นพวกสร้าง Dynamic Query ทั้งหลายยกตัวอย่างเช่นผมต้องการสร้าง

SELECT * FROM USERS WHERE USERS.USR_ID LIKE '%username%'

แทนที่จะต้องไปสร้าง

<select> ... </select>

ใหม่เราก็สร้างเป็น dynamic block ก่อนหน้าตาเป็นแบบนี้

  <sql id="Where_Clause" >
    <iterate property="oredCriteria" conjunction="or" prepend="where" removeFirstPrepend="iterate" >
      <isEqual property="oredCriteria[].valid" compareValue="true" >
        (
        <iterate prepend="and" property="oredCriteria[].criteriaWithoutValue" conjunction="and" >
          $oredCriteria[].criteriaWithoutValue[]$
        </iterate>
        <iterate prepend="and" property="oredCriteria[].criteriaWithSingleValue" conjunction="and" >
          $oredCriteria[].criteriaWithSingleValue[].condition$
            #oredCriteria[].criteriaWithSingleValue[].value#
        </iterate>
        <iterate prepend="and" property="oredCriteria[].criteriaWithListValue" conjunction="and" >
          $oredCriteria[].criteriaWithListValue[].condition$
          <iterate property="oredCriteria[].criteriaWithListValue[].values" open="(" close=")" conjunction="," >
            #oredCriteria[].criteriaWithListValue[].values[]#
          </iterate>
        </iterate>
        <iterate prepend="and" property="oredCriteria[].criteriaWithBetweenValue" conjunction="and" >
          $oredCriteria[].criteriaWithBetweenValue[].condition$
          #oredCriteria[].criteriaWithBetweenValue[].values[0]# and
          #oredCriteria[].criteriaWithBetweenValue[].values[1]#
        </iterate>
        )
      </isEqual>
    </iterate>
  </sql>

จากนนั้นเราจะทำการไปสร้าง

<select> ... </select>

แบบ dynamic ขึ้นมาหน้าตาเป็นแบบนี้ครับ

  <select id="Users_selectByExpression" resultMap="UsersResult" parameterClass="com.spring66.tutorial.model.UsersExpression" >
    select USR_ID, USR_NAME, USR_PWD, USR_LEVEL, USR_FIRST_LOGIN, REG_DATE, LOG_DATE
    from users
    <isParameterPresent >
      <include refid="Where_Clause" />
      <isNotNull property="orderByClause" >
        order by $orderByClause$
      </isNotNull>
    </isParameterPresent>
  </select>

เพียงเท่านี้เราก็สามารถเขียน Dynamic SQL ได้จาก Java Code เลยครับยกตัวอย่างเช่น

	UsersExpression usrEx = new UsersExpression();
        	usrEx.createCriteria().andUsrNameLike("%user%").andUsrIdEqualTo("1");

ได้เรื่อยๆครับซึ่งนี่เป็นหนึ่งในหลายๆวิธีที่เราสามารถสร้าง Dynamic SQL ได้โดยจุดนี้ถือเป็นจุดแข็งอีกเรื่องของ iBatis เพราะไม่ต้องปรับ skill มากแค่มีความรู้เรื่อง SQL ก็สามารถ
เดา code ได้เกือบทั้งหมดแล้วครับ โอเคต่อไปหลังจากสร้าง DAO แล้วอาการแดงเถือกจะหายไปต่อไปเราจะลอง เรียก test แล้วครับ และแน่นอนโดนด่าแน่นอนเพราะไม่มี bean ชื่อ
นี้ดังนั้น ให้ไวครับเขียน implementation คลาสของ interface ที่เราเพิ่งสร้างขึ้นมา

package com.spring66.tutorial.dao.ibatis;

import com.spring66.tutorial.dao.UsersDao;
import com.spring66.tutorial.model.Users;
import com.spring66.tutorial.model.UsersExpression;
import java.util.List;
import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;

public class IbatisUsersDao extends SqlMapClientDaoSupport implements UsersDao {
    public IbatisUsersDao() {
        super();
    }
    public void insert(Users record) {
        getSqlMapClientTemplate().insert("Users_insert", record);
    }
    public int updateByPrimaryKey(Users record) {
        int rows = getSqlMapClientTemplate().update("Users_updateByPrimaryKey", record);
        return rows;
    }
    public int updateByPrimaryKeySelective(Users record) {
        int rows = getSqlMapClientTemplate().update("Users_updateByPrimaryKeySelective", record);
        return rows;
    }
    public List selectByExpression(UsersExpression example) {

        List list = getSqlMapClientTemplate().queryForList("Users_selectByExpression", example);
        return list;
    }
    public Users selectByPrimaryKey(String usrId) {
        Users key = new Users();
        key.setUsrId(usrId);
        Users record = (Users) getSqlMapClientTemplate().queryForObject("Users_selectByPrimaryKey", key);
        return record;
    }
    public int deleteByExpression(UsersExpression example) {
        int rows = getSqlMapClientTemplate().delete("Users_deleteByExpression", example);
        return rows;
    }
    // some other methods
    }
}

จะเห็นว่าคลาสนี้ extends มาจาก SqlMapClientDaoSupport แล้วเอ๊ะไอ้คลาสนี้มาจากไหนจริงๆแล้ว Spring เตรียมเครื่องมือที่ช่วยให้เราใช้ iBatis ได้สะดวกมากขึ้นไว้ให้แล้ว
ซึ่งการใช้ Template คลาสพวกนี้จะช่วยให้เราทำงานกับ ORM ต่างๆได้สะดวกมากขึ้นเพราะโดยปกติแล้วการใช้งาน ORM จะต้องมีการเขียน code ที่เป็น overhead เยอะพอสมควร
ดังนั้น สิ่งต่อไปที่เราต้องทำคือ ต้องสร้าง bean ใหม่ขึ้นมาหนึ่งตัวเพื่อใช้ระบุค่า configuration พื้นฐานต่างๆของ iBatis ดังนี้

<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">

	<property name="configLocation" value="classpath:sqlmap-config.xml"/>

	<property name="dataSource" ref="dataSource"/>

</bean>

พรอพเพอตี้ตัวแรก configLocation เป็นที่ที่เราใช้เก็บ sqlmap-config ซึ่งเป็นที่ระบุว่า mapping file ของเราอยู่ที่ใดและมีกี่ไฟล์ที่ถูกใช้งานอยู่

<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">

	<property name="configLocation" value="classpath:sqlmap-config.xml"/>

	<property name="dataSource" ref="dataSource"/>

</bean>

ของเรามีตารางเดียวครับ ดังนั้นเราก็จะระบุลงไปใน sqlmap-cinfig.xml ดังนี้

<sqlMapConfig>

	<sqlMap resource="ibatis/users.xml"/>

</sqlMapConfig>

พรอพเพอตี้ตัวต่อไปคือ dataSource ก็คือเราจะต่อกับระบบฐานข้อมูลด้วย Connection ไหนต่อไปก็ทำการเพิ่ม Dao ของเราเข้าไปในระบบพร้อมทั้งระบุด้วยว่าเราจะขอใช้ sqlMapClient

<bean id="usersDao" class="com.spring66.tutorial.dao.ibatis.IbatisUsersDao">

	<property name="sqlMapClient" ref="sqlMapClient"/>

</bean>

จากตรงนี้เราจะเห็นได้ว่า ทุกครั้งที่เราต้องการเรียกใช้ sqlMapClient เราก็แค่เรียกมัน ไม่ต้องมานั้ง new ให้เมื่อยตุ้มครับ ถึงตรงนี้ทุกอย่างน่าจะครบแล้วก็ run test เลยครับ แน่นอน หล่อ

Advertisement

2 comments

  1. ไม่เข้าใจตรง Dynamic block เลยครับ เข้าไปอ่านใน doc ของ ibatis แล้วก็ยังไม่เข้าใจ

  2. Sand says:

    ของ stop ibatis ไว้แต่เพียงเท่านี้ กลับไป hibernate ดีกว่า

Leave a Reply

You must be logged in to post a comment.