iBATIS介紹及簡單示例

 轉帖來自:http://www.topxp.org/ac_402881e418e91fd10118e92970ce0002.html

介紹

iBATIS是以SQL爲中心的持久化層框架。能支持懶加載、關聯查詢、繼承等特性。

iBATIS不同於一般的OR映射框架。OR映射框架,將數據庫表、字段等映射到類、屬性,那是一種元數據(meta-data)映射。iBATIS則是將SQL查詢的參數和結果集映射到類。

 

所以,iBATIS做的是SQL Mapping的工作。

 

它把SQL語句看成輸入以及輸出,結果集就是輸出,而where後面的條件參數則是輸入。iBATIS能將輸入的普通POJO對象、MapXML等映射到SQL的條件參數上,同時也可以將查詢結果映射到普通POJO對象(集合)、MapXML等上面。

 

iBATIS使用xml文件來映射這些輸入以及輸出。

 

簡單示例

基於ibatis-2.3.0.677版本。

1、  創建新的項目,並引入jar

a)         ibatis-2.3.0.677.jar

b)        mysql驅動

2、  在類路徑中提供ibatis的配置文件: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>

 

  <transactionManager type="JDBC">

    <dataSource type="SIMPLE">

      <property name="JDBC.Driver" value="com.mysql.jdbc.Driver"/>

      <property name="JDBC.ConnectionURL" value="jdbc:mysql://127.0.0.1/ibatis"/>

      <property name="JDBC.Username" value="root"/>

      <property name="JDBC.Password" value="root"/>

    </dataSource>

  </transactionManager>

  <sqlMap resource="com/bjsxt/ibatis/User.xml"/>

 

</sqlMapConfig>

 

 

3、創建實體類:User.java

package com.bjsxt.ibatis;

 

public class User {

    private int id;

    private String username;

    private String password;

   

    public int getId() {

       return id;

    }

    public void setId(int id) {

       this.id = id;

    }

    public String getUsername() {

       return username;

    }

    public void setUsername(String username) {

       this.username = username;

    }

    public String getPassword() {

       return password;

    }

    public void setPassword(String password) {

       this.password = password;

    }

}

 

 

4、創建針對User對象的CRUDxml映射配置:User.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>

 

  <!-- Use type aliases to avoid typing the full classname every time. -->

  <typeAlias alias="User" type="com.bjsxt.ibatis.User"/>

 

  <!-- Select with no parameters using the result map for Account class. -->

  <select id="selectAllUsers" resultClass="User">

    select * from t_user

  </select>

 

  <select id="selectUser" resultClass="User" parameterClass="int">

    select * from t_user where id=#id#

  </select>

 

  <insert id="insertUser" parameterClass="User">

    insert into t_user values (

        null,#username#,#password#

    )

  </insert>

 

  <update id="updateUser" parameterClass="User">

    update t_user set username = #username#,password=#password#

    where id=#id#

  </update>

 

  <delete id="deleteUser" parameterClass="int">

    delete from t_user where id=#id#

  </delete>

</sqlMap>

 

 

5、創建測試程序測試:

package com.bjsxt.ibatis;

 

import java.io.Reader;

import java.util.Iterator;

import java.util.List;

 

import junit.framework.TestCase;

 

import com.ibatis.common.resources.Resources;

import com.ibatis.sqlmap.client.SqlMapClient;

import com.ibatis.sqlmap.client.SqlMapClientBuilder;

 

public class UserTest extends TestCase {

      

