探索与发现

研究java技术

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  83 随笔 :: 0 文章 :: 109 评论 :: 0 Trackbacks

to robbin
ibatis的网站
www.ibatis.com上面可以找到很好的文档,再加上有非常不错的例子,所以使用是相当的简单。
sourceforge上面的讨论
http://swik.net/DAO
http://www.learntechnology.net/struts-ibatis.do
http://www.nabble.com/iBATIS-f360.html
http://www.cjsdn.net/post/page?bid=20&sty=3&tpg=2&s=73&age=0
https://sourceforge.net/forum/forum.php?forum_id=206693
http://www.cjsdn.net/post/view?bid=11&id=172565&sty=1&tpg=1&age=0Windows
环境下的tomcat + apache配置(绝对实践操作版)

ibatis大体上可以分为两个部分:SQL Maps + Data Access Objects
我现在的项目中都用到了,它提供的jpetstore就使用了db layer,可以参考它的实现方式。
不过我觉得jpetstore的db layer实现方式还不是太好,至少它的业务逻辑层和dao层没有明显区分,在实现比较

大的项目的时候造成了程序的混乱,如果没有一个良好的模式来实现db layer 的时候,确实会造成效率的低下,

有了良好的架构,速度确实很快(特别是SQL Maps + Data Access Objects 都使用的情况)
BO层的设计已经不是什么新鲜的了,但我觉得它确实可以很好的和DaoManager结合起来,通过DaoManager->SQL

map->jdbc
它的两个核心的配置文件:dao.xml+SqlMapConfig.xml
通过灵活的配置文件的组合可以实现数据库不同的访问组合
比如:一个dao.xml可以对应多个SqlMapConfig.xml
一个dao.xml可对应一个数据库,多个dao.xml就可以访问多个数据库了(它的petstore就提供了演示distributed

功能的样例是oracle+ms sql)
它的SqlMapConfig.xml中可配置sql-map resource,就是配置你具体的sql语句的xml文件。
它的sqlMap提供很多方法来访问数据库,直接返回你想要的结果

***************************
DAO中的一个供分页查询的方法
***************************
......

SqlMap sqlMap = getSqlMapFromLocalTransaction();//取到当前sqlmap对象
List list=sqlMap.executeQueryForList("你的MappedStatement文件中sql语句的名称", object("你可以通过这

个object传一些查询条件"),skipResults,maxResults);

...

有了良好的设计模式,它可以和struts完美结合在一起,无论是效率还是清晰型上,都非常令人满意的

public void saveUser(User user)
    {
        if (user.getId() == null)
        {
                Long id = (Long) getSqlMapClientTemplate().insert("addUser", user);
            logger.info("new User id set to: " + id);
        } else {
            getSqlMapClientTemplate().update("updateUser", user);
        }
       
    }   

domain is the central business tier. service package is more like a web package, just a way to

expose these services remotely, so that users could use the web interfaces, or the webservice

interfaces(like amazon's webservices).


//TestA.javapublic class TestA{public static void main(String[] args){TestA a=new TestA

();System.out.println(a.getClass().getClassLoader());TestB b=new TestB();b.print

();}}//TestB.javapublic class TestB{public void print(){System.out.println(this.getClass

().getClassLoader());}}

DAO(data access objects)允许你去创建简单的组件,为你访问你的数据,而不用去实现具体的实现细节。使用

DAOS你能动态配置不同的持久层机制。
注意:DAO框架与sqlmaps框架是完全的分离开和互不依赖性,所以你可以单独使用,或一起来用都没有关系.

下面是一些重要的daos api
DaoManager(Facade模式):负责配置DAO框架实例(经过dao.xml),在其它api当中充当facade.
DaoTransaction(Marker Interface):通用的接口,为了去使用事物(连接),通用的实现将包装jdbc的连接对象

.
DaoException(RuntimeException运行期异常):所有的方法和类全部抛出dao api专有的异常。
Dao(Marker Interface):一个标记接口供所有的dao去实现,这个接口必须为所有的dao类去实现。这个接口没有

