Open-Open

          皇家撒拉哥薩
          posts - 32, comments - 3, trackbacks - 0, articles - 1

          ibatis介紹

          Posted on 2006-05-16 09:40 開(kāi)源愛(ài)好者 閱讀(611) 評(píng)論(0)  編輯  收藏 所屬分類: iBATIS
          ibatis介紹
          作者:紫龍
          ??在開(kāi)發(fā)過(guò)程中最能幫助你的是什么?是框架,一個(gè)優(yōu)秀的框架可以極大的提高你的效率。struts給了我們什么?MVC的實(shí)現(xiàn),國(guó)際化、靈活。還有很多。不過(guò),在一個(gè)通常的WEB應(yīng)該中,是不能缺少數(shù)據(jù)庫(kù)的,而struts在這方面并沒(méi)有給我們提供什么有效的幫助。通常情況下我們做這個(gè)的時(shí)候有幾個(gè)選擇。
          ????????????最直接的當(dāng)然是JDBC啊,自己寫connect、statment和resultset等等的代碼,結(jié)果是累死自己。
          ????????????然后一種方法是EJB,EJB確實(shí)是一個(gè)好東西,可惜在很多場(chǎng)合用不上,起碼它很煩,速度很慢
          ????????????還有一種選擇就是JDO及類似的東西。最著名是free的應(yīng)該是castor,hibernate等。

          現(xiàn)在我們又多了一種選擇,就是ibatis Db Layer,它的主頁(yè)是http://www.ibatis.com,為什么說(shuō)它好,讓我們來(lái)看看作者自己的說(shuō)明吧,使用ibatis的理由

          10、知道怎樣操作10種以上的數(shù)據(jù)庫(kù)
          9 、可配置的caching(包括從屬)
          8、支持DataSource、local transaction managemen和global transaction
          7、簡(jiǎn)單的XML配置文檔
          6、支持Map, Collection, List和簡(jiǎn)單類型包裝(如Integer, String)
          5、支持JavaBeans類(get/set 方法)
          4、支持復(fù)雜的對(duì)象映射(如populating lists, complex object models)
          3、對(duì)象模型從不完美(不需要修改)
          2、數(shù)據(jù)模型從不完美(不需要修改)
          1、你已經(jīng)知道SQL,為什么還要學(xué)習(xí)其他東西

          另外一點(diǎn)它是100% Open Source Freeware

          下面我們就來(lái)看一看,做一個(gè)簡(jiǎn)單的ibatis需要哪一些工作。然后一步一步深入探索它的強(qiáng)大功能。在實(shí)踐中來(lái)看它的好處在哪里。

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

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

          文件路徑功能說(shuō)明備注
          config\properties\petstore.properties可變參數(shù)配置文件,所有根據(jù)環(huán)境不同的參數(shù)都放在這里?
          config\properties\simple\dao.xmldao配置文件,主要存放dao對(duì)象和數(shù)據(jù)池設(shè)置?
          config\properties\simple\sql-map-config-storedb.xml真正的核心配置文件?
          config\sqlmap\Category.xml存放Category的數(shù)據(jù)操作的SQL?
          com.ewuxi.champion.exception.DaoException.java自定義的Exception類,不用說(shuō)了吧?
          com.ewuxi.champion.Service.java一個(gè)服務(wù)類,用于初始化?
          com.ewuxi.champion.persistence.dao.DaoCommonDao層的統(tǒng)一操作類,提供一些公共函數(shù)?
          com.ewuxi.champion.persistence.dao.CategoryDbCategory的操作類?
          com.ewuxi.champion.persistence.vo.CategoryvalueObject 值對(duì)象?
          com.ewuxi.champion.persistence.dao.CategoryDbTest單元測(cè)試類?

          下面一個(gè)一個(gè)文件詳細(xì)說(shuō)明

          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

          ?

          這個(gè)不用解釋,就是數(shù)據(jù)庫(kù)的連接串,如果你在自己的機(jī)器上運(yùn)行,當(dāng)然這些都是需要改的。

          dao.xml

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





          上面這一段也是很簡(jiǎn)單的,連一個(gè)dao也沒(méi)有配置,也就是說(shuō),用的是默認(rèn)的Dao。其中表示它是默認(rèn)的數(shù)據(jù)庫(kù)配置(它可以根據(jù)名字不同同時(shí)連接幾個(gè)數(shù)據(jù)庫(kù)的)。

          sql-map-config-storedb.xml


          PUBLIC "-//iBATIS.com//DTD SQL Map Config 1.0//EN"
          "http://www.ibatis.com/dtd/sql-map-config.dtd">

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

          factory-class="com.ibatis.db.sqlmap.datasource.DbcpDataSourceFactory"
          default="true" >







          這里真正實(shí)現(xiàn)了數(shù)據(jù)庫(kù)連接,我們使用的是dbcp的連接池。JDBC的配置大家都很熟了。${SimpleDriver}就是指的前面petstore.properties中的SimpleDriver的內(nèi)容。

          而則表示包含Category.xml這個(gè)文件。

          Category.xml


          PUBLIC "-//iBATIS.com//DTD SQL Map 1.0//EN"
          "http://www.ibatis.com/dtd/sql-map.dtd">

           






          select CATID, NAME, DESCN from CATEGORY where CATID = #categoryId#


          select CATID, NAME, DESCN from CATEGORY


          CATID = #categoryId#


          NAME = #name#


          DESCN = #description#






          select count(1) as value from CATEGORY



          mapped-statement
          ============================================= -->


          update CATEGORY


          NAME = #name#


          DESCN = #description#


          where
          CATID =#categoryId#


          mapped-statement
          ============================================= -->


          delete from CATEGORY
          where CATID =#categoryId#

          OPTIONAL EXPLICIT PARAMETER MAP
          ============================================= -->





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


          insert into CATEGORY (
          CATID,NAME,DESCN)
          values (
          ?,?,?
          )

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





          這一段的內(nèi)容表示返回的對(duì)象是com.ewuxi.champion.persistence.vo.Category,也就是我們值對(duì)象。當(dāng)執(zhí)行查詢的時(shí)候,dblay會(huì)封裝出一個(gè)Category對(duì)象或者一個(gè)Category的list集合。其中數(shù)據(jù)列CATID就對(duì)象javabean的categoryId值。name是自定義的


          select CATID, NAME, DESCN from CATEGORY where CATID = #categoryId#

          此處result-map="result"表示返回結(jié)果以后,就會(huì)參照前面的result來(lái)返回對(duì)象。select CATID, NAME, DESCN from CATEGORY where CATID = #categoryId#標(biāo)準(zhǔn)的SQL,只不過(guò)這一點(diǎn)CATID = #categoryId#有些不同,#categoryId#表示傳遞一個(gè)Category對(duì)象時(shí),Dblay會(huì)自動(dòng)取得categoryId的值來(lái)執(zhí)行SQL

          再來(lái)看一個(gè)


          update CATEGORY


          NAME = #name#


          DESCN = #description#


          where
          CATID =#categoryId#

          這個(gè)地方就體現(xiàn)了dblayer的強(qiáng)大之處,動(dòng)態(tài)SQL。平常我們經(jīng)常碰到的情況是根據(jù)不同的情況,執(zhí)行的SQL有一點(diǎn)點(diǎn)不一樣。寫在程序里,要寫不少的if then之類的,在這里,dbLayer給你一下解決了。比如在這里,我們?nèi)齻€(gè)值都是String對(duì)象,所以通過(guò)isNotNull就可以實(shí)現(xiàn)幾種不同的update了,比如,如果我只想修改DESCN這個(gè)字段,只要傳過(guò)去的Category對(duì)象只有categoryId和description有值,就會(huì)生成update CATEGORY set DESCN = #description# where CATID =#categoryId#。同樣如果傳遞的對(duì)象只有categoryId和name有值,就會(huì)生成update CATEGORY set NAME = #name# where CATID =#categoryId#。是否很強(qiáng)大?:)

          前面這兩種,參數(shù)的傳遞方式是內(nèi)置參數(shù),也就是CATID =#categoryId#這種,大家可能不太習(xí)慣,那就看一看標(biāo)準(zhǔn)的寫法吧。

          OPTIONAL EXPLICIT PARAMETER MAP
          ============================================= -->





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


          insert into CATEGORY (
          CATID,NAME,DESCN)
          values (
          ?,?,?
          )

          這里面的insert語(yǔ)句想來(lái)大家都很熟了吧?這個(gè)時(shí)候怎么取得參數(shù)呢?關(guān)鍵在于這里parameter-map="insert-params",表示會(huì)讀取的設(shè)置,而這個(gè)設(shè)置也不用多解釋了吧,就是按順序,三個(gè)?分別對(duì)應(yīng)三個(gè)值。還能指明他們的數(shù)據(jù)類型。

          下面來(lái)看看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);
          }
          }

          }

          一個(gè)靜態(tài)方法,從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);
          }
          }

          三個(gè)主要的函數(shù),第一個(gè)是得到默認(rèn)的DAO對(duì)象,后兩個(gè)是根據(jù)一個(gè)dao對(duì)象或者一個(gè)參數(shù)(也就是前面中是name值)。取得SqlMap對(duì)象,這個(gè)對(duì)象是主要的數(shù)據(jù)操作接口。

          /**
          * @throws Exception
          * 開(kāi)始事務(wù),所在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
          * 放棄事務(wù)
          */
          public static void rollBack() {

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

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

          下面的一些函數(shù)是對(duì)事務(wù)的一些封裝。想必也很容易理解。

          然后讓我們來(lái)看CategoryDb的內(nèi)容

          /*
          * 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數(shù)據(jù)庫(kù)操作對(duì)象
          */

          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);
          }
          }

          }


          每一個(gè)函數(shù)都很類似的。關(guān)鍵就在這一句(Category) sqlMap.executeQueryForList("findByPrimaryKeyCategoryDao",vo);。看到"findByPrimaryKeyCategoryDao",這個(gè)對(duì)應(yīng)于前面Category.xml中的名字。而vo則是一個(gè)Category對(duì)象。

          最后是CategoryDbTest類,這個(gè)是我們的單元測(cè)試程序

          /*
          * 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數(shù)據(jù)庫(kù)操作對(duì)象
          */

          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);
          }
          }

          }

          主站蜘蛛池模板: 宁夏| 静宁县| 赣榆县| 汕头市| 永顺县| 抚顺县| 马龙县| 辽源市| 获嘉县| 张北县| 正镶白旗| 卢氏县| 宜州市| 巴马| 城固县| 会宁县| 麻阳| 四川省| 金平| 宾阳县| 磴口县| 新干县| 姜堰市| 白玉县| 象州县| 长汀县| 承德市| 元朗区| 勃利县| 高雄市| 信宜市| 万年县| 石家庄市| 黄山市| 互助| 九江市| 兴城市| 永川市| 平山县| 济宁市| 定边县|