       public void testUser() throws Exception{

             

              //從配置文件中得到SqlMapClient對象

              Reader reader = Resources.getResourceAsReader("sqlMapConfig.xml");

              SqlMapClient sqlMapper = SqlMapClientBuilder.buildSqlMapClient(reader);

              reader.close();

             

              //創建用戶數據

              for(int i=0; i<10; i++){

                     User user = new User();

                     user.setUsername("用戶"+i);

                     user.setPassword("密碼"+i);

                     sqlMapper.insert("insertUser", user);

              }

             

              //查詢用戶數據

              List users = sqlMapper.queryForList("selectAllUsers");

              for (Iterator iter = users.iterator(); iter.hasNext();) {

                     User user = (User) iter.next();

                     System.out.println(user.getUsername());

              }

             

              //查詢特定用戶的數據

              User user = (User)sqlMapper.queryForObject("selectUser", 1);

              System.out.println("用戶【id="+1+"】的名稱是"+user.getUsername());

             

              //更新用戶的信息

              user = new User();

              user.setId(3);

              user.setUsername("更改之後的用戶名稱");

              user.setPassword("密碼被更改");

              sqlMapper.update("updateUser", user);

             

              //刪除用戶的信息

              sqlMapper.delete("deleteUser", 6);

 

       }

}

 

 

 

SqlMapClient對象

這個對象是iBatis操作數據庫的接口(執行CRUD等操作),它也可以執行事務管理等操作。這個類是我們使用iBATIS的最主要的類。它是線程安全的。通常,將它定義爲單例。(與hibernatesessionFactory的定義類似)。如:

import java.io.Reader;

import com.ibatis.common.resources.Resources;

import com.ibatis.sqlmap.client.SqlMapClient;

import com.ibatis.sqlmap.client.SqlMapClientBuilder;

 

public class IbatisSQLMapConfig {

 

    private static final SqlMapClient sqlMap;

 

    //在靜態區塊中初試化返回

    static {

        try {

            //聲明配置文件的名稱(映射文件被定義在其中)

            String resource = "sql_map_config.xml";

 

            //利用工具類Resources來讀取到配置文件

            Reader reader = Resources.getResourceAsReader(resource);

 

            //創建SqlMapClient接口的變量實例

            sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);

 

        } catch (Exception e) {

            e.printStackTrace();

            throw new RuntimeException(

                    "Error initializing MyAppSqlConfig class. Cause: " + e);

        }

    }

    public static SqlMapClient getSqlMapInstance() {

        //提供靜態方法返回靜態區塊中得到的SqlMapClient

        return sqlMap;

    }

}

 

How To

如何獲得剛插入記錄的自增長ID值?

  <insert id="insertUser" parameterClass="User">

    insert into t_user values (

        null,#username#,#password#

    )

    <selectKey resultClass="int" keyProperty="id">

        SELECT @@IDENTITY AS ID

    </selectKey> 

  </insert>

       User user = new User();

       user.setUsername("張三");

       user.setPassword("張三密碼");

      

       //如果主鍵是自動生成的,則其返回值可以通過<selectKey>標籤來設置

       //如果不通過<selectKey>標籤來設置,則返回值爲空!

       //<selectKey >中的keyProperty,是指定User中的id屬性,當調用結束之後,

       //user對象的id值和insert方法的返回值都是這條記錄的ID值!

       Object obj  = sqlMapper.insert("insertUser", user);

 

parameterClass的使用

  <insert id="insertUser" parameterClass="User">

    insert into t_user values (

        null,#username#,#password#

    )

    <selectKey resultClass="int" keyProperty="id">

        SELECT @@IDENTITY AS ID

    </selectKey> 

  </insert>

 

  <insert id="insertUser2">

    insert into t_user values (

        null,#username#,#password#

    )

    <selectKey resultClass="int" keyProperty="id">

        SELECT @@IDENTITY AS ID

    </selectKey> 

  </insert>

 

insertUser使用了parameterClass,所以必需傳入User類型的對象

       User user = new User();

       user.setUsername("張三");

       user.setPassword("張三密碼");

      

       //傳遞進去的對象,必須是User類型

       Object obj  = sqlMapper.insert("insertUser", user);

 