声名任何方法被实现,只是充当一个标记(例如:一些DaoFactory去辩别不同的类);
-----------------------------------
jdbc事务控制实现
sqlmap:通过sqlmaps框架和它的事物管理服务去实现,包括不同的DataSource和事物管理配置
hibernate:提供简单容易的和hibernate,它的事物工具(SessionFactory,Session,Transaction)整合
jdbc:通过jdbc api,使用它的基本的dataSource和Connction接口去管理事物
jta:管理分部式事物,需要被管理的datasource,这样子可以通过jndi访问.
external:允许事物被外部控制

dao.xml为配置文件(http://www.ibatis.com/dtd/dao-2.dtd)
DaoManager负责配置dao框架。DaoManager类可以为框架解析特定的xml文件,而提供出有用的信息供框架使用。

那么配置文件(xml文件)需要指定下面的内容:
1)dao的上下文
2)事物为每一个上下文件的实现
3)TransactionManager配置属性
4)Dao为每一个实现的dao接口
一个Dao上下文是一组相关的配置信息和Dao实现。通常一个上下文关联到一个数据源(datasource)或一个文件。
dao配置文件(通常被叫做dao.xml,但不是必须的),为下面的结构
<!DOCTYPE daoConfig
PUBLIC "-//iBATIS.com//DTD DAO Configuration 2.0//EN"
"http://www.ibatis.com/dtd/dao-2.dtd">
<
daoConfig>
<properties resource="com/domain/properties/MyProperties.properties"/>
<!-- Example JDBC DAO Configuration -->
<context>
<transactionManager type="JDBC">
<property name="DataSource" value="SIMPLE"/>
<property name="JDBC.Driver" value="${driver}"/>
<property name="JDBC.ConnectionURL" value="${url}"/>
<property name="JDBC.Username" value="${username}"/>
<property name="JDBC.Password" value="${password}"/>
<property name="JDBC.DefaultAutoCommit" value="true" />
<property name="Pool.MaximumActiveConnections" value="10"/>
<property name="Pool.MaximumIdleConnections" value="5"/>
<property name="Pool.MaximumCheckoutTime" value="120000"/>
</transactionManager>
<dao interface="com.domain.dao.OrderDao"
implementation="com.domain.dao.jdbc.JdbcOrderDao"/>
<dao interface="com.domain.dao.LineItemDao"
implementation="com.domain.dao.jdbc.JdbcLineItemDao"/>
<dao interface="com.domain.dao.CustomerDao"
implementation="com.domain.dao.jdbc.JdbcCustomerDao"/>
</context>
<!-- Example SQL Maps DAO Configuration -->
<context>
<transactionManager type="SQLMAP">
<property name="SqlMapConfigResource" value="com/domain/dao/sqlmap/SqlMapConfig.xml"/>
</transactionManager>
<dao interface="com.domain.dao.PersonDao"
implementation="com.domain.dao.sqlmap.SqlMapPersonDao"/>
<dao interface="com.domain.dao.BusinessDao"
implementation="com.domain.dao.sqlmap.SqlMapBusinessDao"/>
<dao interface="com.domain.dao.AccountDao"
implementation="com.domain.dao.sqlmap.SqlMapAccountDao"/>
</context>
</daoConfig>
一个dao.xml里可以有多个context,通常一个上下文指定一个特定的dataSource
为了去管理多样的配置(因为有不同的环境),你可以使用可选的元素<properties).
这个允许使用占用符,例如:
driver=org.postgresql.Driver
url=jdbc:postgresql://localhost:5432/test
这时你可以在dao.xml里用占用符取代具体的值,例如上面的可以改写成下面的
<property name="JDBC.Driver" value="${driver}"/>
<property name="JDBC.ConnectionURL" value="${url}"/>
在上下文当中,第一个context里同使用的是jdbc事物控制,所以在指定的property元素也要使用jdbc,不同的事

物管理实现会需要不同的properties,

事物管理实现(Transaction Manager Implementation and Configuration)是一个组件会管理pool(事物对象)

,一事物管理通常只是包装特定的DataSource,简单的事物通常包装一特定的实现类如jdbc连接实现

