分享
 
 
 

ibatis初步介绍

王朝java/jsp·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

在开发过程中最能帮助你的是什么?是框架,一个优秀的框架可以极大的提高你的效率。struts给了我们什么?MVC的实现,国际化、灵活。还有很多。不过,在一个通常的WEB应该中,是不能缺少数据库的,而struts在这方面并没有给我们提供什么有效的帮助。通常情况下我们做这个的时候有几个选择。

最直接的当然是JDBC啊,自己写connect、statment和resultset等等的代码,结果是累死自己。

然后一种方法是EJB,EJB确实是一个好东西,可惜在很多场合用不上,起码它很烦,速度很慢

还有一种选择就是JDO及类似的东西。最著名是free的应该是castorhibernate等。

现在我们又多了一种选择,就是ibatis Db Layer,它的主页是http://www.ibatis.com,为什么说它好,让我们来看看作者自己的说明吧,使用ibatis的理由

10、知道怎样操作10种以上的数据库

9 、可配置的caching(包括从属)

8、支持DataSource、local 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对象或者一个Category的list集合。其中数据列CATID就对象javabean的categoryId值。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对象只有categoryId和description有值,就会生成update CATEGORY set DESCN = #description# where CATID =#categoryId#。同样如果传递的对象只有categoryId和name有值,就会生成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);

}

}

}

运行结果,测试通过。原代码全部下载

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有