insertUser2沒有使用parameterClass,所以可以傳入任意具有相應屬性值的對象

       JustAnObject anobj = new JustAnObject();

       anobj.setUsername("用戶名");

       anobj.setPassword("用戶密碼");

      

       //如果沒有指定parameterClass屬性,則任何一個具有相應屬性值

       //的對象都可以被傳遞進去

       Object obj  = sqlMapper.insert("insertUser2", anobj);

 

parameterMap的使用

  <parameterMap class="User" id="insertUser-param">

    <parameter property="username"/>

    <parameter property="password"/>

  </parameterMap>

 

  <insert id="insertUser" parameterMap="insertUser-param">

    insert into t_user values (

        null,?,?

    )

    <selectKey resultClass="int" keyProperty="id">

        SELECT @@IDENTITY AS ID

    </selectKey> 

  </insert>

 

parameterMap用於傳入參數,以便匹配SQL語句中的?

       User user = new User();

       user.setUsername("張三dd");

       user.setPassword("張三密碼dd");

      

       Object obj  = sqlMapper.insert("insertUser", user);

 

利用parameterMap,可以定義參數對象的屬性如何映射到SQL查詢語句的動態參數上,注意parameterMap<parameter/>標籤的先後順序不能顛倒!

 

如何將查詢結果映射到不同的對象?(resultClass的使用)

  <select id="selectUserForOtherObject" resultClass="com.bjsxt.ibatis.OtherObject" parameterClass="int">

    select

    username as prop1,

    password as prop2

    from t_user where id=#value#

  </select>

 

       //查找t_user表,將其結果映射到一個屬性名不同的對象中!

       OtherObject obj = (OtherObject)sqlMapper.queryForObject("selectUserForOtherObject", 1);

       System.out.println(obj.getProp1()+","+obj.getProp2());

 

 

如何將查詢結果集映射到不同的對象?(resultMap的基本使用)

 

  <resultMap class="com.bjsxt.ibatis.OtherObject" id="ooResult">

    <result property="prop1" column="username"/>

    <result property="prop2" column="password"/>

  </resultMap>

  <!--

  如果使用resultMap來定義如何映射,則如下語句不可寫成:

  select username as prop1,password as prop2 ....

  -->

  <select id="selectUserForOtherObject2" parameterClass="int" resultMap="ooResult">

        select

        username,

        password

        from t_user where id=#value#

  </select>

 

       //查找t_user表,將其結果映射到一個屬性名不同的對象中!

       OtherObject obj = (OtherObject)sqlMapper.queryForObject("selectUserForOtherObject2", 17);

       System.out.println(obj.getProp1()+","+obj.getProp2());

 

如何將查詢結果集映射爲xml格式的數據?

 

  <select id="selectXmlData" resultClass="xml" xmlResultName="User" parameterClass="int">

    select * from t_user where id=#value#

  </select>

  <select id="selectXmlDatas" resultClass="xml" xmlResultName="User">

    select * from t_user

  </select>

 

       //查找t_user表,將其結果映射到xml

       //返回值是xml形式的字符串

       Object obj = (Object)sqlMapper.queryForObject("selectXmlData", 1);

       System.out.println(obj);

 

       //查找t_user表,將其結果映射到xml

       List list  = (List)sqlMapper.queryForList("selectXmlDatas");

       System.out.println(list);

 

如何用Map類型的對象作爲傳入參數?

  <!--

  這裏,可以使用全路徑類名,如:

  java.util.Map

  java.util.HashMap

  java.util.TreeMap

 

  map

  -->

  <insert id="insertUser" parameterClass="map">

    insert into t_user values (

        null,#username#,#password#

    )

  </insert>

 

       Map user = new TreeMap();

       user.put("username", "Map用戶");

       user.put("password", "Map用戶密碼");

       sqlMapper.insert("insertUser",user);

 