jdbc Transaction Manager:利用提供的datasource api提供连接池服务
有三种datasource是支持的(simple,dbcp,jndi),simple是实现了ibatis的SimpleDataSource。dbcp使用了

jakarta dbcp datasource,最后,jndi是实现了查找datasource是从jndi上去查
下面是不同的配置方法
<!-- Example iBATIS SimpleDataSource JDBC Transaction Manager -->
<transactionManager type="JDBC">
<property name="DataSource" value="SIMPLE"/>
<property name="JDBC.Driver" value="${driver}"/>
<property name="JDBC.ConnectionURL" value="${url}"/>
<property name="JDBC.Username" value="${username}"/>
<property name="JDBC.Password" value="${password}"/>
<property name="JDBC.DefaultAutoCommit" value="true" />
<!-- The following are optional -->
<property name="Pool.MaximumActiveConnections" value="10"/>
<property name="Pool.MaximumIdleConnections" value="5"/>
<property name="Pool.MaximumCheckoutTime" value="120000"/>
<property name="Pool.TimeToWait" value="10000"/>
<property name="Pool.PingQuery" value="select * from dual"/>
<property name="Pool.PingEnabled" value="false"/>
<property name="Pool.PingConnectionsOlderThan" value="0"/>
<property name="Pool.PingConnectionsNotUsedFor" value="0"/>
</transactionManager>

<!-- Example Jakarta DBCP JDBC Transaction Manager -->
<transactionManager type="JDBC">
<property name="DataSource" value="DBCP"/>
<property name="JDBC.Driver" value="${driver}"/>
<property name="JDBC.ConnectionURL" value="${url}"/>
<property name="JDBC.Username" value="${username}"/>
<property name="JDBC.Password" value="${password}"/>
<property name="JDBC.DefaultAutoCommit" value="true" />
<!-- The following are optional -->
<property name="Pool.MaximumActiveConnections" value="10"/>
<property name="Pool.MaximumIdleConnections" value="5"/>
<property name="Pool.MaximumWait" value="60000"/>
<!-- Use of the validation query can be problematic. If you have difficulty, try without it. -->
<property name="Pool.ValidationQuery" value="select 1 from ACCOUNT"/>
<property name="Pool.LogAbandoned" value="false"/>
<property name="Pool.RemoveAbandoned" value="false"/>
<property name="Pool.RemoveAbandonedTimeout" value="50000"/>
</transactionManager>


<!-- Example JNDI DataSource JDBC Transaction Manager -->
<transactionManager type="JDBC">
<property name="DataSource" value="JNDI"/>
<property name="DBJndiContext" value="java:comp/env/jdbc/MyDataSource"/>
</transactionManager>

jta管理事物:它使用的是jta api.实种实现总是需要通过jndi去获得datasource和一个UserTransaction实例也

是通过jndi访问的,因些需要在服务器配置一下,不过这使得配置dao框架十分简单了。下面是一个简单的配置
<transactionManager type="JTA">
<property name="DBJndiContext" value="java:comp/env/jdbc/MyDataSource"/>
<property name="UserTransaction" value="java:comp/env/UserTransaction"/>
</transactionManager>

sqlmap管理事物:通过dao框架包装sql maps事物服务,所有的你都要指定一个sql maps配置文件。下面是一个简

单的配置
<transactionManager type="SQLMAP">
<property name="SqlMapConfigResource" value="com/domain/dao/sqlmap/SqlMapConfig.xml"/>
</transactionManager>

hibernate管理事物:同样的,通过dao框架包装hibernate事物服务,基本上properties在配置文件当中和

hibernate.properties文件是一样的,另外,持久化类(你可能通过添加到hibernate配置文件当中去的)要

以"class."开头,下面是一个例子:
<transactionManager type="HIBERNATE">
<property name="hibernate.dialect" value="net.sf.hibernate.dialect.PostgreSQLDialect"/>
<property name="hibernate.connection.driver_class" value="${driver}"/>
<property name="hibernate.connection.url" value="${url}"/>
<property name="hibernate.connection.username" value="${username}"/>
<property name="hibernate.connection.password" value="${password}"/>
<property name="class.1" value="com.domain.Person"/>
<property name="class.2" value="com.domain.Business"/>
<property name="class.3" value="com.domain.Account"/>
</transactionManager>

