海鷗航際

          JAVA站
          posts - 11, comments - 53, trackbacks - 1, articles - 102

          ibatis初步介紹

          Posted on 2005-01-12 09:39 海天一鷗 閱讀(583) 評論(0)  編輯  收藏 所屬分類: Java數據庫技術

          ibatis初步介紹

           

          作者:CHAMPION

          ibatis初步介紹

                      在開發過程中最能幫助你的是什么?是框架,一個優秀的框架可以極大的提高你的效率。struts給了我們什么?MVC的實現,國際化、靈活。還有很多。不過,在一個通常的WEB應該中,是不能缺少數據庫的,而struts在這方面并沒有給我們提供什么有效的幫助。通常情況下我們做這個的時候有幾個選擇。
                      
          最直接的當然是JDBC啊,自己寫connectstatmentresultset等等的代碼,結果是累死自己。
                      
          然后一種方法是EJBEJB確實是一個好東西,可惜在很多場合用不上,起碼它很煩,速度很慢
                      
          還有一種選擇就是JDO及類似的東西。最著名是free的應該是castorhibernate等。

          現在我們又多了一種選擇,就是ibatis Db Layer,它的主頁是http://www.ibatis.com,為什么說它好,讓我們來看看作者自己的說明吧,使用ibatis的理由

          10、知道怎樣操作10種以上的數據庫
          9
          、可配置的caching(包括從屬)
          8
          、支持DataSourcelocal transaction managemen
          global transaction
          7
          、簡單的XML配置文檔

          6
          、支持Map, Collection, List和簡單類型包裝(Integer, String)
          5
          、支持JavaBeans(get/set 方法
          )
          4
          、支持復雜的對象映射(
          populating lists, complex object models)
          3
          、對象模型從不完美(不需要修改
          )
          2
          、數據模型從不完美(不需要修改
          )
          1
          、你已經知道SQL,為什么還要學習其他東西

          另外一點它是100% Open Source Freeware

          下面我們就來看一看,做一個簡單的ibatis需要哪一些工作。然后一步一步深入探索它的強大功能。在實踐中來看它的好處在哪里。

          ibatis的網站上有一個它自己的petstore,在我個人看來是最簡潔的petstore了,跟struts1.0結合。應該說是一個不錯的教程。希望大家能夠好好研究。當然,作為入門。我們先來做一個簡單的程序。所采用的庫嘛,就仍然是用petstore的了。數據庫也是選擇Oracle(為什么選擇Oracle,很多朋友不理解,怎么不用mysql之類的呢,一個主要的原因是個人愛好,Oracle畢竟是商業數據庫,有它的強大之處,另外在linux下它也是免費的,:)。廢話少說,先用jpetstore3.1提供的ddl建立一個庫吧。

          然后在eclipse里建立一個ibatisDemo的工程。加入ibatis提供的庫,建立相就的目錄。看一下一個最簡單的程序需要哪一些文件。我們選擇一個簡單表,即Category這個表的操作來演示功能

          文件路徑

          功能說明

          備注

          config\properties\petstore.properties

          可變參數配置文件,所有根據環境不同的參數都放在這里

           

          config\properties\simple\dao.xml

          dao配置文件,主要存放dao對象和數據池設置

           

          config\properties\simple\sql-map-config-storedb.xml

          真正的核心配置文件

           

          config\sqlmap\Category.xml

          存放Category的數據操作的SQL

           

          com.ewuxi.champion.exception.DaoException.java

          自定義的Exception類,不用說了吧

           

          com.ewuxi.champion.Service.java

          一個服務類,用于初始化

           

          com.ewuxi.champion.persistence.dao.DaoCommon

          Dao層的統一操作類,提供一些公共函數

           

          com.ewuxi.champion.persistence.dao.CategoryDb

          Category的操作類

           

          com.ewuxi.champion.persistence.vo.Category

          valueObject 值對象

           

          com.ewuxi.champion.persistence.dao.CategoryDbTest

          單元測試類

           

          下面一個一個文件詳細說明

          petstore.properties

          ##################################################################
          SIMPLE CONFIGURATION SECTION
          ##################################################################

          ## SimpleDataSource properties
          ## Use only if useSimpleConfiguration=true

          SimpleDriver=oracle.jdbc.OracleDriver
          SimpleUrl=jdbc:oracle:thin:@10.0.0.5:1521:champion
          SimpleUsername=pet
          SimplePassword=pet

           

          這個不用解釋,就是數據庫的連接串,如果你在自己的機器上運行,當然這些都是需要改的。

          dao.xml

          <?xml version="1.0" encoding="UTF-8"?>

          <!DOCTYPE dao-config
          PUBLIC "-//iBATIS.com//DTD DAO Configuration 1.0//EN"
          "http://www.ibatis.com/dtd/dao.dtd">

          <dao-config>

          <context name="StoreDaoManager" default="true">
          <!-- Configure the transaction pool. -->
          <transaction-pool implementation="com.ibatis.db.dao.jdbc.SqlMapDaoTransactionPool">
          <property name="sql-map-config-file" value="properties/simple/sql-map-config-storedb.xml"/>
          </transaction-pool>

          </context>

          </dao-config>

          上面這一段也是很簡單的,連一個dao也沒有配置,也就是說,用的是默認的Dao。其中<context name="StoreDaoManager" default="true">表示它是默認的數據庫配置(它可以根據名字不同同時連接幾個數據庫的)

          sql-map-config-storedb.xml

          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE sql-map-config
          PUBLIC "-//iBATIS.com//DTD SQL Map Config 1.0//EN"
          "http://www.ibatis.com/dtd/sql-map-config.dtd">

          <sql-map-config>

          <properties resource="properties/petstore.properties" />

          <settings
          maxExecute="0"
          maxExecutePerConnection="0"
          maxTransactions="0"
          cacheModelsEnabled="true"
          statementCacheSize="175"
          useBeansMetaClasses="false"
          useGlobalTransactions="false" />

          <datasource name="jpestoreSimple"
          factory-class="com.ibatis.db.sqlmap.datasource.DbcpDataSourceFactory"
          default="true" >
          <property name="JDBC.Driver" value="${SimpleDriver}"/>
          <property name="JDBC.ConnectionURL" value="${SimpleUrl}"/>
          <property name="JDBC.Username" value="${SimpleUsername}"/>
          <property name="JDBC.Password" value="${SimplePassword}"/>
          <property name="Pool.MaximumActiveConnections" value="15"/>
          <property name="Pool.MaximumIdleConnections" value="15"/>
          <property name="Pool.MaximumWait" value="1000"/>
          </datasource>

          <sql-map resource="sqlmap/Category.xml" />

          </sql-map-config>

          這里真正實現了數據庫連接,我們使用的是dbcp的連接池。JDBC的配置大家都很熟了。${SimpleDriver}就是指的前面petstore.properties中的SimpleDriver的內容。

          <sql-map resource="sqlmap/Category.xml" />則表示包含Category.xml這個文件。

          Category.xml

          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE sql-map
          PUBLIC "-//iBATIS.com//DTD SQL Map 1.0//EN"
          "http://www.ibatis.com/dtd/sql-map.dtd">

          <sql-map name="Category">

          <result-map name="result" class="com.ewuxi.champion.persistence.vo.Category">
          <property name="categoryId" column="CATID" columnIndex="1" />
          <property name="name" column="NAME" columnIndex="2"/>
          <property name="description" column="DESCN" columnIndex="3"/>
          </result-map>

          <mapped-statement name="findByPrimaryKeyCategoryDao" result-map="result">
          select CATID, NAME, DESCN from CATEGORY where CATID = #categoryId#
          </mapped-statement>

          <dynamic-mapped-statement name="findCategoryDao" result-map="result">
          select CATID, NAME, DESCN from CATEGORY
          <dynamic prepend="where">
          <isNotNull prepend="and" property="categoryId" >
          CATID = #categoryId#
          </isNotNull>
          <isNotNull prepend="and" property="name" >
          NAME = #name#
          </isNotNull>
          <isNotNull prepend="and" property="description">
          DESCN = #description#
          </isNotNull>
          </dynamic>
          </dynamic-mapped-statement>


          <mapped-statement name="findCategoryDaoCount" result-class="java.lang.Integer">
          select count(1) as value from CATEGORY
          </mapped-statement>


          <!-- =============================================
          mapped-statement
          ============================================= -->

          <dynamic-mapped-statement name="updateByPrimaryKeyCategoryDao">
          update CATEGORY
          <dynamic prepend="set">
          <isNotNull prepend="," property="name" >
          NAME = #name#
          </isNotNull>
          <isNotNull prepend="," property="description">
          DESCN = #description#
          </isNotNull>
          </dynamic>
          where
          CATID =#categoryId#
          </dynamic-mapped-statement>

          <!-- =============================================
          mapped-statement
          ============================================= -->

          <mapped-statement name="deleteByPrimaryKeyCategoryDao">
          delete from CATEGORY
          where CATID =#categoryId#
          </mapped-statement>

          <!-- =============================================
          OPTIONAL EXPLICIT PARAMETER MAP
          ============================================= -->

          <parameter-map name="insert-params">
          <property name="categoryId"/>
          <property name="name" type="VARCHAR"/>
          <property name="description" type="VARCHAR"/>
          </parameter-map>

          <!-- =============================================
          MAPPED STATEMENTS - w/Explicit Parameter Map
          ============================================= -->

          <mapped-statement name="insertCategoryDao" parameter-map="insert-params" >
          insert into CATEGORY (
          CATID,NAME,DESCN)
          values (
          ?,?,?
          )
          </mapped-statement>
          </sql-map>

          上述文件就是真正的SQL所存在的地方。

          <result-map name="result" class="com.ewuxi.champion.persistence.vo.Category">
          <property name="categoryId" column="CATID" columnIndex="1" />
          <property name="name" column="NAME" columnIndex="2"/>
          <property name="description" column="DESCN" columnIndex="3"/>
          </result-map>

          這一段的內容表示返回的對象是com.ewuxi.champion.persistence.vo.Category,也就是我們值對象。當執行查詢的時候,dblay會封裝出一個Category對象或者一個Categorylist集合。其中數據列CATID就對象javabeancategoryId值。name是自定義的

           

          <mapped-statement name="findByPrimaryKeyCategoryDao" result-map="result">
          select CATID, NAME, DESCN from CATEGORY where CATID = #categoryId#
          </mapped-statement>

          此處result-map="result"表示返回結果以后,就會參照前面的result來返回對象。select CATID, NAME, DESCN from CATEGORY where CATID = #categoryId#標準的SQL,只不過這一點CATID = #categoryId#有些不同,#categoryId#表示傳遞一個Category對象時,Dblay會自動取得categoryId的值來執行SQL

          再來看一個

          <dynamic-mapped-statement name="updateByPrimaryKeyCategoryDao">
          update CATEGORY
          <dynamic prepend="set">
          <isNotNull prepend="," property="name" >
          NAME = #name#
          </isNotNull>
          <isNotNull prepend="," property="description">
          DESCN = #description#
          </isNotNull>
          </dynamic>
          where
          CATID =#categoryId#
          </dynamic-mapped-statement>

          這個地方就體現了dblayer的強大之處,動態SQL。平常我們經常碰到的情況是根據不同的情況,執行的SQL有一點點不一樣。寫在程序里,要寫不少的if then之類的,在這里,dbLayer給你一下解決了。比如在這里,我們三個值都是String對象,所以通過isNotNull就可以實現幾種不同的update了,比如,如果我只想修改DESCN這個字段,只要傳過去的Category對象只有categoryIddescription有值,就會生成update CATEGORY set DESCN = #description# where CATID =#categoryId#。同樣如果傳遞的對象只有categoryIdname有值,就會生成update CATEGORY set NAME = #name# where CATID =#categoryId#。是否很強大?:)

          前面這兩種,參數的傳遞方式是內置參數,也就是CATID =#categoryId#這種,大家可能不太習慣,那就看一看標準的寫法吧。

          <!-- =============================================
          OPTIONAL EXPLICIT PARAMETER MAP
          ============================================= -->

          <parameter-map name="insert-params">
          <property name="categoryId"/>
          <property name="name" type="VARCHAR"/>
          <property name="description" type="VARCHAR"/>
          </parameter-map>

          <!-- =============================================
          MAPPED STATEMENTS - w/Explicit Parameter Map
          ============================================= -->

          <mapped-statement name="insertCategoryDao" parameter-map="insert-params" >
          insert into CATEGORY (
          CATID,NAME,DESCN)
          values (
          ?,?,?
          )
          </mapped-statement>
          </sql-map>

          這里面的insert語句想來大家都很熟了吧?這個時候怎么取得參數呢?關鍵在于這里parameter-map="insert-params",表示會讀取<parameter-map name="insert-params">的設置,而這個設置也不用多解釋了吧,就是按順序,三個?分別對應三個值。還能指明他們的數據類型。

          下面來看看Service.java


          package com.ewuxi.champion;

          import java.io.Reader;
          import java.util.Properties;

          import org.apache.commons.logging.Log;
          import org.apache.commons.logging.LogFactory;

          import com.ibatis.common.resources.Resources;
          import com.ibatis.db.dao.DaoManager;

          /**
          * @author champion
          *
          * To change the template for this generated type comment go to
          * Window - Preferences - Java - Code Generation - Code and Comments
          */
          public class Service {
          static Log log = LogFactory.getLog(Service.class);
          public static void initSet() {

          try {

          String resource = null;

          resource = "properties/simple/dao.xml";
          log.info("Using SIMPLE configuration. (" + resource + ")");

          Reader reader = Resources.getResourceAsReader(resource);
          DaoManager.configure(reader);

          } catch (Exception e) {
          throw new RuntimeException(
          "Could not initialize BaseLogic. Cause: " + e);
          }
          }

          }

          一個靜態方法,從resource文件中讀出配置,最后用DaoManager.configure(reader);完成配置。

          DaoCommon

          public static Dao getDefautDao(){
          return DaoManager.getInstance().getDao("");
          }
          public static SqlMap getSqlMap(Dao c) throws DaoException {
          try {
          DaoManager daoManager = DaoManager.getInstance(c);

          if (daoManager == null) {
          daoManager = DaoManager.getInstance();
          }

          SqlMapDaoTransaction trans = (SqlMapDaoTransaction) daoManager.getLocalTransaction();
          SqlMap sqlMap = trans.getSqlMap();

          return sqlMap;
          } catch (Exception e) {
          throw new DaoException(e);
          }
          }

          public static SqlMap getSqlMap(String c) throws DaoException {
          try {
          DaoManager daoManager = DaoManager.getInstance(c);
          SqlMapDaoTransaction trans = (SqlMapDaoTransaction) daoManager.getLocalTransaction();
          SqlMap sqlMap = trans.getSqlMap();

          return sqlMap;
          } catch (Exception e) {
          throw new DaoException(e);
          }
          }

          三個主要的函數,第一個是得到默認的DAO對象,后兩個是根據一個dao對象或者一個參數(也就是前面<context name="StoreDaoManager" >中是name)。取得SqlMap對象,這個對象是主要的數據操作接口。

          /**
          * @throws Exception
          *
          開始事務,所在session層必須使用它
          */
          public static void startTransaction() throws Exception {
          if (!DaoCommon.inTransaction()) {
          DaoManager.getInstance().startTransaction();
          }
          }

          public static boolean inTransaction() throws Exception {
          try {
          DaoManager.getInstance().getLocalTransaction();

          return true;
          } catch (Exception e) {
          return false;
          }
          }

          /**
          * @throws Exception
          *
          放棄事務
          */
          public static void rollBack() {

          try {
          DaoManager.getInstance().rollbackTransaction();
          } catch (Exception e) {
          LogFactory.getLog(DaoCommon.class).error(e, e);
          }
          }

          /**
          * @throws Exception
          *
          提交事務
          */
          public static void commit() throws Exception {
          DaoManager.getInstance().commitTransaction();
          }

          下面的一些函數是對事務的一些封裝。想必也很容易理解。

          然后讓我們來看CategoryDb的內容

          /*
          * Created on 2003-10-11
          *
          * To change the template for this generated file go to
          * Window - Preferences - Java - Code Generation - Code and Comments
          */
          package com.ewuxi.champion.persistence.dao;

          import com.ewuxi.champion.exception.DaoException;
          import com.ewuxi.champion.persistence.vo.Category;
          import com.ibatis.db.sqlmap.SqlMap;

          /**
          * @author champion
          *
          *category
          數據庫操作對象
          */

          public class CategoryDb {

          /**
          * @param vo
          * @throws DaoException
          *
          插入一條記錄
          */
          public void insert(Category vo) throws DaoException{
          try {
          SqlMap sqlMap=DaoCommon.getSqlMap(DaoCommon.getDefautDao());
          sqlMap.executeUpdate("insertCategoryDao",vo);
          } catch (Exception e) {
          throw new DaoException(e);
          }
          }
          /**
          * @param vo
          * @throws DaoException
          *
          刪除一條記錄
          */
          public void delete(Category vo) throws DaoException{
          try {
          SqlMap sqlMap=DaoCommon.getSqlMap(DaoCommon.getDefautDao());
          sqlMap.executeUpdate("deleteByPrimaryKeyCategoryDao",vo);
          } catch (Exception e) {
          throw new DaoException(e);
          }
          }
          /**
          * @param vo
          * @throws DaoException
          *
          修改一條記錄
          */
          public void update(Category vo) throws DaoException{
          try {
          SqlMap sqlMap=DaoCommon.getSqlMap(DaoCommon.getDefautDao());
          sqlMap.executeUpdate("updateByPrimaryKeyCategoryDao",vo);
          } catch (Exception e) {
          throw new DaoException(e);
          }
          }
          /**
          * @param vo
          * @return
          * @throws DaoException
          *
          查找一條記錄
          */
          public Category findByPk(Category vo) throws DaoException{
          try {
          SqlMap sqlMap=DaoCommon.getSqlMap(DaoCommon.getDefautDao());
          return (Category) sqlMap.executeQueryForObject("findByPrimaryKeyCategoryDao",vo);
          } catch (Exception e) {
          throw new DaoException(e);
          }
          }

          }

           

          每一個函數都很類似的。關鍵就在這一句(Category) sqlMap.executeQueryForList("findByPrimaryKeyCategoryDao",vo);。看到"findByPrimaryKeyCategoryDao",這個對應于前面Category.xml中的名字。而vo則是一個Category對象。

          最后是CategoryDbTest類,這個是我們的單元測試程序

          /*
          * Created on 2003-10-11
          *
          * To change the template for this generated file go to
          * Window - Preferences - Java - Code Generation - Code and Comments
          */
          package com.ewuxi.champion.persistence.dao;

          import com.ewuxi.champion.exception.DaoException;
          import com.ewuxi.champion.persistence.vo.Category;
          import com.ibatis.db.sqlmap.SqlMap;

          /**
          * @author champion
          *
          *category
          數據庫操作對象
          */

          public class CategoryDb {

          /**
          * @param vo
          * @throws DaoException
          *
          插入一條記錄
          */
          public void insert(Category vo) throws DaoException{
          try {
          SqlMap sqlMap=DaoCommon.getSqlMap(DaoCommon.getDefautDao());
          sqlMap.executeUpdate("insertCategoryDao",vo);
          } catch (Exception e) {
          throw new DaoException(e);
          }
          }
          /**
          * @param vo
          * @throws DaoException
          *
          刪除一條記錄
          */
          public void delete(Category vo) throws DaoException{
          try {
          SqlMap sqlMap=DaoCommon.getSqlMap(DaoCommon.getDefautDao());
          sqlMap.executeUpdate("deleteByPrimaryKeyCategoryDao",vo);
          } catch (Exception e) {
          throw new DaoException(e);
          }
          }
          /**
          * @param vo
          * @throws DaoException
          *
          修改一條記錄
          */
          public void update(Category vo) throws DaoException{
          try {
          SqlMap sqlMap=DaoCommon.getSqlMap(DaoCommon.getDefautDao());
          sqlMap.executeUpdate("updateByPrimaryKeyCategoryDao",vo);
          } catch (Exception e) {
          throw new DaoException(e);
          }
          }
          /**
          * @param vo
          * @return
          * @throws DaoException
          *
          查找一條記錄
          */
          public Category findByPk(Category vo) throws DaoException{
          try {
          SqlMap sqlMap=DaoCommon.getSqlMap(DaoCommon.getDefautDao());
          return (Category) sqlMap.executeQueryForObject("findByPrimaryKeyCategoryDao",vo);
          } catch (Exception e) {
          throw new DaoException(e);
          }
          }

          }

          運行結果,測試通過。原代碼全部下載

           

          主站蜘蛛池模板: 莲花县| 赣州市| 肥西县| 汝南县| 宜春市| 都匀市| 邯郸市| 祁连县| 安龙县| 奉节县| 上思县| 宣恩县| 颍上县| 凯里市| 普陀区| 台北市| 信宜市| 邯郸县| 将乐县| 吴忠市| 婺源县| 宣汉县| 邢台县| 永修县| 华蓥市| 昭苏县| 开原市| 芦溪县| 民权县| 甘孜县| 长顺县| 尼勒克县| 原平市| 合肥市| 双鸭山市| 饶平县| 开封市| 阜新市| 皋兰县| 毕节市| 响水县|