如何將查詢結果集的元素轉換爲Map類型的對象?

  <!--

  resultClass可以定義爲java.util.HashMap類型,

  將能自動轉換

  -->

  <select id="selectMapUsers" resultClass="java.util.HashMap">

    select * from t_user

  </select>

 

       List list = (List)sqlMapper.queryForList("selectMapUsers");

       System.out.println(list);

       for (Iterator iter = list.iterator(); iter.hasNext();) {

           Map map = (Map) iter.next();

           //可在此輸出map的數據

       }

 

 

 

 

事務處理

可以使用sqlMapClientstartTransaction/commitTransaction/endTransaction等方法來控制事務的邊界。

 

如果與spring整合(這是iBatis推薦的方式),則我們需要在spring配置文件中指定其事務特性。

 

 

spring集成

Spring通過DAO模式,提供了對iBATIS的良好支持。SqlMapClient對象是iBATIS中的主要對象,我們可以通過配置讓spring來管理SqlMapClient對象的創建。

 

hibernate類似,Spring 提供了SqlMapClientDaoSupport對象,我們的DAO可以繼承這個類,通過它所提供的SqlMapClientTemplate對象來操縱數據庫。看起來這些概念都與hibernate類似。

 

通過SqlMapClientTemplate來操縱數據庫的CRUD是沒有問題的,這裏面關鍵的問題是事務處理。Spring提供了強大的聲明式事務處理的功能,我們已經清楚hibernate中如何配置聲明式的事務,那麼在iBATIS中如何獲得聲明式事務的能力呢?

 

第一,我們需要了解的是spring通過AOP來攔截方法的調用,從而在這些方法上面添加聲明式事務處理的能力。典型配置如下:

    <!-- 配置事務特性 -->

    <tx:advice id="txAdvice" transaction-manager="事務管理器名稱">

       <tx:attributes>

           <tx:method name="add*" propagation="REQUIRED"/>

           <tx:method name="del*" propagation="REQUIRED"/>

           <tx:method name="update*" propagation="REQUIRED"/>

           <tx:method name="*" read-only="true"/>

       </tx:attributes>

    </tx:advice>

   

    <!-- 配置哪些類的方法需要進行事務管理 -->

    <aop:config>

        <aop:pointcut id="allManagerMethod" expression="execution(* com.bjsxt.crm.manager.*.*(..))"/>

       <aop:advisor advice-ref="txAdvice" pointcut-ref="allManagerMethod"/>

    </aop:config>

這些事務都是聲明在業務邏輯層的對象上的。

 

 

第二,我們需要一個事務管理器,對事務進行管理。

    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

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

    </bean>

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">

        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>

        <property name="url" value="jdbc:mysql://127.0.0.1/crm"/>

        <property name="username" value="root"/>

        <property name="password" value="mysql"/>

    </bean>

 

此後,我們需要讓spring來管理SqlMapClient對象:

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

       <property name="configLocation"><value>classpath:sqlMapConfig.xml</value></property>

    </bean>

 

我們的DAO的編寫:

package com.bjsxt.crm.dao.impl.ibatis;

 

import java.util.List;

 

import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;

 

import com.bjsxt.crm.dao.UserDAO;

import com.bjsxt.crm.model.User;

 

public class UserDAOImpl extends SqlMapClientDaoSupport implements UserDAO {

 

       public void delete(User user) {

              getSqlMapClientTemplate().delete("delete",user.getId());

       }

 

       public List findAll() {

              return getSqlMapClientTemplate().queryForList("findAll");

       }

 

       public User findById(int id) {

              return (User)getSqlMapClientTemplate().queryForObject("findById", id);

       }

 

       public void save(User user) {

              getSqlMapClientTemplate().insert("save",user);

       }

 

       public void update(User user) {

              getSqlMapClientTemplate().update("update",user);

       }

 

}

 

繼承SqlMapClientDaoSupport,要求我們注入SqlMapClient對象,因此,需要有如下的DAO配置:

<bean id="userDAO" class="com.bjsxt.crm.dao.impl.ibatis.UserDAOImpl">

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

</bean>

 

這就是所有需要注意的問題了,此後就可以在業務邏輯層調用DAO對象了!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章