external 管理事物:允许使用dao框架控制。这个执行基本是没有行为,因些不需要properties,如果你使用一个

flat file,你可以使用external事物管理,
<transactionManager type="EXTERNAL"/>

dao实现模板:你可能要问我怎么使用上面的事物,好了每一种事物类型都要相应的dao模板与之对应。例如:

jta,jdbc模板提供简单的访问jdbc连接对象。相似的sqlmap模板提供访问简单的SqlMapExecutor实例,而

hibernate template提供访问Session object.
使用dao template完全是可选的,但99%的时间里,是不可不选择的/

更多的模板请看下面的.
DaoManager编程:iBATIS dao框架有许多的目的.第一个,它试图持久层的细节.这包括所有的接口,实现和异

常细节(在你的持久层解决方案当中).
例如:如果你使用jdbc,dao框架将为你隐藏类如DataSource,Connection和SQLException.类似的,如果你使用

Hibernate orm,dao框架会为你隐藏类如Configuration,SessionFactory,Session和HibernateException.所有的

这些细节都会隐藏到了dao接口层.甚至在显示层的许多的datasource也会被隐藏.
第二个目的是:简化持久层编程模型,使在同一时间保持一致.不同的持久层解决方案有不同的编程语义和行为.
dao框架试图隐藏更多,允许在你的应用service和domain层,写出一致的风格.

DaoManager类负责dao框架的配置文件(通过dao.xml),另外,DaoManage扮演着中心门面的角色,它特殊之处是,还提

供方法允许你访问事物和dao实例.

读取配置文件:
使用DaoManagerBuilder类的静态方法buildDaoManager()方法读取dao.xml文件,buildDaoManager()方法需要一个

Reader实例作为参数.
例如:
Reader reader = new FileReader(C:/myapp/dao.xml);
DaoManager daoManager = DaoManagerBuilder.buildDaoManager(reader);

如在web应用环境当中(或其它),一般配置文件都会从classpath当中去加载的.我们可以使用

com.ibatis.common.resources.Resources类
Reader reader = Resources.getResourceAsReader(“com/domain/config/dao.xml”);
DaoManager daoManager = DaoManagerBuilder.buildDaoManager(reader);

Context和DaoManager
DaoManager实例是从dao.xml文件建立的.当你需要一个dao实例时,你可以通过DaoManager,和事物控制也会从它此

处提供的.因些不需直接访问context和事物管理..
你的dao知道它怎么去做.类似的,需要看你的daos怎么工作的,事物会恰当的开始和提交的.而且,事物仅在你的dao

被调用时才启动.

获取dao实例
一旦你得到了DaoManager实例,你就可以根据dao名字,利用DaoManager的getDao方法获取该dao实例了,如:
ProductDao productDao = (ProductDao) daoManager.getDao (ProductDao.class);

DaoManager提供了处理事务的方法.这些方法允许你划分事务,和避免传递事务对象(eg:jdbc Connction)到你的所

有的daos当中去.例如:
ProductDao productDao = (ProductDao) daoManager.getDao (ProductDao.class);
try {
daoManager.startTransaction();
Product product = productDao.getProduct (5);
product.setDescription (“New description.”);
productDao.updateProduct(product);
daoManager.commitTransaction();
} finally {
daoManager.endTransaction();
}
调用startTransaction()只是让DaoManager知道,你将要启动编程控制事务.
dao实例化时才启动事务的,甚至事务仅仅是contexts需要的时候.
commitTransaction()提交事务,endTransaction()需要在try{}catch(){}里面的,,
如果发现了异常,那么就会回滚.

自动提交事务
像jdbc的setAutoCommit(true)一样,不过也有不同之处,你可以使用多个update作为一个事务,你不需要指定提交

的行为方式,只要你不调用startTransaction()就行了
Product product = productDao.getProduct (5); // Transaction 1
product.setDescription (“New description.”);
productDao.updateProduct(product); // Transaction 2
product = productDao.getProduct (5); // Transaction 3
注意了,这里没有异常的事件发生的,如发生异常,就会回滚,和释放连接资源的.

实现自己的dao接口:
dao接口非常的简单,因为它没有声名任何的方法,只是一个marker interface,所以实现的只是你自己的接口罢了,

在你的接口当中没有限制你要定的任何方法,抛出的异常是运行期的DaoException类型的异常.
An example of a good Dao interface is:
public interface ProductDao extends Dao {
// Updates
public int updateProduct (Product product); // DAO Framework code may throw DaoException
public int insertProduct (Product product);
public int deleteProduct (int productId);
/
/ Queries
public Product getProduct (int productId);
public List getProductListByProductDescription (String description);
}

Templates和Implementations
在上面也提到了,每一种模板都对应一种特殊的Transaction Manager.
每一种模板提供了一种便利的方法去交互.
template Class       Transaction Manager        Convenience Method
JdbcDaoTemplate      JDBC                       Connection getConnection()
JtaDaoTemplate       JTA                        Connection getConnection();
SqlMapDaoTemplate    SQLMAP                     SqlMapExecutor getSqlMapExecutor()
HibernateDaoTemplate  HIBERNATE             Session getSession()

The following is an example implementation using the SqlMapDaoTemplate:
public class SqlMapProductDao implements ProductDao extends SqlMapDaoTemplate {
public SqlMapProductDao (DaoManager daoManager) {
super (daoManager);
}
/
* Insert method */
public int updateProduct (Product product) {
try {
getSqlMapExecutor().insert (“insertProduct”, product);
} catch (SQLException e) {
throw new DaoException (“Error inserting product. Cause: “ + e, e);
}
}
/
/ … assume remaining methods to save space
}
注意:在上面的例子里只有一些个构造器,参数为DaoManager,它是在初始化实例时通过DaoManagerBuilder自动注

入参数进去..第一个需要DaoManager作为构造器的参数,也就迫使它的子类都要一个带参(DaoManager)的构造器,

当你使用模板时,构造器是必须的,你不需要提供其它的构造器了..你的daos仅仅需要DaoManagerBuilder去实例化

它.

考虑dao的设计方式:
推荐使用一个继承dao接口的接口,另一个为一个继承dao接口的抽象类(封闭一些异常,事务等等)..
实际上你只需要一个就行了,另外你也可以选择下面这种方式..
你可以使用BaseJdbcDao(abstract)继承dao接口,需让ProductDao不要去断承dao接口,让ProductJdbcDao去实现

ProductDao和继承BaseJdbcDao就可以了,让Product接口仍然与dao分离开来....
在上面的例子当中可以将BaseJdbcDao继承JdbcDaoTemplate(它已经实现了dao接口)


现在做一个例子:
create table test
(
id int auto_increment;
name varchar(20)
);

建一个对应的vo
package zhai;

public class test {
 int id;
 String name;
public int getId() {
 return id;
}
public void setId(int id) {
 this.id = id;
}
public String getName() {
 return name;
}
public void setName(String name) {
 this.name = name;
}
}

建一个配置数据库的配置文件
config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig
    PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
    "http://www.ibatis.com/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
  <transactionManager type="JDBC">
    <dataSource type="SIMPLE">
      <property value="com.mysql.jdbc.Driver" name="JDBC.Driver"/>
      <property value="jdbc:mysql://localhost:3306/test" name="JDBC.ConnectionURL"/>
      <property value="root" name="JDBC.Username"/>
      <property value="root" name="JDBC.Password"/>
    </dataSource>
  </transactionManager>
  <sqlMap url="file:C:\Test\sql.xml"/>
</sqlMapConfig>


--
sql.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 namespace="test">
  <typeAlias alias="test" type="test.test"/>
  <select id="getByName" resultClass="test" parameterClass="string">
    SELECT
     ID,
     NAME
    FROM TEST
    WHERE NAME = #name#
  </select>
</sqlMap>

----------------
------------------
package zhai;

public interface MyDao {
  public void MyInsert(test t);
}
==================
package zhai;

import java.sql.SQLException;

import com.ibatis.dao.client.DaoManager;
import com.ibatis.dao.client.template.SqlMapDaoTemplate;

public class TestDao extends SqlMapDaoTemplate implements MyDao{

 public TestDao(DaoManager arg0) {
  super(arg0);
  // TODO Auto-generated constructor stub
 }

 public void MyInsert(test t) {
  try {
   getSqlMapExecutor().insert ("insertTest",t);
  } catch (SQLException e) {
   System.out.println("插入时出异常");
   e.printStackTrace();
  }
 }

}

============
package zhai;
import java.io.*;

import com.ibatis.sqlmap.client.*;
public class TestDemo {

 public static void main(String[] args) throws Exception {
  Reader reader=new FileReader("C:\\Test\\config.xml");
     SqlMapClient sqlmap=SqlMapClientBuilder.buildSqlMapClient(reader);
     test emp = (test) sqlmap.queryForObject("getById", new Integer(1));
        System.out.println("欢迎你="+emp.getName());
 }

}
-------------------------------------------------

-------------------------------------------------

-------------------------------------------------

-------------------------------------------------

-------
写一个运行dao的
<!DOCTYPE daoConfig
PUBLIC "-//iBATIS.com//DTD DAO Configuration 2.0//EN"
"http://www.ibatis.com/dtd/dao-2.dtd">
<daoConfig>
<!-- Example JDBC DAO Configuration -->
<context>
    <transactionManager type="SQLMAP">
     <property name="SqlMapConfigResource" value="zhai/config.xml"/>
    </transactionManager>
<dao interface="zhai.MyDao" implementation="zhai.TestDao"/>
</context>
</daoConfig>
----------------------
--------------------
<?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 namespace="test">
  <typeAlias alias="test" type="zhai.test"/>
  <select id="getById" resultClass="test" parameterClass="int">
    SELECT
     ID,
     NAME
    FROM TEST
    WHERE ID = #id#
  </select>
  <insert id="insertTest" parameterClass="test">
    insert into TEST (NAME) values (#name#)
  </insert>
 
</sqlMap>
--------------------------------------------------------------------------------------------------

---------------------------------------------
package zhai;
import java.io.*;

import com.ibatis.dao.client.DaoManager;
import com.ibatis.dao.client.DaoManagerBuilder;
import com.ibatis.sqlmap.client.*;
public class TestDemo {

 public static void main(String[] args) throws Exception {
                //Reader reader = Resources.getResourceAsReader("zhai/dao.xml");
  Reader reader=new FileReader("C:\\Test\\dao.xml");
  DaoManager daoManager = DaoManagerBuilder.buildDaoManager(reader);
  MyDao testdao = (MyDao) daoManager.getDao(MyDao.class);
  test t=new test();
  t.setName("test");
  testdao.MyInsert(t);
 }

}


注意了如果你用的是
Reader reader = Resources.getResourceAsReader("zhai/dao.xml");
那么你就得注意事了,dao.xml要放在项目的bin目录下面,否则就会出错
还有在dao.xml里的  <transactionManager type="SQLMAP">
     <property name="SqlMapConfigResource" value="zhai/config.xml"/>
    </transactionManager>
也是一个道理呀

posted on 2006-07-24 00:48 蜘蛛 阅读(4097) 评论(4)  编辑  收藏 所属分类: hibernate

评论

# re: 学习一下ibaties 2006-07-24 10:35 Compass
拜托,专业点,先把名字写对  回复  更多评论
  

# re: 学习一下ibatis 2006-07-25 14:02 剑事
我在自己的网站应用了ibatis 感觉还不错 结合Spring比较好
http://www.migti.com  回复  更多评论
  

# re: 学习一下ibatis 2006-07-31 17:08 蜘蛛小子
剑事大哥,我知道你刚从德国留学毕业了,
恭喜你呀!我现在还没有具体的把ibatis用到工程里去,而且现在这方面的资料又不多,听说现在进在出一本ibatis in action,不过现在好像还没有出来,,不知道你那里有没有相关的资料,,分享一下好么,,我的邮箱javazhai@126.com  回复  更多评论
  

# re: 学习一下ibatis 2006-08-03 07:24 剑事
你从哪听说我去德国留学????????????

我很是吃惊啊

我只有官方的中文指南比较全  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: