﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Open-Open-随笔分类-iBATIS</title><link>http://www.blogjava.net/realzar/category/11155.html</link><description>皇家撒拉哥萨</description><language>zh-cn</language><lastBuildDate>Thu, 01 Mar 2007 14:22:24 GMT</lastBuildDate><pubDate>Thu, 01 Mar 2007 14:22:24 GMT</pubDate><ttl>60</ttl><item><title>基于struts+spring+ibatis的轻量级J2EE开发</title><link>http://www.blogjava.net/realzar/archive/2006/06/05/50379.html</link><dc:creator>开源爱好者</dc:creator><author>开源爱好者</author><pubDate>Sun, 04 Jun 2006 16:09:00 GMT</pubDate><guid>http://www.blogjava.net/realzar/archive/2006/06/05/50379.html</guid><wfw:comment>http://www.blogjava.net/realzar/comments/50379.html</wfw:comment><comments>http://www.blogjava.net/realzar/archive/2006/06/05/50379.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/realzar/comments/commentRss/50379.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/realzar/services/trackbacks/50379.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 多数				IT 						组织都必须解决三个主要问题：				1						．帮助组织减少成本				 2						．增加并且保持客户								3								．加快业务效率。完成这些问题一般都需要实现对多个业务系统的数据和业务逻辑的无缝访问，也就是说，要实施系统集成工程，以便联结业务流程、实现数据的访问与共享。...&nbsp;&nbsp;<a href='http://www.blogjava.net/realzar/archive/2006/06/05/50379.html'>阅读全文</a><img src ="http://www.blogjava.net/realzar/aggbug/50379.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/realzar/" target="_blank">开源爱好者</a> 2006-06-05 00:09 <a href="http://www.blogjava.net/realzar/archive/2006/06/05/50379.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>iBatis DAO入门与进阶</title><link>http://www.blogjava.net/realzar/archive/2006/05/30/49067.html</link><dc:creator>开源爱好者</dc:creator><author>开源爱好者</author><pubDate>Tue, 30 May 2006 09:27:00 GMT</pubDate><guid>http://www.blogjava.net/realzar/archive/2006/05/30/49067.html</guid><wfw:comment>http://www.blogjava.net/realzar/comments/49067.html</wfw:comment><comments>http://www.blogjava.net/realzar/archive/2006/05/30/49067.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/realzar/comments/commentRss/49067.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/realzar/services/trackbacks/49067.html</trackback:ping><description><![CDATA[
		<center>
				<b>
						<span style="FONT-SIZE: 20px">iBatis DAO入门与进阶</span>
				</b>
		</center>
		<br />
		<center>作者：Sunil Patil</center>
		<br />
		<center>译者:<a href="http://www.matrix.org.cn/user.shtml?username=rotter_pal" target="_new">rotter_pal</a></center>
		<br />
		<br />
		<br />
		<br />
		<br />
		<span style="COLOR: red">版权声明：任何获得Matrix授权的网站，转载时请<b>务必</b>以超链接形式标明文章原始出处和作者信息及本声明</span>
		<br />作者:Sunil Patil;<a href="http://www.matrix.org.cn/user.shtml?username=rotter_pal" target="_new">rotter_pal</a><br />原文地址:<a href="http://www.onjava.com/pub/a/onjava/2005/08/10/ibatisdao.html" target="_new">http://www.onjava.com/pub/a/onjava/2005/08/10/ibatisdao.html</a><br />中文地址:<a href="http://www.matrix.org.cn/resource/article/44/44058_iBatis+DAO.html" target="_new">http://www.matrix.org.cn/resource/article/44/44058_iBatis+DAO.html</a><br />关键词： iBatis DAO<br /><br /><br />在核心J2EE模式中是这样介绍DAO模式的：为了建立一个健壮的J2EE应用，应该将所有对数据源的访问操作抽象封装在一个公共API中。用程序设计的语言来说，就是建立一个接口，接口中定义了此应用程序中将会用到的所有事务方法。在这个应用程序中，当需要和数据源进行交互的时候则使用这个接口，并且编写一个单独的类来实现这个接口在逻辑上对应这个特定的数据存储。<br /><br />比如考虑在iBatis: SQL Maps中的应用例子。这是一个Struts应用允许对一个关系表执行SELECT, INSERT, UPDATE和DELETE的SQL请求。在这个应用中，使用SQL Maps做持续性框架。现在我们要修改这个应用，将这个关系表储存在一个XML文件中而不是存在关系数据库中，或者使用Hibernate来实现SELECT请求，而用SQL Map来执行其他请求，因为Hibernate提供了对高速缓存更好的支持。这样的修改很难实现，或者即使我们能修改而实现了这个功能，也会是很混乱的解决方案。<br /><br /><br />对于这类问题更好的解决方法是建立一个ContactDAO接口，在这个接口中定义处理SELECT, INSERT, UPDATE, 和DELETE 请求的事务方法。然后根据不同的事务逻辑建立不同的类实现各个方法。所以可能会有一个类处理使用SQL Maps同关系表进行交互的情况，而另外一个类处理用XML文件存放关系表而不是关系数据库的情况，等等。在项目中，根据实际的需要从不同的ContactDAO中选择相应的实现。这种关系见图1：<br /><br /><img onmouseover="javascript:imgShowTip(this);" style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="image" src="http://www.matrix.org.cn/resource/upload/article/2005_12_18_224911_SOAyTyFzWZ.gif" onload="javascript:imgLoad(this);" border="0" resized="0" /><br />图1. ContactDAO 接口及实现<br /><br />iBatis DAO是由Apache主持的开源框架项目，主要目标是为了解决这类问题。它允许在工程中以DAO模式为基础建立应用。这就意味着可以建立一个XML文件，并声明XMLContactDAO.java是ContactDAO的实现类，这个类知道如何从XML文件中读写数据。SQLMapContactDAO则知道如何用SQL Maps作为持续化框架与关系表进行交互。在工程中，如果向DAO框架提交一个需要XML的ContactDAO请求，框架则会返回一个XMLContactDAO对象。同样的DAO框架提供了唯一的接口处理事务管理，这个接口能实现与数据的存储方式无关。它同样考虑了底层连接管理细节和初始化存储框架。<br /><br />这篇文章是关于如何一步一步的在项目中应用iBatis DAO框架的基础指导。我们将由如何把SQL Maps一文中的应用实例改为应用DAO框架入手。然后，我们要讨论DAO框架的构造。再下一步，我们关注事务管理是如何在DAO框架中得到支持的。最后一部分是关于如何建立自己的事务管理模块。<br /><br /><b><span style="FONT-SIZE: 16px">示例应用</span></b><br /><br />首先，我们将SQL Maps一文中的例子改为应用DAO框架。<br />1.        将ibatis-dao-2.jar文件复制到WEB-INF/lib目录下。<br />2.        在Java源程序的目录里新建一个如下的DAOMap.xml文件<br /><b>清单1：</b><br /><pre class="overflow">&lt;daoConfig&gt;<br /> &lt;context id="sqlmap"&gt;<br />  &lt;transactionManager type="SQLMAP"&gt;<br />  &lt;property name="SqlMapConfigResource" value=<br />   "com/sample/contact/dao/sqlmap/SqlMapConfig.xml"/&gt;<br />  &lt;/transactionManager&gt;<br />  &lt;dao interface="com.sample.contact.dao.ContactDAO"<br />   implementation=<br />   "com.sample.contact.dao.sqlmap.SQLMapContactDAO"/&gt;<br /> &lt;/context&gt;<br />&lt;/daoConfig&gt;</pre><br /><br />DAOMap.xml是发布iBatis DAO框架的配置文件。&lt;daoConfig&gt;是根元素，每个&lt;context&gt;元素描述了一种存储机制。在这个例子中只使用了SQL Maps来存储，所以我们这里只有一个&lt;context&gt;元素。每种存储机制必须包含一个&lt;transactionManager&gt;元素，这个元素描述连接它后面的数据存储所用的管理器，并且标记事务的界限。我们将在稍后再讨论transactionManager。<br /><br />&lt;context&gt;元素还包括一组DAO用于描述其他的存储管理机制。在这个例子中，我们将生成一个使用SQL Maps存储的ContactDAO，所以在配置文件中添加一个ie&lt;dao&gt;标记来定义SQLMapContactDAO。<br /><br />3.        建立ContactDAO.java,如下：<br /><b>清单2：</b><br /><pre class="overflow">public interface ContactDAO extends DAO {<br />    public int insertContact(Contact contact);<br />    public int updateContact(Contact contact);<br />    public Contact selectContact(int contactId);<br />    public int deleteContact(int contactId);<br />} </pre>   <br /><br />ContactDAO.java定义了用户和一个关系表进行交互所需要用到的所有事务处理方法。请注意到ContactDAO.java中的所有方法都将一个Contact对象作为参数，这是一个用来携带数据的数据传递对象。<br /><br /><br />4.        建立一个SQLMapContactDAO.java文件，如下<br /><b>清单3：</b><br /><pre class="overflow">public class SQLMapContactDAO extends<br /> SqlMapDaoTemplate implements ContactDAO {<br />  public SQLMapContactDAO(DaoManager arg0) {<br />      super(arg0);<br />  }<br />  public int deleteContact(int contactId) {<br />    return super.delete("deleteContact",<br />    new Integer(contactId));<br />  }<br />  public int insertContact(Contact contact) {<br />    Integer contactId =(Integer)super.insert<br />      ("insertContact",contact);<br />    return contact.getContactId();<br />  }<br />  public Contact selectContact(int contactId) {<br />    return (Contact)super.queryForObject("getContact",<br />      new Integer(contactId));<br />  }<br />  public int updateContact(Contact contact) {<br />    return super.update("updateContact",contact);<br />  }<br />}</pre><br /><br />SQLMapContactDAO是ContactDAO接口的具体实现，它用SQL Maps作为存储管理机制。注意到我们并没有写任何代码来或者初始化SQL Maps，或得到一个连接，或者在类中标注一个事务的界限。相反，我们继承SqlMapDaoTemplate.java类，它帮我们处理下层的、反复的操作。我们在SQLMapContactDAO类中需要考虑的唯一的事情就是事务处理逻辑。<br /><br />5.        修改ContactSelectAction.java类中的execute()方法，如下：<br /><b>清单4：</b><br /><pre class="overflow">Contact contactForm = (Contact) form;<br />Reader reader=<br />  Resources.getResourceAsReader("DAOMap.xml");<br />DaoManager daoManager =<br />  DaoManagerBuilder.buildDaoManager(reader);<br />ContactDAO contactDAO =<br />  (ContactDAO) daoManager.getDao(<br />ContactDAO.class,"sqlmap");<br /><br />request.setAttribute("contactDetail",<br />  contactDAO.selectContact(<br />    contactForm.getContactId()));</pre><br /><br />最后一步是修改ContactSelectAction类中的execute()方法，使它使用DAO框架。为了初始化DAO框架，我们需要一个为DAOMap.xml 准备一个Reader对象。iBatis框架为我们提供了方法Resources.getResourceAsReader()来读取资源。一旦有了Reader对象来读取DAOMap.xml，就能将它们读取至DAOManagerBuilder.buildDaoManager()，返回一个DaoManager实例，将来用于与DAO框架进行交互。从理论上来说，应该在项目启动的时候初始化DAO框架，在我们这个程序中，可以将这个模块放入Struts插件中，但是为了简化这个例子，我们将初始化模块放入execute方法中。<br /><br />有了DaoManager实例后，可以调用相应的接口和存储实现类(在&lt;context&gt;元素中的id属性值)的getDao()方法。在我们的例子中，需要一个SQLMapContactDAO的实例，所以以ContactDAO为接口名称，“sqlmap”为存储机制。一旦实现了SQLMapContactDAO实例，就可以在调用其中的事务方法。<br /><br />在最后的资源章节中可以下载到这个例子的源码。<br /><br /><b><span style="FONT-SIZE: 16px">DAO框架架构</span></b><br /><br />由于有了一个可以运行的示例，让我们得以粗略了解DAO框架是如何运作的。在图2表示的顺序图中演示了DAO的工作方式：<br /><br /><img onmouseover="javascript:imgShowTip(this);" style="DISPLAY: inline" onclick="javascript:imgClick(this);" height="450" alt="image" src="http://www.matrix.org.cn/resource/upload/article/2005_12_18_224916_OkWdiCStgH.gif" width="553" onload="javascript:imgLoad(this);" border="0" resized="1" /><br />图2. DAO顺序图<br /><br />在开始时，调用DaoManagerBuilder.buildDaoManager()并传入DAOMap.xml来初始化DAO框架。在这个方法中DAO框架会读取DAOMap.xml并且由此生成相应的DAOManager对象。这个对象包括了对支持的数据存储机制的描述。哪个接口会被实现，哪个是接口和存储机制结合的实现类？基本上这是和DAOMap.xml文件相等的 Java对象。<br /><br />当有了DAOManager对象，可以从中得到ContactDAO接口的SQL Map实例。DAO框架会返回一个包装了实现类的DaoProxy对象。在本例子中将给SQLMapContactDAO返回一个DaoProxy对象。这个DaoProxy对象允许DAO框架截获调用商业方法。本例中，当调用 contactDAO.selectContact()时，DAO框架会截获这个调用并检查事务处理是否已经开始执行，如果没有，它将调用事务管理器中的startTransaction()创建一个新的事务处理调用。如果处理已经开始，DaoProxy对象会调用事务中的SQLMapContactDAO中的selectContact()方法。当selectContact()调用返回的时候，DaoProxy对象截获返回并提交给事务。<br /><br />如果不希望事务在方法层上可见，或者希望在一个事务中调用多个不同的方法，则可在调用ContactDAO中的商业方法前调用daoManager.startTransaction()，然后在daoManager.startTransaction()执行完以后再提交商业方法。<br /><br />那么现在剩下要关心的事情就是那个模块负责存储机制的初始化并传递控制给存储机制。在这个例子中，就意味着由哪个模块负责将SqlMapConfig.xml的路径传递给SQL Map框架并给它初始化。同样意味着哪个模块负责和SQL Maps框架进行实际的交互。DAO框架为每种存储提供了Template类，在工程中，可以从这个Template类中继承实例类，并只要自己的方法中编写商业事务逻辑。然后将控制传递给这个模板类，它将负责和存储机制的交互。在我们的例子中调用super.queryForObject("getContact",new Integer(contactId))，意味着SqlMapDaoTemplate将负责SQL Maps的初始化和与之交互。<br /><br />初始化存储机制需要相关的一些信息，在例子中初始化需要SqlMapConfig.xml的路径，这个文件中包含驱动类的名字、JDBC URL、登陆信息之类的信息。这些特定的事务管理器需要的信息将会在DaoMap.xml文件中作为一个属性元素传递给管理器。下一节，我们将讨论DAO框架支持哪些事务管理器，每个管理器需要哪些初始化信息。<br /><br /><b><span style="FONT-SIZE: 16px">支持的存储管理机制</span></b><br /><br />DAO框架提供了内置的对一些存储管理机制的支持。为了使用其中的一个内置的transactionManagers，需要做两件事情：<br />1.在DAOMap.xml中增加一个&lt;transactionManager&gt;元素来声明对存储管理机制的支持。<br />2.在生成DAO实现类的时候为transactionManager继承适当的Template类。<br /><br />下面我们要研究内置transactionManagers并找出在应用程序中使用如何使用它们。<br /><br /><b>JDBC</b><br />如果不想使用任何存储框架，不想自己写JDBC代码，那么JDBC事务管理器是很好的选择。如果使用JDBC作为存储机制，则可以使用以下三种连接管理之一：<br /><br />SIMPLE：如果要使用iBatis'自己的连接池实例，可以把SIMPLE作为DataSource元素的值。将通常的JDBC属性(DriverManager类， JDBC URL，等等)传入作为Properties。在iBatis在线文档中查看更多的连接属性。<br /><b>清单5：</b><br /><pre class="overflow">&lt;transactionManager type="JDBC"&gt;<br /> &lt;property name="DataSource" value="SIMPLE"/&gt;<br /> &lt;property name="JDBC.Driver"<br />  value="com.ibm.db2j.jdbc.DB2jDriver"/&gt;<br /> &lt;property name="JDBC.ConnectionURL"<br />  value="jdbc:db2j:D:\cloudscape\wpsdb"/&gt;<br /> &lt;property name="JDBC.Username"<br />  value="db2admin"/&gt;<br /> &lt;property name="JDBC.Password"<br />  value="db2admin"/&gt;<br /> &lt;property name="JDBC.DefaultAutoCommit"<br />  value="true" /&gt;<br />&lt;/transactionManager&gt;</pre><br /><br /><br />DBCP：使用Apache DBCP作为连接管理。请查看DAO在线指导获得如何配置DBCP连接池的信息。<br /><br />JNDI：当要使用应用服务器的连接池，那么要做的是提供连接池的JNDI名，DAO框架则使用这个名称获得一个连接。<br /><b>清单6：</b><br /><pre class="overflow">&lt;transactionManager type="JDBC"&gt;<br /> &lt;property name="DataSource" value="JNDI"/&gt;<br /> &lt;property name="DBJndiContext"<br />  value="java:comp/env/jdbc/MyDataSource"/&gt;<br />&lt;/transactionManager&gt;</pre><br /><br /><br />然后要建立一个类继承JdbcDaoTemplate.java来实现事务方法借口。在示例中，我们建立了JDBCContactDAO.java。在事务方法中，可以调用getConnection()向父类请求连接。因为我们没有使用任何存储框架，所以我们只能建立并执行我们自己的SQL请求。<br /><b>清单7：</b><br /><pre class="overflow">public int updateContact(Contact contact) {<br /> try {<br />  Connection conn = getConnection();<br />  PreparedStatement updateStmt =<br />   conn.prepareStatement("UPDATE DB2ADMIN.CONTACT<br />    SET FIRSTNAME=?,LASTNAME=? WHERE CONTACTID=?");<br />  updateStmt.setString(1, contact.getFirstName());<br />  updateStmt.setString(2, contact.getLastName());<br />  updateStmt.setInt(3, contact.getContactId());<br />  return updateStmt.executeUpdate();<br /> } catch (SQLException ex) {<br />    throw new DaoException(ex);<br /> }<br />}</pre><br /><br />使用JDBC transactionManager的时候，DAO框架会调用Connection 对象中的commit和rollback方法来控制事务处理。所以事务会在Connection层被处理，而不参与全局事务处理。<br /><br /><b>JTA</b><br />如果项目是J2EE应用，那么使用应用服务器提供的连接池会更有利，因为它将比SIMPLE 或者DBCP 连接池有更好的性能。同样的，使用J2EE应用，RDBMS是唯一的处理源，除了RDBMS还需要包含JCA、MQ Server等功能。因为不能在连接层开始和处理事务，而要特别的在全局事务处理时在一个UserTransaction对象中调用begin()和commit()方法。所以对于这类请求，可以使用JTA 作为transctionManager,既可以向JNDI URL提供数据源连接池，也可以在里面包含UserTransaction对象。<br /><b>清单8：</b><br /><pre class="overflow">&lt;transactionManager type="JTA"&gt;<br /> &lt;property name="DBJndiContext"<br />  value="java:comp/env/jdbc/MyDataSource"/&gt;<br /> &lt;property name="UserTransaction"<br />  value="java:comp/env/UserTransaction"/&gt;<br />&lt;/transactionManager&gt;</pre><br /><br /><b>Hibernate</b><br />因为Hibernate是很常见的存储框架，iBatis DAO也提供了对它的支持。为了在项目中使用Hibernate，像下面那样在DAOMap.xml增加&lt;transactionManager&gt;元素：<br /><b>清单9：</b><br /><pre class="overflow">&lt;transactionManager type="HIBERNATE"&gt;<br /> &lt;property name="hibernate.dialect"<br />  value="net.sf.hibernate.dialect.Cloudscape"/&gt;<br /> &lt;property name="hibernate.connection.driver_class"<br />  value="com.ibm.db2j.jdbc.DB2jDriver"/&gt;<br /> &lt;property name="hibernate.connection.url"<br />  value="jdbc:db2j:D:\cloudscape\wpsdb"/&gt;<br /> &lt;property name="hibernate.connection.username"<br />  value="db2admin/&gt;<br /> &lt;property name="hibernate.connection.password"<br />  value="db2admin"/&gt;<br /> &lt;property name="class.1"<br />  value="com.sample.contact.Contact"/&gt;<br />&lt;/transactionManager&gt;</pre><br /><br /><br />同样的，需要建立一个DAO类继承HibernateDaoTemplate。在这个DAO内，可以通过调用getSession()方法来获得Hibernate Session对象的入口。<br /><br /><b>SQL MAP</b><br />请查看示例(在资源小节中)了解如何在项目中使用SQL Map存储框架的细节。<br /><br /><b>外部管理</b><br />外部的事务管理器允许事务处理在外部被DAO框架控制。这种行为有利于处理和非关系数据库数据源的交互。下一节，我们将讨论如何用DAO框架处理以XML文件作为数据源的情况。<br /><br /><br /><b><span style="FONT-SIZE: 16px">部署xml事务Map</span></b><br /><br />你可能也经常遇到这种情况：需要从xml中读取数据，而不是从RDBMS中读取，假想你正在从事一个银行项目，你并不能够直接接触到银行的数据库，所有的用户信息暂时都会通过一个XML文件传输给你，你必须使用这个XML文件进行开发，开发完毕再部署到真正的使用RDBMS的环境中，<br />这样的话，你需要做一下改变：<br /><br />1. 在DAOMap.xml 中增加对外部的transactionManager 的支持。<br />2. 新建一个XMLContactDAO.java文件:<br /><b>清单10：</b><br /><pre class="overflow">public class XMLContactDAO implements ContactDAO {<br /> public static final String<br />  CONTACTXMLNAME = "c:\\Contact.xml";<br /> public XMLContactDAO(DaoManager manager) {<br />    super(manager);<br /> }<br /> public int insertContact(Contact contact) {<br />  HashMap contactMap = loadChanges();<br />  if (contactMap.get(new Integer<br />    (contact.getContactId())) == null)<br />   contactMap.put(new<br />    Integer(contact.getContactId()), contact);<br />  saveChanges(contactMap);<br />  return contact.getContactId();<br /> }<br /> public Contact selectContact(int contactId) {<br />  HashMap contactMap = loadChanges();<br />  return (Contact) contactMap.get(<br />   new Integer(contactId));<br /> }<br /> public HashMap loadChanges() {<br />  HashMap contactMap = null;<br />  try {<br />   XStream xstream = new XStream(new DomDriver());<br />   xstream.alias("contact", Contact.class);<br />   contactMap =<br />    (HashMap) xstream.fromXML(<br />     new FileReader(CONTACTXMLNAME),HashMap.class);<br />  } catch (FileNotFoundException e) {<br />    e.printStackTrace();<br />    return new HashMap();<br />  }<br />  return contactMap;<br /> }<br /> public void saveChanges(HashMap contactMap) {<br />  try {<br />   XStream xstream = new XStream();<br />   xstream.alias("contact", Contact.class);<br />   xstream.toXML(contactMap,<br />    new FileWriter(CONTACTXMLNAME));<br />   } catch (IOException e) {<br />   e.printStackTrace();<br />  }<br /> }<br />}</pre><br /><br />这个例子中，XMLContactDAO实现了ContactDAO事务接口。因为我们使用了一个EXTERNAL事务管理器，所以不能使用任何已经存在的Template类。在我们的类中，我们使用XStream框架新建了两个简单的方法——loadChanges()和saveChanges()——实现对XML文件的读写。XStream是一个开源框架，实现将一个XML文件看作一个对象来读取，将对象保存为XML文件的功能。<br /><br /><b><span style="FONT-SIZE: 16px">结论</span></b><br />当今，有很多新的存储框架出现。这对于一个程序员既有好处也有坏处。好处是有更多的选择余地。坏处是因为你必须作出一个选择，更糟糕的是不得不在项目开始的时候就选择一种框架，这就意味着你可能不能完全清楚的了解项目的需求，或者不能完全确信这种框架是否能完全满足项目的需求。DAO是一种容易使用并且功能强大的框架能够处理存储机制的改变。你在前期作出了付出，但是它肯定会在最后对你有帮助的。<br /><br /><b><span style="FONT-SIZE: 16px">资源</span></b><br />·Matrix-Java开发者社区:<a href="http://www.matrix.org.cn/" target="_new">http://www.matrix.org.cn</a><br />·onjava.com:<a href="http://onjava.com/" target="_new">onjava.com</a><br />·这篇文章的示例代码：（注：与译文放入同一压缩包中）:<a href="http://www.onjava.com/onjava/2005/08/10/examples/SampleDAO.zip" target="_new">http://www.onjava.com/onjava/2005/08/10/examples/SampleDAO.zip</a><br />·iBatis主页：<a href="http://ibatis.apache.org/" target="_new">http://ibatis.apache.org/</a><br />·核心 J2EE 模式：数据存储对象：<a href="http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html" target="_new">http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html</a><br />·Hibernate主页 (或者CodeZoo: Hibernate) ：<a href="http://www.hibernate.org/" target="_new">http://www.hibernate.org/</a><br />·使用XStream序列化Java对象：<a href="http://www.xml.com/pub/a/2004/08/18/xstream.html" target="_new">http://www.xml.com/pub/a/2004/08/18/xstream.html</a>        <br />·XStream (或者 CodeZoo: XStream) ：http://xstream.codehaus.org/ ( http://www.codezoo.com/ ：http://www.codezoo.com/pub/component/3551 )<br /><br /><b><span style="FONT-SIZE: 16px">关于作者</span></b><br />Sunil Patil对J2EE技术领域的研究超过5年时间。他对感兴趣的领域是与对象相关的映射工具、UI框架和Portals<br /><br /><img src ="http://www.blogjava.net/realzar/aggbug/49067.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/realzar/" target="_blank">开源爱好者</a> 2006-05-30 17:27 <a href="http://www.blogjava.net/realzar/archive/2006/05/30/49067.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring与iBATIS的集成</title><link>http://www.blogjava.net/realzar/archive/2006/05/20/47131.html</link><dc:creator>开源爱好者</dc:creator><author>开源爱好者</author><pubDate>Fri, 19 May 2006 16:14:00 GMT</pubDate><guid>http://www.blogjava.net/realzar/archive/2006/05/20/47131.html</guid><wfw:comment>http://www.blogjava.net/realzar/comments/47131.html</wfw:comment><comments>http://www.blogjava.net/realzar/archive/2006/05/20/47131.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/realzar/comments/commentRss/47131.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/realzar/services/trackbacks/47131.html</trackback:ping><description><![CDATA[iBATIS似乎已远离众说纷纭的OR框架之列，通常人们对非常流行的Hibernate情有独钟。但正如Spring: A Developer's Notebook作者Bruce Tate 和Justin Gehtland所说的那样，与其他的OR框架相比，iBATIS独辟蹊径:“iBATIS不是试图从根本上掩盖SQL，实际上，它是在拥抱SQL。”<br /><br />但别犯愁：SQL本身具备了一些重要的功能，并且通过模板的使用，在Spring应用中采用iBATIS显得轻而易举。在此摘录中，两位作者将和你一起安装iBATIS并将其集成进你的Spring应用中。他们也阐明了怎样取得你已编写的SQL语句及把他们映射给iBATIS使用的Bean。最后，还讨论了iBATIS的优缺点，及为什么是这样的一种方式，即所谓的“在完全OR与JDBC之间的一个幽雅的折衷。”<br /><br />就象Developer's Notebook 系列中所有的书一样，你将由直接的且实用的方式获得信息，这些信息包含了完成你工作所需的细节。换言之：“一切来自实战，没有讲义。”<br /><br />作者:<a href="http://www.matrix.org.cn/user.shtml?username=czyczy" target="_new">czyczy</a><br />原文:<a href="http://www.matrix.org.cn/resource/article/44/44304_Spring+iBATIS.html" target="_new">http://www.matrix.org.cn/resource/article/44/44304_Spring+iBATIS.html</a><br />关键字:Spring;iBATIS<br /><br /><b><span style="FONT-SIZE: 16px">对象关系持久化（OR Persistence）</span></b><br /><br />本章所涉及的内容为：<br /><span style="COLOR: blue">· 与iBATIS的集成<br />· 在Spring的应用中使用JDO<br />· 在Spring的应用中使用Hibernate<br />· 运行测试用例</span><br /><br />离我住处不远的地方，名为啤酒山的山上有一个臭名远扬的山地自行车道。我想不出它为何会得到这样的名字，因为在下山的时候你要保持完全地清醒甚至于全神贯注。据我所知，那决不是纯粹的攀爬（或不曾离开自行车步行）。大多数人认为那很荒谬，哪怕只是去尝试一下而已。这座山连绵起伏，异常陡峭，它的表面覆盖了松散的岩石和大量的岩脊。我想我一定是太厌烦我的余生了，因为两年半来我一直不断地在攀爬。在我看来，那样的一座山峰就像是一个困难的编程问题。我已多次重新启程，在到达山峰的途中，尝试过翻越许多岩脊和泥砾丛的不同途径。为了攀爬啤酒山， 我需要改良自行车，提高车技，加强训练。<br /><br />对Java 开发人员而言，对象关系映射已然成为那类问题了。我们需要处理功能（processing power）、较佳设计模式及更好持久化框架的组合，从而使解决持久化设计变得更加清晰。最终，我们开始取得实质性的进展。现在，我们已逼近山峰，象Spring这样的框架就象是方程式的一部分，因为他们让对象关系映射（ORM）花较少的精力来做更多的事情。在本章中，你将看到三种框架：iBATIS, JDO及Hibernate:<br /><br />·iBATIS 是一种JDBC助手类框架，它给了你一些OR映射及使用OR的好处，但不带 有太多的风险。<br />·JDO是一种饱受争议的持久化标准，但它有着一些独特的实现，这使得JDO在行业中也算得上是最完美的持久化框架之一。<br />·Hibernate 是在JBoss组织控制下的一开源持久化框架。它可能是时下最为流行的持久化框架。大量的客户采用它，而且客户的数量还在持续稳定地增长。        <br /><br />在本章中，我们会对所提的三个框架进行尝试，而不必对应用的其余部分的代码做任何变更。<br /><br /><span style="FONT-SIZE: 6px">与iBATIS集成</span><br /><br />常言道:“树大招风”。在大肆宣扬的J2EE和.Net之争中, Sun的一示例应用程序被用来作为衡量应用服务器在运行时的各项性能的核心基准。 .Net非常好地打败了基于EJB的J2EE版本, 且方兴未艾。Clinton Begin 开发了iBATIS的持久化框架，他在iBATIS中使用PetStore的简化版，且自从那以后iBATIS就越来越流行。Spring提供非常优良的与iBATIS的集成功能， 在此章中将对其进行介绍。<br /><br />并非所有的问题都非常适合持久化框架这朵盛开的花朵，中等难度的问题是最合适的环境。没有正确的技巧或不相称的问题，可能就会误入歧途。跟我一起教课的Ted Neward， 他是《Effective Enterprise Java》一书的作者，他经常把构建或采用持久化框架与美国的越南战争拿来做比较，进入这样的两场战争是很诱人的，但最终都很难赢得胜利，而且此二例中并不存在着行之有效的策略。关于这一话题，你仍可查阅http://www.neward.net上的相关内容。<br /><br />然而，我不想扯得太远。尝试一下象iBATIS SqlMaps的框架给了你OR的使用模型又何尝不可呢？当然，我们不会强迫你一口吞下一只大象。具体来说，iBATIS让你：<br />·映射字段和SQL语句到关键字<br />·使用SQL的全部功能而没有乏味的JDBC<br />·从你的代码中剥离SQL<br />Spring 与iBATIS的集成给了你这些及更多的裨益， 让我们为此而忙乎起来。<br /><br /><b>我该怎么做？</b><br /><br /><br />首先，你需要安装iBATIS。由于iBATIS的配置会在你的Spring 应用上下文中完成，因此你不需要立即配置它。在http://www.ibatis.com/(译注：最新的网址为：http://ibatis.apache.org/，iBATIS已于2004-08-16并入Apache 软件基金会)上可以下载并安装。在本书中我们使用1.3.1版本。把iBATIS提供的jars(ibatis-sqlmap.jar, ibatis-dao.jar, and ibatis-common.jar)和Spring提供的jdom.jar(在Spring的/lib 目录下)放到你的项目目录/war/WEB-INF/lib中。<br /><br />You’ve already got the interface for the fa&amp;ccedil;ade and the model, so you need an implementation of the fa&amp;ccedil;ade and the SQL statement.  First, you can implement the fa&amp;ccedil;ade for the application, as in Example 5-1.<br />你已经有了门户（fa&amp;ccedil;ade）和模型（model)的接口，因而你需要facade和SQL语句的实现。首先，你可以象示例5-1那样，在你的应用中实现fa&amp;ccedil;ade的接口。<br /><br /><b>示例 5-1 IBatisRentABike.java</b><br /><br /><pre class="overflow">public class IBatisRentABike extends SqlMapDaoSupport<br />                 implements RentABike {<br /><br />        private String storeName ="";<br /><br />        public void setStoreName(String storeName) {<br />                this.storeName= storeName;<br />        }<br /><br />        public String getStoreName( ) {<br />                return this.storeName;<br />        }<br /><br />        public List getBikes() {<br />                return getSqlMapTemplate().executeQueryForList("getBikes", null);<br />        }<br /><br />        public Bike getBike(String serialNo) {<br />                return (Bike) getSqlMapTemplate().<br />                        executeQueryForObject("getBikeBySerialNo", serialNo);<br />        }<br /><br />        public Bike getBike(int bikeId) {<br />                return (Bike) getSqlMapTemplate().<br />                        executeQueryForObject("getBikeByID", new Integer(bikeId));<br />        }<br /><br />        public void saveBike(Bike bike) {<br />                getSqlMapTemplate().executeUpdate("saveBike", bike);<br />        }<br /><br />        public void deleteBike(Bike bike) {<br />                getSqlMapTemplate().executeUpdate("deleteBike", bike);<br />        }<br /><br />        public List getCustomers() {<br />                return getSqlMapTemplate().executeQueryForList("getCustomers", null);<br />        }<br /><br />        public Customer getCustomer(int custId) {<br />                return (Customer) getSqlMapTemplate().<br />                    executeQueryForObject("getCustomer", new Integer(custId));<br />        }<br />        <br />        public List getReservations() {<br />                return getSqlMaptemplate().<br />                    executeQueryForList("getReservations", null);<br />        }<br /><br />        public List getReservations(Customer customer) {<br />                return getSqlMaptemplate().<br />                    executeQueryForList("getReservationsForCustomer", customer);<br />        }<br /><br />        public List getReservations(Bike bike) {<br />                return getSqlMaptemplate().<br />                    executeQueryForList("getReservationsForBike",bike);<br />        }<br /><br />        public List getReservations(Date date) {<br />                return getSqlMaptemplate().<br />                    executeQueryForList("getReservationsForDate", date);<br />        }<br /><br />        public Reservation getReservation(int resId) {<br />                return getSqlMaptemplate().<br />                    executeQueryForObject("getReservation", new Integer(resId));<br />        }<br />}</pre><br /><br />这些就是命名式查询。iBATIS将每一查询分成一个独立的映射，那样你就可以用名字来执行查询。<br /><br />SqlMapTemplate由Spring的SqlMapDaoSupport 类提供，我们的RentABike实现必须来继承这个类。SqlMapTemplate负责建立和管理底层数据存储的连接，同时也解释了你所提供的映射文件。你可以把template 看成是你对于iBATIS命名式查询所做那些事情的默认实现。 <br /><br />你也需要创建SQL语句，可以给每条SQL语句取一个名字。然后，把结果映射给Java Bean。在这里你有两种选择，你可以在SQL中把每个Bean属性作为别名来引用，或在查询和Bean 之间建立显式映射，就象示例5-2那样。在此例中我们也建立了Customer 与Reservation的映射。<br /><br /><b>示例5-2.  Bike.xml（iBATIS SQL 映射文件）</b><br /><pre class="overflow">&lt;?xml version="1.0" encoding="UTF-8" ?&gt;<br /><br /><br />&lt;sql-map name="Bike" &gt;<br />    &lt;result-map name="result" class="com.springbook.Bike" &gt;<br />       &lt;property name="bikeId" column="bikeId" columnIndex="1" /&gt;<br />       &lt;property name="manufacturer" column="manufacturer" columnIndex="2" /&gt;<br />       &lt;property name="model" column="model" columnIndex="3" /&gt;<br />       &lt;property name="frame" column="frame" columnIndex="4" /&gt;<br />       &lt;property name="serialNo" column="serialNo" columnIndex="5" /&gt;<br />       &lt;property name="weight" column="weight" columnIndex="6" /&gt;<br />       &lt;property name="status" column="status" columnIndex="7" /&gt;<br />    &lt;/result-map&gt;<br />    <br />    &lt;mapped-statement name="getBikes" result-map="result"&gt;<br />        select bikeId, manufacturer, model, frame, serialNo, status<br />        from bikes<br />    &lt;/mapped-statement&gt;<br /><br />    &lt;mapped-statement name="getBikeBySerialNo" result-map="result"&gt;<br />        select bikeId, manufacturer, model, frame, serialNo, status<br />        from bikes<br />       where serialNo=#value#<br />    &lt;/mapped-statement&gt;<br /><br />    &lt;mapped-statement name="getBikeByID" result-map="result"&gt;<br />        select bikeId, manufacturer, model, frame, serialNo, weight, status<br />        from bikes<br />        where bikeId=#value#<br />    &lt;/mapped-statement&gt;<br /><br />    &lt;mapped-statement name="saveBike" &gt;<br />        insert into bikes<br />        (bikeId, manufacturer, model, frame, serialNo, weight, status)<br />        values(#bikeId#, #manufacturer#, #model#, #frame#, #serialNo#, <br />        #weight#, #status#)<br />    &lt;/mapped-statement&gt;<br /><br />    &lt;mapped-statement name="deleteBike" &gt;<br />        delete from bikes <br />        where bikeId = #bikeId#<br />    &lt;/mapped-statement&gt;<br />&lt;/sql-map&gt;</pre><br /><br /><b>示例5-3. Customer.xml </b><br /><pre class="overflow">&lt;?xml version="1.0" encoding="UTF-8" ?&gt;<br /><br /><br />&lt;sql-map name="Customer" &gt;<br />    &lt;result-map name="result" class="com.springbook.Customer" &gt;<br />       &lt;property name="custId" column="custId" columnIndex="1" /&gt;<br />       &lt;property name="firstName" column="firstName" columnIndex="2" /&gt;<br />       &lt;property name="lastName" column="lastName" columnIndex="3" /&gt;<br />    &lt;/result-map&gt;<br />    <br />    &lt;mapped-statement name="getCustomers" result-map="result"&gt;<br />            select custId, <br />                    firstName,<br />                    lastName<br />             from customers<br />    &lt;/mapped-statement&gt;<br /><br />    &lt;mapped-statement name="getCustomer" result-map="result"&gt;<br />            select custId, <br />                    firstName,<br />                    lastName<br />            from customers<br />            where custId = #value#<br />    &lt;/mapped-statement&gt;<br />&lt;/sql-map&gt;</pre><br /><br /><b>示例 5-4. Reservation.xml</b><br /><pre class="overflow">&lt;?xml version="1.0" encoding="UTF-8" ?&gt;<br /><br /><br />&lt;sql-map name="Reservation" &gt;<br />    &lt;result-map name="result" class="com.springbook.Customer" &gt;<br />       &lt;property name="reservationId" column="resId" columnIndex="1" /&gt;<br />       &lt;property name="bike" column="bikeId" columnIndex="2" /&gt;<br />       &lt;property name="customer" column="custId" columnIndex="3" /&gt;<br />       &lt;property name="reservationDate" column="resDate" columnIndex="4" /&gt;<br />    &lt;/result-map&gt;<br />    <br />    &lt;mapped-statement name="getReservations" result-map="result"&gt;<br />            select resId, <br />                   bikeId,<br />                              custId,<br />                              resDate           <br />             from reservations<br />    &lt;/mapped-statement&gt;<br /><br />    &lt;mapped-statement name="getReservationsForCustomer" result-map="result"&gt;<br />            select resId, <br />                   bikeId,<br />                              custId,<br />                              resDate           <br />             from reservations<br />             where custId = #value#<br />    &lt;/mapped-statement&gt;<br /><br />    &lt;mapped-statement name="getReservationsForBike" result-map="result"&gt;<br />            select resId, <br />                   bikeId,<br />                              custId,<br />                              resDate           <br />             from reservations<br />             where bikeId = #value#<br />    &lt;/mapped-statement&gt;<br /><br />    &lt;mapped-statement name="getReservationsForDate" result-map="result"&gt;<br />            select resId, <br />                   bikeId,<br />                              custId,<br />                              resDate           <br />             from reservations<br />             where resDate = #value#<br />    &lt;/mapped-statement&gt;<br /><br />    &lt;mapped-statement name="getReservation" result-map="result"&gt;<br />            select resId, <br />                   bikeId,<br />                              custId,<br />                              resDate           <br />             from reservations<br />             where resId = #value#<br />    &lt;/mapped-statement&gt;<br />&lt;/sql-map&gt;</pre><br /><br />The &lt;result-map&gt; portion provides an explicit map between columns in the database and properties of a persistent class.  The &lt;mapped-statement&gt; can then simply define the SQL queries necessary to execute the needed functionality, and the map handles creation of the resultant Java object.  In addition to the Bike version above, your application currently also requires a map for Customer and Reservation.<br />&lt;result-map&gt;部分提供了数据库字段与持久化类属性之间的一显式映射。&lt;mapped-statement&gt;接着可以简单定义运行所需功能的必要的SQL查询，而映射负责创建合成的Java 对象。除了上述的Bike 版本之外，你的应用程序目前也需要一个关于Customer 和Reservation的映射。<br /><br />你将不得不做一些OR框架通常为我们所做的活，如创建标识符。在此例中，你将使用MySQL生成的序列（就是数据库表中的那些AUTO_INCREMENT字段）。你只需在数据库表定义时简单地把bikeId标为AUTO_INCREMENT，这样当增加一条新记录时，你就可以在SQL语句中略过bikeId字段。我们映射中SaveBike语句就成了示例5-5。<br /><br /><b>示例5-5. Bike.xml </b><br /><pre class="overflow">    &lt;mapped-statement name="saveBike" &gt;<br />        insert into bikes<br />        (manufacturer, model, frame, serialNo, weight, status)<br />        values(#manufacturer#, #model#, #frame#, #serialNo#, #weight#,<br />        #status#)<br />    &lt;/mapped-statement&gt;</pre><br /><br />若你是在使用Oracle, Spring和iBATIS也支持Oracle生成的序列。<br /><br />下一步，你可以更新应用上下文，且需要列出我们的新fa&amp;ccedil;ade，而fa&amp;ccedil;ade要有SQL映射。把SQL 引入PROPERTIES 文件，就象我们对待JDBC 的参数一样。 此外，你还需要配置事务策略。( 示例5-6)<br /><br /><b>示例5-6. .RentABikeApp-servlet.xml</b><br /><pre class="overflow">&lt;beans&gt;<br />&lt;bean id="dataSource"<br />class="org.springframework.jdbc.datasource.DriverManagerDataSource"&gt;<br />&lt;property name="driverClassName"&gt;<br />&lt;value&gt;com.mysql.jdbc.Driver&lt;/value&gt;<br />&lt;/property&gt;<br />&lt;property name="url"&gt;<br />&lt;value&gt;jdbc:mysql://localhost/bikestore&lt;/value&gt;<br />&lt;/property&gt;<br />&lt;property name="username"&gt;<br />&lt;value&gt;bikestore&lt;/value&gt;<br />&lt;/property&gt;<br />&lt;/bean&gt;<br />&lt;bean id="rentaBike" class="com.springbook.IBatisRentABike"&gt;<br />&lt;property name="storeName"&gt;&lt;value&gt;Bruce's Bikes&lt;/value&gt;&lt;/property&gt;<br />&lt;property name="dataSource"&gt;&lt;ref local="dataSource"/&gt;&lt;/property&gt;<br />&lt;property name="sqlMap"&gt;&lt;ref local="sqlMap"/&gt;&lt;/property&gt;<br />&lt;/bean&gt;<br />&lt;bean id="sqlMap"<br />class="org.springframework.orm.ibatis.SqlMapFactoryBean"&gt;<br />&lt;property name="configLocation"&gt;<br />&lt;value&gt;/WEB-INF/ibatis.config&lt;/value&gt;<br />&lt;/property&gt;<br />&lt;/bean&gt;<br />&lt;bean id="transactionManager"<br />class="org.springframework.jdbc.datasource.DataSourceTransactionManager"&gt;<br />&lt;property name="dataSource"&gt;&lt;ref local="dataSource"/&gt;&lt;/property&gt;<br />&lt;/bean&gt;</pre><br /><br />这个事务策略就在应用上下文中，你不必来管理提交适宜，因为Spring 会为你完成。你将在第六章中更完整地探讨事务策略。                                                <br /><br /><b>示例5-7. . ibatis.config</b><br /><pre class="overflow">&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br /><br />&lt;sql-map-config&gt;<br />&lt;sql-map resource="Bike.xml" /&gt;<br />&lt;sql-map resource="Customer.xml" /&gt;<br />&lt;sql-map resource="Reservation.xml" /&gt;<br />&lt;/sql-map-config&gt;</pre><br /><br />稍后我们会谈到事务策略。<br /><br /><b>发生了什么事?</b><br /><br />你没看到OR映射。OR框架会有意地将一个数据库表与一个类或多个类关连起来。在此例中，iBATIS会将查询结果赋予一个类。这意味着iBATIS并未试图对你隐藏SQL细节。实际上，它是在拥抱SQL。<br /><br />Spring打算通过模板来简化iBATIS的使用。iBATIS模板会给出类似JDBC模板的使用模型，你只需指定数据源和iBATIS映射的SQL语句。<br /><br />当执行SQL语句时，Spring与iBATIS一起为你管理资源，并按要求来创建和关闭连接。Spring会把映射的SQL语句传给iBATIS, 由iBATIS来运行映射的语句，且若需要，iBATIS会把结果集传给给你映射SQL语句时所指定的Bean。如果你已有了任何参数，那就可将那些结果集放入hash map中并把结果集传给带有映射的SQL语句的模板。<br /><br />然而，从内部所表现的来看，iBATIS或许并不象是一个OR框架，但使用模型的确有OR的趋向。 构建带有操作数据存储的数据访问对象（data access object），你不会在代码中看到SQL语句，因为它已被保存在配置文件中了，且iBATIS使用对象集合而不是结果集。简而言之，这是在全部OR与JDBC之间的一个幽雅的折衷。<br /><br /><b>关于…</b><br /><br />一切都适合iBATIS吗？ 由于这种使用模型与OR模型是那么的相似，且许多应用对他们可能生成的SQL需要有更多的控制，或许你倾向于普遍地使用iBATIS。尽管如此，象JDO和Hibernate的OR框架仍拥有着属于自己的舞台。OR框架给了你更多的灵活性和更强大的功能：<br />·一些高级的对象模型导致了非常复杂的SQL，把这些复杂的SQL交由ORM来完成是最好的处理方式。 例如，继承通常使得原始的JDBC API操作变得更为复杂。<br />·一些高级的性能特征，象延迟加载和数据抓取群组，要求对有效地的自动控制需要一个更正式的模型。然而，完美地优化后的JDBC至少要和ORM一样快速。相对于使用原始的JDBC而言，由ORM提供的性能优化选项对某些类型的问题更获得较佳性能。<br />·ORM使某些问题变得更加有趣。操作对象比创建一套的SQL查询更加简易。ORM很适合带有简单的查找，创建，更新，根据主键读取数据库中的数据以及删除记录的应用。<br /><br />如若你的应用有快速的数据模型和对象模型的变更，iBATIS就会很适合。如果你有了CRUD类型的应用，那么，使用iBATIS可能就会有点乏味。相反地，如果你正寻找一种好的SQL访问方式及在ORM和原始的JDBC间有效的折衷，那么，iBATIS可能就会给了你所需的一切。<br /><img src ="http://www.blogjava.net/realzar/aggbug/47131.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/realzar/" target="_blank">开源爱好者</a> 2006-05-20 00:14 <a href="http://www.blogjava.net/realzar/archive/2006/05/20/47131.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基于iBatis的通用持久层对象</title><link>http://www.blogjava.net/realzar/archive/2006/05/20/47130.html</link><dc:creator>开源爱好者</dc:creator><author>开源爱好者</author><pubDate>Fri, 19 May 2006 16:13:00 GMT</pubDate><guid>http://www.blogjava.net/realzar/archive/2006/05/20/47130.html</guid><wfw:comment>http://www.blogjava.net/realzar/comments/47130.html</wfw:comment><comments>http://www.blogjava.net/realzar/archive/2006/05/20/47130.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/realzar/comments/commentRss/47130.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/realzar/services/trackbacks/47130.html</trackback:ping><description><![CDATA[
		<strong>ibatis介绍<br /></strong>　　使用ibatis 提供的ORM机制，对业务逻辑实现人员而言，面对的是纯粹的Java对象， 这一层与通过Hibernate 实现ORM 而言基本一致，而对于具体的数据操作，Hibernate 会自动生成SQL 语句，而ibatis 则要求开发者编写具体的SQL 语句。相对Hibernate等 “全自动”ORM机制而言，ibatis 以SQL开发的工作量和数据库移植性上的让步，为系统 设计提供了更大的自由空间。作为“全自动”ORM 实现的一种有益补充，ibatis 的出现显 得别具意义。<br /><br />作者:<a href="http://www.matrix.org.cn/user.shtml?username=fellow99" target="_new">fellow99</a><br />原文:<a href="http://www.matrix.org.cn/resource/article/44/44410_iBatis.html" target="_new">http://www.matrix.org.cn/resource/article/44/44410_iBatis.html</a><br />关键字:iBatis;ORM<br /><br /><b>一、为什么要设计“通用”的东西</b><br />　　在大多数时候，我们所需要的持久层对象（PO）大多都是一张表（or视图）对应一个类。按照Hibernate的思想，就是抛开数据库的束缚，把焦点集中到业务对象中。而很多自动化工具的确让做到了通过表结构生成对应的对象，or通过对象自动生成表。对于小项目来说，一切都是简单的；对于有规范设计的项目来说，PO的设计也不是一件困难的工作。但是对于那些业务变动频繁的项目来说，改动PO可能成了一件很繁重的工作。试想一下，假设某个表需要增加一个字段：对于Hibernate（or iBaits），首先要改配置文件，然后PO，然后DAO（也许没有），然后业务逻辑，然后JO，然后界面，etc，贯通了全部层次。<br />　　恩，写程序的都不喜欢这些重复劳动，但是做企业级应用的谁不是每天在这些工作中打滚。<br />　　研究过iBaits以后，发现有些通用的方法可以解决，就是设计一个通用的持久层对象。<br /><br /><b>二、基于什么技术</b><br />　　iBatis可以使用Map对象作为PO，Hibernate好像也有相关的功能（我没有细看，不确定）。<br />　　iBatis执行一条指令的过程大概是这样的：<br /><br /><img height="333" alt="111.JPG" src="http://www.blogjava.net/images/blogjava_net/realzar/ibatis/111.JPG" width="532" border="0" /><br /><br />其中圈圈1、2、3描述了iBatis最重要的三个对象。<br /><br />圈圈1：statement简单来说就是存储sql语句的配置信息，一个最简单的statement：<br /><pre class="overflow"><br />&lt;statement id=”insertTestProduct” &gt;<br />    insert into PRODUCT (PRD_ID, PRD_DESCRIPTION) values (1, “Shih Tzu”)<br />&lt;/statement&gt;<br /></pre><br />其中id属性是这个statement的唯一标识，全局不能重复。<br /><br />以上当然是最简单的了，没有参数也不需要返回值，但实际情况下基本都需要传入参数，下面就是介绍参数。<br /><br />圈圈2：参数对象主要分两种类型：parameterMap、parameterClass和Inline Parameter。<br /><br />　　其中parameterMap是配置文件定义传入参数表，如下：<br /><pre class="overflow"><br />&lt;parameterMap id=”insert-product-param” class=”com.domain.Product”&gt;<br /><br />&lt;/parameterMap&gt;<br />    &lt;statement id=”insertProduct” parameterMap=”insert-product-param”&gt;<br />        insert into PRODUCT (PRD_ID, PRD_DESCRIPTION) values (?,?);<br />    &lt;/statement&gt;<br /></pre><br />　　而parameterClass是传入参数对象（JavaBean），如下：<br /><pre class="overflow"><br />&lt;statement id=”statementName” parameterClass=” examples.domain.Product”&gt;<br />    insert into PRODUCT values (#id#, #description#, #price#)<br />&lt;/statement&gt;<br /></pre><br />　　Inline Parameter则是强化版的parameterClass，如下：<br /><pre class="overflow"><br /> &lt;statement id=”insertProduct” parameterClass=”com.domain.Product”&gt;<br />    insert into PRODUCT (PRD_ID, PRD_DESCRIPTION)<br />        values (#id:NUMERIC:-999999#, #description:VARCHAR:NO_ENTRY#);<br />&lt;/statement&gt;<br /></pre><br />　　其中第一种方法看着就复杂，实际是为了兼容老版本留下来的，所以parameterClass是我们最常用的方法。官方文档对parameterClass介绍很详细，因为这是核心之一，具体请自己查阅。有3个特性说明一下：<br /><br />　　a. parameterClass对象可以传入一个Map对象（or Map子类）。本来如果是传入JavaBean，程序会通过get/set来分析取得参数；而Map是key-value结构的，那程序会直接通过key来分析取参数。<br /><br />　　b. 看以下语句：<br /><pre class="overflow"><br />&lt;statement id=”statementName” parameterClass=” examples.domain.Product”&gt;<br />    insert into PRODUCT values (#id#, #description#, #price#, #classify.id#)<br />&lt;/statement&gt;<br /></pre><br />　　蓝色部分#classify.id#翻译过来实际是product.getClassify().getId()，classify是Product对象的一个子对象。<br /><br />　　c. 在模板sql语句中除了“#”以外，还有“$”，它们两代表的意思当然不同了：<br /><pre class="overflow"><br />&lt;statement id=”getProduct” resultMap=”get-product-result”&gt;<br />    select * from PRODUCT order by $preferredOrder$<br />&lt;/statement&gt;<br /></pre><br />　　“#”在生成sql语句的过程中，会变成“?”，同时在参数表中增加一个参数；<br /><br />　　“$”则会直接替换成参数对象对应的值，例如上面的preferredOrder的值可能是“price”，则生成的sql语句就是：select * from PRODUCT order by price。<br /><br />　　*需要特别说明的是传入参数这一部分将会是后面正题“通用持久层对象”的核心，怎么个通用法，怎么设计模板sql语句，都是在这部分上。<br /><br /><br /><br />圈圈3：结果对象跟参数对象差不多，也有两种，resultMap和resultClass，如下：<br /><br />　　resultMap就是配置文件中预定义了要取得的字段：<br /><pre class="overflow"><br />&lt;resultMap id=”get-product-result” class=”com.ibatis.example.Product”&gt;<br />    &lt;result property=”id” column=”PRD_ID”/&gt;<br />    &lt;result property=”description” column=”PRD_DESCRIPTION”/&gt;<br />&lt;/resultMap&gt;<br />&lt;statement id=”getProduct” resultMap=”get-product-result”&gt;<br />    select * from PRODUCT<br />&lt;/statement&gt;<br /></pre><br />　　resultClass则是通过分析返回的字段，来填充结果对象：<br /><pre class="overflow"><br />&lt;statement id="getPerson" parameterClass=”int” resultClass="examples.domain.Person"&gt;<br />    SELECT PER_ID as id, PER_FIRST_NAME as firstName <br />        FROM PERSON WHERE PER_ID = #value#<br />&lt;/statement&gt;<br /></pre><br />　　跟参数对象相反，结果对象一般使用resultMap形式。引用官方的话：使用resultClass的自动映射存在一些限制，无法指定输出字段的数据类型（如果需要的话），无法自动装入相关的数据（复杂属性），并且因为需要ResultSetMetaData的信息，会对性能有轻微的不利影响。但使用resultMap，这些限制都可以很容易解决。<br /><br /><br /><b>三、正题来了，怎么做“通用持久层对象”</b><br /><br />1. 表结构：<br /><br />　　每个表都必须包含两个字段：id和parentId，其他字段按照需求来定义，其他各种索引、约束、关系之类的也按需求定义。<br /><br />2. 通用的持久层对象，CustomPO：<br /><pre class="overflow"><br />public class CustomPO {<br />    protected String moduleTable;  //该PO对应的表名（视图名）<br />    protected int id;  //表的id<br />    protected int parentID;  //父表的id（如果有的话）<br />    protected Map fieldMap;  //字段Map，核心，用于存储字段及其值<br />    public String getModuleTable()<br />    public void setModuleTable(String moduleTable)<br />    public int getId()<br />    public void setId(int id) <br />    public int getParentID() <br />    public void setParentID(int parentID) <br />    public Map getFieldMap()<br />    public void setFieldMap(Map fieldMap)<br />    public void copyFieldMap(Map fieldMap)<br />    //取得字段名列表<br />    public List getFieldList()<br />    //设置字段名列表。如果fieldMap没有相应的字段，则增加，字段值为null；如果有则不增加。<br />    public void setFieldList(List fieldList)<br />    //返回字段的“字段名 - 字段值”列表，使用com.fellow.pub.util.KeyValuePair对象作为存储<br />    public List getFieldValueList()<br />}<br /></pre><br />　　那些成员变量的get/set就没什么说的，主要说说getFieldValueList()这个方法。该方法返回一个列表，列表元素是一个key-value结构，简单来说就是把字段map序列化。在构造模板sql语句时会体现它的用途。<br /><br />3. iBatis对象配置文件CustomPO.xml：<br /><pre class="overflow"><br />&lt;sqlMap namespace="CustomPO"&gt;<br />  &lt;!--定义别名--&gt;<br />  &lt;typeAlias alias="customPO" type="com.fellow.component.customPO.CustomPO"/&gt;<br />    &lt;!--<br />        通过id查找<br />        特点：iterate这个fieldList列表，生成要输出的字段<br />    --&gt;<br />  &lt;select id="customPO_findByID" resultClass="java.util.HashMap" parameterClass="customPO"&gt;<br />    SELECT id, parentID<br />      &lt;iterate property="fieldList" conjunction=","&gt;<br />        $fieldList[]$<br />      &lt;/iterate&gt;<br />     FROM $moduleTable$ WHERE id = #id#<br />  &lt;/select&gt;<br />  <br />    &lt;!--<br />        插入一条新纪录<br />        特点：iterate这个fieldValueList列表，分别取得其元素的key和value值<br />        注意$号和#号的使用方法，还有最后怎么取得insert后的id值（各种数据库都可能不同）<br />    --&gt;<br />  &lt;insert id="customPO_insert" parameterClass="customPO"&gt;<br />    INSERT INTO $moduleTable$ (parentID<br />      &lt;iterate property="fieldValueList" prepend="," conjunction=","&gt;<br />        $fieldValueList[].key$<br />      &lt;/iterate&gt;<br />      )<br />    VALUES (#parentID#<br />      &lt;iterate property="fieldValueList" prepend="," conjunction=","&gt;<br />        #fieldValueList[].value#<br />      &lt;/iterate&gt;<br />      )<br />    &lt;selectKey resultClass="int" keyProperty="id"&gt;<br />      SELECT last_insert_id()<br />    &lt;/selectKey&gt;<br />  &lt;/insert&gt;<br /><br />    &lt;!--<br />        更新一条纪录<br />        特点：iterate这个fieldValueList列表，分别取得其元素的key和value值<br />        注意$号和#号的使用方法<br />    --&gt;<br />  &lt;update id="customPO_update" parameterClass="customPO"&gt;<br />    UPDATE $moduleTable$ SET<br />      &lt;iterate property="fieldValueList" conjunction=","&gt;<br />        $fieldValueList[].key$ = #fieldValueList[].value#<br />      &lt;/iterate&gt;<br />     WHERE id = #id#<br />  &lt;/update&gt;<br /><br />    &lt;!--删除一条纪录--&gt;<br />  &lt;delete id="customPO_delete" parameterClass="customPO"&gt;<br />    DELETE FROM $moduleTable$ WHERE id = #id#<br />  &lt;/delete&gt;<br /></pre><br />　　要注意的地方如下：<br /><br />　　a. 跟一般的ibatis配置文件不一样，该配置中没有包含resultMap，使用的就是resultClass的方式（效率没那么高的那种）。当然，也可以使用resultMap，这样就要为每个表写自己的配置文件了。因此，在该设计没完成前，我暂时先使用resultClass的方式。<br /><br />　　b. 上面只列举了最简单的增删改以及按id查询，并没有更复杂的查询，为什么呢？因为我还在研究中。。。研究通用的模板sql的写法。<br /><br />4. CustomPO对应的DAO：<br /><br />　　我使用了ibaits提供的DAO框架，很好用，不单支持ibatis的框架，还支持Hibernate、JDBC等等，而且是与ibatis本身独立的，完全可以单独使用。以后就不用自己写DAO框架了。一下是该DAO接口：<br /><pre class="overflow"><br />public interface ICustomDAO {<br />    /**<br />     * 通过传入moduleTable和id取得一条记录<br />     */<br />    CustomPO findByID(String moduleTable, int id) throws Exception;<br /><br />    /**<br />     * 通过传入CustomPO对象取得一条记录<br />     * @param po CustomPO 该对象在传入前应该先设置moduleTable和id参数，<br />     * 并且使用setFieldList()函数设置字段列表（该设置决定所返回的字段）。<br />     */<br />    CustomPO findByID(CustomPO po) throws Exception;<br /><br />    /**<br />     * 通过传入moduleTable和parentID取得一条记录<br />     */<br />    CustomPO findByParentID(String moduleTable, int parentID) throws Exception;<br /><br />    /**<br />     * 通过传入CustomPO对象插入一条记录<br />     * @param po CustomPO 该对象在传入前应该先设置moduleTable和id参数，<br />     * 并且使用setFieldMap()函数设置“字段-值”对。<br />     */<br />    void insert(CustomPO po) throws Exception;<br /><br />    /**<br />     * 通过传入CustomPO对象更新一条记录<br />     * @param po CustomPO 该对象在传入前应该先设置moduleTable和id参数，<br />     * 并且使用setFieldMap()函数设置“字段-值”对。<br />     */<br />    void update(CustomPO po) throws Exception;<br /><br />    /**<br />     * 删除moduleTable和id所对应的记录<br />     */<br />    void delete(String moduleTable, int id) throws Exception;<br />}<br /></pre><br />　　我没有把所有的方法都列出来，反正挺简单的，跟一般的DAO没什么分别。<br /><br />　　另外列几个实现的片断：<br /><br />　　a. 统一的数据装填函数，需要手工把id和parentID字段去掉。<br /><pre class="overflow"><br />    protected void fill(Map result, CustomPO po) {<br />        Long returnId = (Long) result.get("id");<br />        Long returnParentID = (Long) result.get("parentID");<br />        result.remove("id");<br />        result.remove("parentID");<br />        if (returnId != null) po.setId(returnId.intValue());<br />        if (returnParentID != null) po.setParentID(returnParentID.intValue());<br />        po.setFieldMap(result);<br />    }<br /></pre><br />　　b. 一般的查询，返回的是一个map，然后再用fill()函数<br /><pre class="overflow"><br />    //查询<br />     Map result = (Map)this.queryForObject("customPO_findByID", po);<br /><br />    //处理返回结果<br />    if(result == null)<br />        po = null;<br />    else<br />        fill(result, po);<br /></pre><br />　　c. 增删改，没有返回值，值得一提的是增加操作完成后，po里面的id会更新，具体看前面相关的statement。<br /><pre class="overflow"><br />    //增删改<br />    this.insert("customPO_insert", po);<br />    this.update("customPO_update", po);<br />    this.delete("customPO_delete", po);<br /></pre><br /><br />5. 前面是通用的部分，光是通用是不够的。因此我另外建立了一套配置文件，记录字段对应关系。看看我所定义的一个配置文件，挺简单的：<br /><pre class="overflow"><br />&lt;struct name="userInfo" table-name="tblUserInfo"&gt;<br />    &lt;field name="昵称" column="NICK_NAME" type="string" not-null="true" unique="false" /&gt;<br />    &lt;field name="姓名" column="FULL_NAME" type="string" not-null="true" unique="false" /&gt;<br />    &lt;field name="性别" column="SEX" type="string" not-null="false" unique="false" /&gt;<br />    。。。<br />&lt;/struct&gt;<br /></pre><br />　　其中，name是字段名，column是字段对应数据表的字段名，type是字段类型，not-null是是否不能为空，unique是是否唯一。只有name这个属性是必填的，column如果不填默认与name相等，type默认为string，not-null和unique默认为false。<br /><br />　　配置文件的读取类在这里就省略了。<br /><br />　　为什么要自己定义一套这个框架？好像挺多此一举的，但是没办法，ibatis配置文件的信息是封闭的，我无法取得。另外我考虑的是：<br />　　a. viewer层：在web开发中，我可以在这套配置框架的基础上，建立自己的标签，实现数据自动绑定的功能；GUI开发中也可以做相应的功能。<br />　　b. module层：可以做通用的业务操作，不需要为每个业务都都做独立的业务逻辑。<br /><br /><b>四、有什么优点、缺陷</b><br /><br />1. 优点：<br />　a. “通用”，一切都是为了通用，为了减少重复劳动，一个个项目面对不同的业务，其实说到底都是那些操作。各种持久成框架已经带给我们不少的方便，但是在实际业务逻辑的处理上好像还没有一个这样的框架。<br />　b. 极大地减少代码量。前面说了，数据库改一个字段，PO、DAO、module、JO、viewer、validator全都要改一遍。使用了这套东西，可以把绝大部分的劳动都放在配置文件和UI上。当然，这是完美的设想，对于很多情况，业务逻辑还是要手工写的。<br />　c. 好像没有c了。<br /><br />2. 缺点：<br />　a. 通常通用的东西都缺乏灵活性，在我的实际应用中也发现了这样那样的问题，解决方法都是以通用为基本原则。但是如果针对的是某个项目，那就可以针对业务来修改了。<br />　b. 性能问题。因为使用resultClass，按照文档所说的，性能没有resultMap好。当然也可以使用resultMap，如前所说，就要对每个PO写配置文件了，工作量也不少。<br />　c. 也好像没有c了。<br /><br /><b>五、后话</b><br />　　我总是喜欢写一些通用的东西，总是想把它设计成万能的。但是经过多次失败总结出来，我发现通用的东西在很多情况下都等于不能用。但我就是喜欢往通用方面想，这个毛病不知道什么时候才能改得了。其实在Delphi平台中，我早就实现了相关的东西，但是用delphi总是限制于ADO+Data Module这样掉牙的模式。现在转向java，发现有ibatis、hibernate这么多好的持久层框架，自然有移植必要了。<br /><img src ="http://www.blogjava.net/realzar/aggbug/47130.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/realzar/" target="_blank">开源爱好者</a> 2006-05-20 00:13 <a href="http://www.blogjava.net/realzar/archive/2006/05/20/47130.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>UML-JpetStore专题</title><link>http://www.blogjava.net/realzar/archive/2006/05/16/46363.html</link><dc:creator>开源爱好者</dc:creator><author>开源爱好者</author><pubDate>Tue, 16 May 2006 03:25:00 GMT</pubDate><guid>http://www.blogjava.net/realzar/archive/2006/05/16/46363.html</guid><wfw:comment>http://www.blogjava.net/realzar/comments/46363.html</wfw:comment><comments>http://www.blogjava.net/realzar/archive/2006/05/16/46363.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/realzar/comments/commentRss/46363.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/realzar/services/trackbacks/46363.html</trackback:ping><description><![CDATA[
		<a href="http://www.uml.org.cn/zhuanti/zhuanti.asp">UML-JpetStore专题</a>
<img src ="http://www.blogjava.net/realzar/aggbug/46363.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/realzar/" target="_blank">开源爱好者</a> 2006-05-16 11:25 <a href="http://www.blogjava.net/realzar/archive/2006/05/16/46363.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ibatis开发人员指南(一)</title><link>http://www.blogjava.net/realzar/archive/2006/05/16/46356.html</link><dc:creator>开源爱好者</dc:creator><author>开源爱好者</author><pubDate>Tue, 16 May 2006 03:08:00 GMT</pubDate><guid>http://www.blogjava.net/realzar/archive/2006/05/16/46356.html</guid><wfw:comment>http://www.blogjava.net/realzar/comments/46356.html</wfw:comment><comments>http://www.blogjava.net/realzar/archive/2006/05/16/46356.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/realzar/comments/commentRss/46356.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/realzar/services/trackbacks/46356.html</trackback:ping><description><![CDATA[
		<table cellspacing="0" cellpadding="0" width="760" align="center" border="0">
				<tbody>
						<tr>
								<td class="title" valign="center" align="middle" height="56">
										<b>
												<font color="#ff0000" size="3">ibatis开发人员指南(一)<br /><!-- #EndEditable --></font>
										</b>
								</td>
						</tr>
						<tr>
								<td class="formtitle" align="middle" height="40">
										<!-- #BeginEditable "2" -->作者：紫龙<!-- #EndEditable --></td>
						</tr>
				</tbody>
		</table>
		<table height="65" cellspacing="0" cellpadding="0" width="760" align="center" border="0">
				<tbody>
						<tr>
								<td class="content" height="65">
										<!-- #BeginEditable "3" -->
										<table width="100%">
												<tbody>
														<tr>
																<td class="content" valign="top" width="720">
																		<p class="style1">
																				<strong>介绍</strong>
																		</p>
																		<p>欢迎来到iBATIS Database Layer!这个框架将让你能够更好的在JAVA应用中设计和实现实体层。这个框架有两个主要的组成部分，一个是SQL Maps，另一个是Data Access Objects。另外还包括一些可能很有用的工具。</p>
																		<p>
																				<strong>SQL Maps</strong>
																		</p>
																		<p>Sql Maps是这个框架中最激动人心的部分，它是整个iBATIS Database Layer的核心价值所在。通过使用Sql Maps你可以显著的节约数据库操作的代码量。SQL Maps使用一个简单的XML文件来实现从javaBean到SQL statements的映射。跟其他的框架或者对象映射工具相比，SQL Maps最大的优势是简单。它需要学习的东西很少，在连接表或复杂查询时也不需要复杂的scheme(怎么翻complex scheme?)，使用SQL Maps， 你可以自由的使用SQL语句。</p>
																		<p>
																				<strong>Data Access Objects (DAO)</strong>
																		</p>
																		<p>当我们开发灵活的JAVA应用时，有一个好主意就是通过一个通用API层把实体操作的细节封装起来。Data Access Objects允许你通过一个简单接口的来操作数据，从而隐藏了实现的细节。使用DAO，你可以动态配置你的应用程序来访问不同的实体存储机制。如果你有一个复杂的应用需要用到几个不同的数据库，DAO可以让你建立一个一致的API，让系统的其他部分来调用。</p>
																		<p>
																				<strong>Utilities</strong>
																		</p>
																		<p>iBATIS Database Layer包含一系列的有用的工具，比如SimpleDataSource，JDBC DataSource 2.0(也包括3.0)的一个轻量级实现。ScriptRunner也提供了从单元测试到自动发布的数据库准备工作。</p>
																		<p>
																				<strong>Examples</strong>
																		</p>
																		<p> 跟这个框架一起有一个examples.zip，包含了一系列简单的实例，在http://www.ibatis.com上有更多的例子，包括非常著名的Jpestore， 一个在线商店。(译者注，蓝色天空也有一系列的中文介绍和实例)</p>
																		<p>A<strong>bout this Document</strong></p>
																		<p>本文介绍了iBATIS Database Layer最重要的功能，还有一些功用没有写出来，凡是没有写出来的这些，可以认为是不支持或者正在修改。这些功能可能不经过通知就修改了，所以最好不要使用它们。本文将尽可能保持与框架同步。请确认你两者是否匹配。</p>
																		<p class="style1">SQL Maps (com.ibatis.db.sqlmap.*)</p>
																		<p>
																				<strong>概念</strong>
																		</p>
																		<p>SQL Map API允许程序员很简单的把JAVA对象映射到PreparedStatement参数或者ResultSets。SQL Maps的机制很简单，提供一个框架，来实现用20%的代码来实现80%JDBC的功能。</p>
																		<p>
																				<strong>How does it work?</strong>
																		</p>
																		<p>SQL Maps提供一个简单的框架，通过XML描述来映射JAVABeans，MAP implementations甚至原始类型的包装(String,Integer等)到JDBC PreparedStatement。想法很简单，基本的步骤如下：</p>
																		<p>1)提供一个对象作为参数(either a JavaBean, Map or primitive wrapper)，The parameter object<br />will be used setting input values in an update statement, or query values in a where clause (etc.).(感觉不译为好，你说呢？)</p>
																		<p>2)执行这个映射的statement，这一步是魔术发生的地方。SQL Maps框架将建立一个PreparedStatement实例(instance)，使用前面提供的对象的参数，执行statement，然后从ResultSet中建立一个返回对象。</p>
																		<p>3)如果是Update，则返回有多少行修改了，如果是查询，则返回一个对象或者对象的集合。跟参数一样，返回对象也可以是一个JAVABEAN，MAP或者一个primitive type wrapper。</p>
																		<p>流程图如下：</p>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<img height="401" alt="流程图.jpg" src="http://www.blogjava.net/images/blogjava_net/realzar/流程图.jpg" width="711" border="0" />
<img src ="http://www.blogjava.net/realzar/aggbug/46356.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/realzar/" target="_blank">开源爱好者</a> 2006-05-16 11:08 <a href="http://www.blogjava.net/realzar/archive/2006/05/16/46356.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ibatis开发人员指南(二)</title><link>http://www.blogjava.net/realzar/archive/2006/05/16/46357.html</link><dc:creator>开源爱好者</dc:creator><author>开源爱好者</author><pubDate>Tue, 16 May 2006 03:08:00 GMT</pubDate><guid>http://www.blogjava.net/realzar/archive/2006/05/16/46357.html</guid><wfw:comment>http://www.blogjava.net/realzar/comments/46357.html</wfw:comment><comments>http://www.blogjava.net/realzar/archive/2006/05/16/46357.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/realzar/comments/commentRss/46357.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/realzar/services/trackbacks/46357.html</trackback:ping><description><![CDATA[
		<table cellspacing="0" cellpadding="0" width="760" align="center" border="0">
				<tbody>
						<tr>
								<td class="title" valign="center" align="middle" height="56">
										<b>
												<font color="#ff0000" size="3">ibatis开发人员指南(二)<br /><!-- #EndEditable --></font>
										</b>
								</td>
						</tr>
						<tr>
								<td class="formtitle" align="middle" height="40">
										<!-- #BeginEditable "2" -->作者：紫龙<!-- #EndEditable --></td>
						</tr>
				</tbody>
		</table>
		<table height="65" cellspacing="0" cellpadding="0" width="760" align="center" border="0">
				<tbody>
						<tr>
								<td class="content" height="65">
										<!-- #BeginEditable "3" -->
										<table width="100%">
												<tbody>
														<tr>
																<td class="content" valign="top" width="720">
																		<p>本篇文章的第一部分将带你走过一系列的“fash Track”，带你浏览一遍SQL maps的简单应用。在walkthrough之后，将有详细的论述。 </p>
																		<p>
																				<strong>Fast Track: Preparing to Use SQL Maps</strong>
																		</p>
																		<p>SQL Maps对不好的数据库模型甚至对象模型都有很强的容忍度。尽管如此，还是推荐你使用最佳实践来设计你的的数据库模型和对象模型。通过这样，你将得到更干净的设计和更好的性能。</p>
																		<p> 最简单的开始就是分析你在做的内容，商业模型是什么样的，表结构是什么样的，它们怎么样互相发生关系。第一个例子，我们就简单的实现一个典型的Persion类。</p>
																		<table width="70%" bgcolor="#cccccc" border="1">
																				<tbody>
																						<tr>
																								<td class="content" height="277">Person.java<br />package examples.domain;<br />//imports implied….<br />public class Person {<br />private int id;<br />private String firstName;<br />private String lastName;<br />private Date birthDate;<br />private double weightInKilograms;<br />private double heightInMeters;<br />public int getId () {<br />return id;<br />}<br />public void setId (int id) {<br />this.id = id;<br />}<br />//…let’s assume we have the other getters and setters to save space…<br />}</td>
																						</tr>
																				</tbody>
																		</table>
																		<p>现在persion对象怎么映射到数据库？SQL Maps并不约束你必须要一个表一个对象或者多个表一个对象这种映射关系。因为你可以自由使用SQL语句，所以约束很小。在这个例子里，我们使用下面简单的表，实现一个表对象一个对象的映射关系。</p>
																		<table class="content" width="70%" border="1">
																				<tbody>
																						<tr>
																								<td class="smallFont" bgcolor="#cccccc">Person.sql<br />CREATE TABLE PERSON(<br />PER_ID NUMBER (5, 0) NOT NULL,<br />PER_FIRST_NAME VARCHAR (40) NOT NULL,<br />PER_LAST_NAME VARCHAR (40) NOT NULL,<br />PER_BIRTH_DATE DATETIME ,<br />PER_WEIGHT_KG NUMBER (4, 2) NOT NULL,<br />PER_HEIGHT_M NUMBER (4, 2) NOT NULL,<br />PRIMARY KEY (PER_ID)<br />)</td>
																						</tr>
																				</tbody>
																		</table>
																		<p>
																				<strong>Fast Track: The SQL Map Configuration File</strong>
																		</p>
																		<p>当我们对我们的工作感到很舒适时，最好的开始就是SQL Map的配置文件。这个文件是SQL Map实现的根配置。</p>
																		<p>配置文件是XML文件，我们用它来配置属性，JDBC DataSources 和 SQL Maps。它给我们一个便利的地方可以集中配置不同的DataSource。这个框架支持iBATIS SimpleDataSource, Jakarta DBCP (Commons)，以及其他任何可以通过JNDI context来访问的DataSource。我们在以后将详细讨论这个问题。现在我们用Jakarta DBCP，结构很简单，象上面这个例子，它的配置文件如下。</p>
																		<p>
																				<span class="smallFont">SqlMapConfigExample.xml</span>
																		</p>
																		<table class="content" width="70%" border="1">
																				<tbody>
																						<tr>
																								<td class="smallFont" bgcolor="#cccccc">
																										<p>&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br /><br />&lt;!DOCTYPE sql-map-config<br />PUBLIC "-//iBATIS.com//DTD SQL Map Config 1.0//EN"<br />"http://www.ibatis.com/dtd/sql-map-config.dtd"&gt;<br /><br /><br />&lt;!-- Always ensure to use the correct XML header as above! --&gt;<br /><br />&lt;sql-map-config&gt;<br /><br />&lt;!-- The properties (name=value) in the file specified here can be used placeholders in this config<br />file (e.g. “${driver}”. The file is relative to the classpath and is completely optional. --&gt;<br /><br />&lt;properties resource="examples/sqlmap/maps/SqlMapConfigExample.properties" /&gt;<br /><br />&lt;!-- These settings control SqlMap configuration details, primarily to do with transaction<br />management. They are all optional (more detail later in this document). --&gt;<br /><br />&lt;settings maxExecute="300"<br />        maxExecutePerConnection="1"<br />        maxTransactions="10"<br />        statementCacheSize="75"<br />        useGlobalTransactions="false"<br />        useBeansMetaClasses=”true”/&gt;<br />&lt;!-- Configure a datasource to use with this SQL Map using Jakarta DBCP.<br />Notice the use of the properties from the above resource --&gt;<br />&lt;datasource name="basic" default = "true"<br />factory-class="com.ibatis.db.sqlmap.datasource.DbcpDataSourceFactory"&gt;<br />        &lt;property name="JDBC.Driver" value="${driver}"/&gt;<br />        &lt;property name="JDBC.ConnectionURL" value="${url}"/&gt;<br />        &lt;property name="JDBC.Username" value="${username}"/&gt;<br />        &lt;property name="JDBC.Password" value="${password}"/&gt;<br />        &lt;property name="Pool.MaximumActiveConnections" value="10"/&gt;<br />        &lt;property name="Pool.MaximumIdleConnections" value="5"/&gt;<br />        &lt;property name="Pool.MaximumWait" value="60000"/&gt;<br />&lt;/datasource&gt;<br /><br />&lt;!-- Identify all SQL Map XML files to be loaded by this SQL map. Notice the paths<br />are relative to the classpath. For now, we only have one… --&gt;<br /><br />&lt;sql-map resource="examples/sqlmap/maps/Person.xml" /&gt;<br /><br />&lt;/sql-map-config&gt;</p>
																								</td>
																						</tr>
																				</tbody>
																		</table>
																		<p>SqlMapConfigExample.properties</p>
																		<table class="content" width="70%" border="1">
																				<tbody>
																						<tr>
																								<td class="smallFont" bgcolor="#cccccc">
																										<p># This is just a simple properties file that simplifies automated configuration<br /># of the SQL Maps configuration file (e.g. by Ant builds or continuous<br /># integration tools for different environments… etc.)<br /># These values can be used in any property value in the file above (e.g. “${driver}”)<br /># Using a properties file such as this is completely optional.</p>
																										<p>
																												<br />driver=oracle.jdbc.driver.OracleDriver<br />url=jdbc:oracle:thin:@localhost:1521:oracle1<br />username=jsmith<br />password=test</p>
																								</td>
																						</tr>
																				</tbody>
																		</table>
																		<p>
																				<strong>Fast Track: The SQL Map File(s)</strong>
																		</p>
																		<p>    现在我们已经配置好DataSource了，然后就要准备核心配置文件了。我们需要准备一个实际的SQL Map文件来存放SQL语句和以及用作映射的参数对象和结果对象（分别是输入和输出）。</p>
																		<p>继续我们上面的示例。让我们为Person类和Person表建立映射关系。我们先建立一个标准结构，和一个简单的select说明。</p>
																		<p>Person.xml</p>
																		<table class="content" width="70%" border="1">
																				<tbody>
																						<tr>
																								<td class="smallFont" bgcolor="#cccccc">&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br /><br />&lt;!DOCTYPE sql-map<br />PUBLIC "-//iBATIS.com//DTD SQL Map 1.0//EN"<br />"http://www.ibatis.com/dtd/sql-map.dtd"&gt;<br /><br />&lt;sql-map name="Person"&gt;<br /><br />    &lt;mapped-statement name="getPerson" result-class="examples.domain.Person"&gt;<br />        SELECT<br />        PER_ID as id,<br />        PER_FIRST_NAME as firstName,<br />        PER_LAST_NAME as lastName,<br />        PER_BIRTH_DATE as birthDate,<br />        PER_WEIGHT_KG as weightInKilograms,<br />        PER_HEIGHT_M as heightInMeters<br />        FROM PERSON<br />        WHERE PER_ID = #value#<br />    &lt;/mapped-statement&gt;<br />&lt;/sql-map&gt;</td>
																						</tr>
																				</tbody>
																		</table>
																		<p>上面的示例显示了一个SQL map的一个最简单的组成。它使用了SQL Maps的一个特性，就是自动根据字段名和JAVABean属性(Map的主键)名建立对应关系。#value#象征着一个输入参数，多情况下，使用"value"意味着我们使用一个基本类型 (e.g. Integer; but we’re not limited to this).</p>
																		<p>因为非常简单，所以使用这种方法有一些限制。首先不能明确指定每个字段的输入类型。没有办法自动加载相关数据（复杂类型），同时有一些性能影响，因为它使用了ResultSetMetaData。通过使用result-map，我们可以克服所有这些限制。但是现在，简单是我们的目标。同是，以后我们可以随便修改成其他方式（不需要修改java代码）。</p>
																		<p>多数JAVA程序不仅读取数据，还要更改数据。我们已经看到怎样在Map-statement里使用select 了，那Update,delete和Insert是什么样的？一个好消息，跟select没有什么区别。下面我们就完成一个我们的Person Sql Map，包括一系列的statement用来操作和修改数据。</p>
																		<p>Person.xml</p>
																		<table class="content" width="70%" border="1">
																				<tbody>
																						<tr>
																								<td bgcolor="#cccccc">
																										<p class="smallFont" style="TEXT-ALIGN: left; mso-layout-grid-align: none" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">&lt;?xml version="1.0" encoding="UTF-8"?&gt;<?XML:NAMESPACE PREFIX = O /?><o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="TEXT-ALIGN: left; mso-layout-grid-align: none" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">&lt;!DOCTYPE sql-map<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="TEXT-ALIGN: left; mso-layout-grid-align: none" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">PUBLIC "-//iBATIS.com//DTD SQL Map 1.0//EN"<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="TEXT-ALIGN: left; mso-layout-grid-align: none" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">"http://www.ibatis.com/dtd/sql-map.dtd"&gt;<o:p></o:p></span>
																												</b>
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">
																																<o:p>
																																</o:p>
																														</span>
																												</b>
																										</p>
																										<p class="smallFont" style="TEXT-ALIGN: left; mso-layout-grid-align: none" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">&lt;sql-map name="Person"&gt;<o:p></o:p></span>
																												</b>
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">
																																<o:p>
																																</o:p>
																														</span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 21pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 2.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: blue; FONT-FAMILY: Arial; mso-font-kerning: 0pt">&lt;!-- Use primitive wrapper type (e.g. Integer) as parameter and allow results to<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 21pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 2.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: blue; FONT-FAMILY: Arial; mso-font-kerning: 0pt">be auto-mapped results to Person object (JavaBean) properties --&gt;<o:p></o:p></span>
																												</b>
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: blue; FONT-FAMILY: Arial; mso-font-kerning: 0pt">
																																<o:p>
																																</o:p>
																														</span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 21pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 2.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">&lt;mapped-statement name="getPerson" result-class="examples.domain.Person"&gt;<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 42pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 4.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">SELECT<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 42pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 4.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">PER_ID as id,<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 42pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 4.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">PER_FIRST_NAME as firstName,<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 42pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 4.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">PER_LAST_NAME as lastName,<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 42pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 4.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">PER_BIRTH_DATE as birthDate,<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 42pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 4.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">PER_WEIGHT_KG as weightInKilograms,<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 42pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 4.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">PER_HEIGHT_M as heightInMeters<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 42pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 4.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">FROM PERSON<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 42pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 4.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">WHERE PER_ID = #value#<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 21pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 2.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">&lt;/mapped-statement&gt;<o:p></o:p></span>
																												</b>
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">
																																<o:p>
																																</o:p>
																														</span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 21pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 2.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: blue; FONT-FAMILY: Arial; mso-font-kerning: 0pt">&lt;!-- Use Person object (JavaBean) properties as parameters for insert. Each of the<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 21pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 2.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: blue; FONT-FAMILY: Arial; mso-font-kerning: 0pt">parameters in the #hash# symbols is a JavaBeans property. --&gt;<o:p></o:p></span>
																												</b>
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: blue; FONT-FAMILY: Arial; mso-font-kerning: 0pt">
																																<o:p>
																																</o:p>
																														</span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 21pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 2.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">&lt;mapped-statement name="insertPerson" &gt;<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 42pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 4.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">INSERT INTO<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 42pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 4.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">PERSON (PER_ID, PER_FIRST_NAME, PER_LAST_NAME,<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 42pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 4.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">PER_BIRTH_DATE, PER_WEIGHT_KG, PER_HEIGHT_M)<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 42pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 4.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">VALUES (#id#, #firstName#, #lastName#,<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 42pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 4.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">#birthDate#, #weightInKilograms#, #heightInMeters#)<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 21pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 2.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">&lt;/mapped-statement&gt;<o:p></o:p></span>
																												</b>
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">
																																<o:p>
																																</o:p>
																														</span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 21pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 2.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: blue; FONT-FAMILY: Arial; mso-font-kerning: 0pt">&lt;!-- Use Person object (JavaBean) properties as parameters for update. Each of the<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 21pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 2.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: blue; FONT-FAMILY: Arial; mso-font-kerning: 0pt">parameters in the #hash# symbols is a JavaBeans property. --&gt;<o:p></o:p></span>
																												</b>
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: blue; FONT-FAMILY: Arial; mso-font-kerning: 0pt">
																																<o:p>
																																</o:p>
																														</span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 21pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 2.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">&lt;mapped-statement name="updatePerson" &gt;<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 42pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 4.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">UPDATE PERSON<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 42pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 4.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">SET (PER_ID = PER_FIRST_NAME = #firstName#,<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 42pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 4.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">PER_LAST_NAME = #lastName#, PER_BIRTH_DATE = #birthDate#,<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 42pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 4.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">PER_WEIGHT_KG = #weightInKilograms#,<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 42pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 4.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">PER_HEIGHT_M = #heightInMeters#)<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 42pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 4.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">WHERE PER_ID = #id#<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 21pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 2.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">&lt;/mapped-statement&gt;<o:p></o:p></span>
																												</b>
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">
																																<o:p>
																																</o:p>
																														</span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 21pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 2.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: blue; FONT-FAMILY: Arial; mso-font-kerning: 0pt">&lt;!-- Use Person object (JavaBean) “id” properties as parameters for delete. Each of the<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 21pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 2.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: blue; FONT-FAMILY: Arial; mso-font-kerning: 0pt">parameters in the #hash# symbols is a JavaBeans property. --&gt;<o:p></o:p></span>
																												</b>
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: blue; FONT-FAMILY: Arial; mso-font-kerning: 0pt">
																																<o:p>
																																</o:p>
																														</span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 21pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 2.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">&lt;mapped-statement name="deletePerson" &gt;<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 31.5pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 3.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">DELETE PERSON<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 31.5pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 3.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">WHERE PER_ID = #id#<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="smallFont" style="MARGIN-LEFT: 21pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 2.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">&lt;/mapped-statement&gt;<o:p></o:p></span>
																												</b>
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">
																																<o:p>
																																</o:p>
																														</span>
																												</b>
																										</p>
																										<p class="MsoNormal" style="TEXT-ALIGN: left; mso-layout-grid-align: none" align="left">
																												<span class="smallFont">
																														<b>
																																<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">&lt;/sql-map&gt;</span>
																														</b>
																														<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">
																																<o:p>
																																</o:p>
																														</span>
																												</span>
																												<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">
																														<o:p>
																														</o:p>
																														<o:p>
																														</o:p>
																												</span>
																										</p>
																								</td>
																						</tr>
																				</tbody>
																		</table>
																		<p>
																				<strong>Fast Track: Programming with the SQL Map Framework</strong>
																		</p>
																		<p>现在我们已经完成了所有的配置和映射，剩下的就是写JAVA代码了。第一步是配置SQL　Map。加载我们前面配置好的SQL Map XML文件是很简单的。加载XML以后，就可以在框架里使用资源类。</p>
																		<table class="content" width="70%" bgcolor="#cccccc" border="1">
																				<tbody>
																						<tr>
																								<td class="smallFont">String resource = “com/ibatis/example/sql-map-config.xml”;<br />Reader reader = Resources.getResourceAsReader (resource);<br />SqlMap sqlMap = XmlSqlMapBuilder.buildSqlMap(reader);</td>
																						</tr>
																				</tbody>
																		</table>
																		<p>SQL Map对象是线程安全的，意味着是长期生存的。对于一个运行的系统来说，你只要配置一次。所以它可以很好的成为一个基类的静态对象（比如，一个BASE Dao类），也许你更喜欢集中配置并成为全局可见，你可以把它包装在你自己的工具类中。比如说：</p>
																		<table class="content" width="70%" bgcolor="#cccccc" border="1">
																				<tbody>
																						<tr>
																								<td>
																										<p class="content" style="TEXT-ALIGN: left; mso-layout-grid-align: none" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">private MyAppSqlConfig {<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="content" style="MARGIN-LEFT: 10.5pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 1.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">private static final SqlMap sqlMap;<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="content" style="MARGIN-LEFT: 10.5pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 1.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">static {<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="content" style="MARGIN-LEFT: 21pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 2.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">try {<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="content" style="MARGIN-LEFT: 31.5pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 3.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">String resource = “com/ibatis/example/sql-map-config.xml”;<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="content" style="MARGIN-LEFT: 31.5pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 3.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">Reader reader = Resources.getResourceAsReader (resource);<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="content" style="MARGIN-LEFT: 31.5pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 3.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">sqlMap = XmlSqlMapBuilder.buildSqlMap(reader);<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="content" style="MARGIN-LEFT: 21pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 2.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">} catch (Exception e) {<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="content" style="MARGIN-LEFT: 31.5pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 3.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: blue; FONT-FAMILY: Arial; mso-font-kerning: 0pt">// If you get an error at this point, it matters little what it was. It is going to be<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="content" style="MARGIN-LEFT: 31.5pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 3.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: blue; FONT-FAMILY: Arial; mso-font-kerning: 0pt">// unrecoverable and we will want the app to blow up good so we are aware of the<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="content" style="MARGIN-LEFT: 31.5pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 3.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: blue; FONT-FAMILY: Arial; mso-font-kerning: 0pt">// problem. You should always log such errors and re-throw them in such a way that<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="content" style="MARGIN-LEFT: 31.5pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 3.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: blue; FONT-FAMILY: Arial; mso-font-kerning: 0pt">// you can be made immediately aware of the problem.<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="content" style="MARGIN-LEFT: 31.5pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 3.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">e.printStackTrace();<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="content" style="MARGIN-LEFT: 31.5pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 3.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">throw new RuntimeException (“Error initializing MyAppSqlConfig class. Cause: ” + e);<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="content" style="MARGIN-LEFT: 21pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 2.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">}<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="content" style="MARGIN-LEFT: 10.5pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 1.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">}<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="content" style="MARGIN-LEFT: 21pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 2.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">public static getSqlMapInstance () {<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="content" style="MARGIN-LEFT: 31.5pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 3.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">return sqlMap;<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="content" style="MARGIN-LEFT: 21pt; TEXT-ALIGN: left; mso-layout-grid-align: none; mso-para-margin-left: 2.0gd" align="left">
																												<b>
																														<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">}<o:p></o:p></span>
																												</b>
																										</p>
																										<p class="MsoNormal" style="TEXT-ALIGN: left; mso-layout-grid-align: none" align="left">
																												<span class="content">
																														<b>
																																<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">}</span>
																														</b>
																														<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">
																																<o:p>
																																</o:p>
																																<o:p>
																																</o:p>
																																<o:p>
																																</o:p>
																														</span>
																												</span>
																												<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">
																														<o:p>
																														</o:p>
																												</span>
																												<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial; mso-font-kerning: 0pt">
																														<o:p>
																														</o:p>
																												</span>
																										</p>
																								</td>
																						</tr>
																				</tbody>
																		</table>
																		<p>
																				<strong>从数据库读取对象</strong>
																		</p>
																		<p> 现在SQL Map实例已经完成初始化，并且很容易访问,我们可以使用它了。首先我们用它从数据库中取得一个Person对象。(举例，我们假设数据库中有10条记录，PER_ID分别从是1到10)</p>
																		<p>为了从数据库中取得一个Person对象，我们需要SQL Map实例，mapped statement的名称以及PER_ID号,让我们读取#5。　</p>
																		<table class="content" width="70%" bgcolor="#cccccc" border="1">
																				<tbody>
																						<tr>
																								<td>…<br />SqlMap sqlMap = MyAppSqlMapConfig.getSqlMapInstance(); // as coded above<br />…<br />Integer personPk = new Integer(5);<br />Person person = (Person) sqlMap.executeQueryForObject (“getPerson”, personPk);<br />…</td>
																						</tr>
																				</tbody>
																		</table>
																		<p>把对象写到数据库中</p>
																		<p> 现在我们已经从数据库取得一个对象，让我们修改一些值，我们将修改身高和体重。   </p>
																		<table class="content" width="70%" border="1">
																				<tbody>
																						<tr>
																								<td class="smallFont" bgcolor="#cccccc">…<br />person.setHeightInMeters(1.83); // person as read from the database above<br />person.setWeightInKilograms(86.36);<br />…<br />sqlMap.executeUpdate(“updatePerson”, person);<br />…</td>
																						</tr>
																				</tbody>
																		</table>
																		<p>如果我们要删除一个对象，也一样的简单。</p>
																		<table class="content" width="70%" bgcolor="#cccccc" border="1">
																				<tbody>
																						<tr>
																								<td class="smallFont">…<br />sqlMap.executeUpdate(“deletePerson”, person);<br />…</td>
																						</tr>
																				</tbody>
																		</table>
																		<p>同样的，新插入一个对象也类似。</p>
																		<table width="70%" bgcolor="#cccccc" border="1">
																				<tbody>
																						<tr>
																								<td class="content">Person newPerson = new Person();<br />newPerson.setId(11); // you would normally get the ID from a sequence or custom table<br />newPerson.setFirstName(“Clinton”);<br />newPerson.setLastName(“Begin”);<br />newPerson.setBirthDate (null);<br />newPerson.setHeightInMeters(1.83);<br />newPerson.setWeightInKilograms(86.36);<br />…<br />sqlMap.executeUpdate (“insertPerson”, newPerson);<br />…</td>
																						</tr>
																				</tbody>
																		</table>
																		<p>
																				<strong>End of Fast Track(结束语)</strong>
																		</p>
																		<p>This is the end of the quick walkthrough. The next several sections will discuss the features of the<br />SqlMap framework in more detail. </p>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/realzar/aggbug/46357.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/realzar/" target="_blank">开源爱好者</a> 2006-05-16 11:08 <a href="http://www.blogjava.net/realzar/archive/2006/05/16/46357.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ibatis介绍</title><link>http://www.blogjava.net/realzar/archive/2006/05/16/46324.html</link><dc:creator>开源爱好者</dc:creator><author>开源爱好者</author><pubDate>Tue, 16 May 2006 01:40:00 GMT</pubDate><guid>http://www.blogjava.net/realzar/archive/2006/05/16/46324.html</guid><wfw:comment>http://www.blogjava.net/realzar/comments/46324.html</wfw:comment><comments>http://www.blogjava.net/realzar/archive/2006/05/16/46324.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/realzar/comments/commentRss/46324.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/realzar/services/trackbacks/46324.html</trackback:ping><description><![CDATA[
		<table cellspacing="0" cellpadding="0" align="center">
				<tbody>
						<tr>
								<td class="title" align="middle">
										<b>
												<font color="#ff0000" size="3">ibatis介绍 <br /></font>
										</b>
								</td>
						</tr>
						<tr>
								<td class="formtitle" align="middle">作者：紫龙</td>
						</tr>
				</tbody>
		</table>
		<table cellspacing="0" cellpadding="0" align="center">
				<tbody>
						<tr>
								<td class="content">
										<table>
												<tbody>
														<tr>
																<td class="content">  在开发过程中最能帮助你的是什么？是框架，一个优秀的框架可以极大的提高你的效率。struts给了我们什么？MVC的实现，国际化、灵活。还有很多。不过，在一个通常的WEB应该中，是不能缺少数据库的，而struts在这方面并没有给我们提供什么有效的帮助。通常情况下我们做这个的时候有几个选择。<br />            最直接的当然是JDBC啊，自己写connect、statment和resultset等等的代码，结果是累死自己。<br />            然后一种方法是EJB，EJB确实是一个好东西，可惜在很多场合用不上，起码它很烦，速度很慢<br />            还有一种选择就是JDO及类似的东西。最著名是free的应该是castor，hibernate等。 
<p>现在我们又多了一种选择，就是ibatis Db Layer，它的主页是http://www.ibatis.com，为什么说它好，让我们来看看作者自己的说明吧，使用ibatis的理由</p>10、知道怎样操作10种以上的数据库<br />9 、可配置的caching(包括从属)<br />8、支持DataSource、local transaction managemen和global transaction<br />7、简单的XML配置文档<br />6、支持Map, Collection, List和简单类型包装(如Integer, String)<br />5、支持JavaBeans类(get/set 方法)<br />4、支持复杂的对象映射(如populating lists, complex object models)<br />3、对象模型从不完美(不需要修改)<br />2、数据模型从不完美(不需要修改)<br />1、你已经知道SQL，为什么还要学习其他东西 
<p>另外一点它是100% Open Source Freeware</p><p>下面我们就来看一看，做一个简单的ibatis需要哪一些工作。然后一步一步深入探索它的强大功能。在实践中来看它的好处在哪里。</p><p>在ibatis的网站上有一个它自己的petstore，在我个人看来是最简洁的petstore了，跟struts1.0结合。应该说是一个不错的教程。希望大家能够好好研究。当然，作为入门。我们先来做一个简单的程序。所采用的库嘛，就仍然是用petstore的了。数据库也是选择Oracle(为什么选择Oracle，很多朋友不理解，怎么不用mysql之类的呢，一个主要的原因是个人爱好，Oracle毕竟是商业数据库，有它的强大之处，另外在linux下它也是免费的，:)。废话少说，先用jpetstore3.1提供的ddl建立一个库吧。</p><p>然后在eclipse里建立一个ibatisDemo的工程。加入ibatis提供的库,建立相就的目录。看一下一个最简单的程序需要哪一些文件。我们选择一个简单表，即Category这个表的操作来演示功能</p><table class="content"><tbody><tr><td>文件路径</td><td>功能说明</td><td>备注</td></tr><tr><td>config\properties\petstore.properties</td><td>可变参数配置文件，所有根据环境不同的参数都放在这里</td><td> </td></tr><tr><td>config\properties\simple\dao.xml</td><td>dao配置文件，主要存放dao对象和数据池设置</td><td> </td></tr><tr><td>config\properties\simple\sql-map-config-storedb.xml</td><td>真正的核心配置文件</td><td> </td></tr><tr><td>config\sqlmap\Category.xml</td><td>存放Category的数据操作的SQL</td><td> </td></tr><tr><td>com.ewuxi.champion.exception.DaoException.java</td><td>自定义的Exception类，不用说了吧</td><td> </td></tr><tr><td>com.ewuxi.champion.Service.java</td><td>一个服务类，用于初始化</td><td> </td></tr><tr><td>com.ewuxi.champion.persistence.dao.DaoCommon</td><td>Dao层的统一操作类，提供一些公共函数</td><td> </td></tr><tr><td>com.ewuxi.champion.persistence.dao.CategoryDb</td><td>Category的操作类</td><td> </td></tr><tr><td>com.ewuxi.champion.persistence.vo.Category</td><td>valueObject 值对象</td><td> </td></tr><tr><td>com.ewuxi.champion.persistence.dao.CategoryDbTest</td><td>单元测试类</td><td> </td></tr></tbody></table><p>下面一个一个文件详细说明</p><p>petstore.properties</p><table class="content" bgcolor="#cccccc"><tbody><tr><td>##################################################################<br />SIMPLE CONFIGURATION SECTION<br />################################################################## 
<p>## SimpleDataSource properties<br />## Use only if useSimpleConfiguration=true</p><p>SimpleDriver=oracle.jdbc.OracleDriver<br />SimpleUrl=jdbc:oracle:thin:@10.0.0.5:1521:champion<br />SimpleUsername=pet<br />SimplePassword=pet</p><p> </p></td></tr></tbody></table><p>这个不用解释，就是数据库的连接串，如果你在自己的机器上运行，当然这些都是需要改的。</p><p>dao.xml</p><table class="content" bgcolor="#cccccc"><tbody><tr><td><p>PUBLIC "-//iBATIS.com//DTD DAO Configuration 1.0//EN"<br />"http://www.ibatis.com/dtd/dao.dtd"&gt;</p><p></p><p><br /><br /><br /><br /></p><p></p><p></p></td></tr></tbody></table><p>上面这一段也是很简单的，连一个dao也没有配置，也就是说，用的是默认的Dao。其中表示它是默认的数据库配置(它可以根据名字不同同时连接几个数据库的)。</p><p>sql-map-config-storedb.xml</p><table class="content" bgcolor="#cccccc"><tbody><tr><td><br />PUBLIC "-//iBATIS.com//DTD SQL Map Config 1.0//EN"<br />"http://www.ibatis.com/dtd/sql-map-config.dtd"&gt; 
<p></p><p></p><p>maxExecute="0"<br />maxExecutePerConnection="0"<br />maxTransactions="0"<br />cacheModelsEnabled="true"<br />statementCacheSize="175"<br />useBeansMetaClasses="false"<br />useGlobalTransactions="false" /&gt;</p><p>factory-class="com.ibatis.db.sqlmap.datasource.DbcpDataSourceFactory"<br />default="true" &gt;<br /><br /><br /><br /><br /><br /><br /><br /></p><p></p><p></p></td></tr></tbody></table><p>这里真正实现了数据库连接，我们使用的是dbcp的连接池。JDBC的配置大家都很熟了。${SimpleDriver}就是指的前面petstore.properties中的SimpleDriver的内容。</p><p>而则表示包含Category.xml这个文件。</p><p>Category.xml</p><table class="content" bgcolor="#cccccc"><tbody><tr><td><p><br />PUBLIC "-//iBATIS.com//DTD SQL Map 1.0//EN"<br />"http://www.ibatis.com/dtd/sql-map.dtd"&gt;</p><p></p><p>　</p><p><br /><br /><br /><br /></p><p><br />select CATID, NAME, DESCN from CATEGORY where CATID = #categoryId#<br /></p><p><br />select CATID, NAME, DESCN from CATEGORY<br /><br /><br />CATID = #categoryId#<br /><br /><br />NAME = #name#<br /><br /><br />DESCN = #description#<br /><br /><br /><br /><br /><br /><br />select count(1) as value from CATEGORY<br /><br /><br /><br />mapped-statement<br />============================================= --&gt;</p><p><br />update CATEGORY<br /><br /><br />NAME = #name#<br /><br /><br />DESCN = #description#<br /><br /><br />where<br />CATID =#categoryId#<br /><br /><br />mapped-statement<br />============================================= --&gt;</p><p><br />delete from CATEGORY<br />where CATID =#categoryId#<br /><br /></p><p>OPTIONAL EXPLICIT PARAMETER MAP<br />============================================= --&gt;</p><p><br /><br /><br /><br /></p><p class="content">MAPPED STATEMENTS - w/Explicit Parameter Map<br />============================================= --&gt;</p><p><br />insert into CATEGORY (<br />CATID,NAME,DESCN)<br />values (<br />?,?,?<br />)<br /><br /></p></td></tr></tbody></table><p>上述文件就是真正的SQL所存在的地方。</p><table class="content"><tbody><tr><td><p><br /><br /><br /><br /></p><p>这一段的内容表示返回的对象是com.ewuxi.champion.persistence.vo.Category，也就是我们值对象。当执行查询的时候，dblay会封装出一个Category对象或者一个Category的list集合。其中数据列CATID就对象javabean的categoryId值。name是自定义的</p></td></tr></tbody></table><table class="content" bgcolor="#cccccc"><tbody><tr><td><p><br />select CATID, NAME, DESCN from CATEGORY where CATID = #categoryId#<br /></p><p>此处result-map="result"表示返回结果以后，就会参照前面的result来返回对象。select CATID, NAME, DESCN from CATEGORY where CATID = #categoryId#标准的SQL，只不过这一点CATID = #categoryId#有些不同，#categoryId#表示传递一个Category对象时，Dblay会自动取得categoryId的值来执行SQL</p></td></tr></tbody></table><p>再来看一个</p><table class="content"><tbody><tr><td><p><br />update CATEGORY<br /><br /><br />NAME = #name#<br /><br /><br />DESCN = #description#<br /><br /><br />where<br />CATID =#categoryId#<br /></p><p>这个地方就体现了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#。是否很强大？:)</p></td></tr></tbody></table><p>前面这两种，参数的传递方式是内置参数，也就是CATID =#categoryId#这种，大家可能不太习惯，那就看一看标准的写法吧。</p><table class="content" bgcolor="#cccccc"><tbody><tr><td><p>OPTIONAL EXPLICIT PARAMETER MAP<br />============================================= --&gt;</p><p><br /><br /><br /><br /></p><p>MAPPED STATEMENTS - w/Explicit Parameter Map<br />============================================= --&gt;</p><p><br />insert into CATEGORY (<br />CATID,NAME,DESCN)<br />values (<br />?,?,?<br />)<br /><br /></p></td></tr></tbody></table><p>这里面的insert语句想来大家都很熟了吧？这个时候怎么取得参数呢？关键在于这里parameter-map="insert-params"，表示会读取的设置，而这个设置也不用多解释了吧，就是按顺序，三个？分别对应三个值。还能指明他们的数据类型。</p><p>下面来看看Service.java</p><table class="content"><tbody><tr><td><br />package com.ewuxi.champion; 
<p>import java.io.Reader;<br />import java.util.Properties;</p><p>import org.apache.commons.logging.Log;<br />import org.apache.commons.logging.LogFactory;</p><p>import com.ibatis.common.resources.Resources;<br />import com.ibatis.db.dao.DaoManager;</p><p>/**<br />* @author champion<br />*<br />* To change the template for this generated type comment go to<br />* Window - Preferences - Java - Code Generation - Code and Comments<br />*/<br />public class Service {<br />static Log log = LogFactory.getLog(Service.class);<br />public static void initSet() {</p><p>try {</p><p>String resource = null;</p><p>resource = "properties/simple/dao.xml";<br />log.info("Using SIMPLE configuration. (" + resource + ")");</p><p>Reader reader = Resources.getResourceAsReader(resource);<br />DaoManager.configure(reader);</p><p>} catch (Exception e) {<br />throw new RuntimeException(<br />"Could not initialize BaseLogic. Cause: " + e);<br />}<br />}</p><p>}<br /></p></td></tr></tbody></table><p>一个静态方法，从resource文件中读出配置，最后用DaoManager.configure(reader);完成配置。</p><p>DaoCommon</p><table class="content" bgcolor="#cccccc"><tbody><tr><td>public static Dao getDefautDao(){<br />return DaoManager.getInstance().getDao("");<br />}<br />public static SqlMap getSqlMap(Dao c) throws DaoException {<br />try {<br />DaoManager daoManager = DaoManager.getInstance(c); 
<p>if (daoManager == null) {<br />daoManager = DaoManager.getInstance();<br />}</p><p>SqlMapDaoTransaction trans = (SqlMapDaoTransaction) daoManager.getLocalTransaction();<br />SqlMap sqlMap = trans.getSqlMap();</p><p>return sqlMap;<br />} catch (Exception e) {<br />throw new DaoException(e);<br />}<br />}</p><p>public static SqlMap getSqlMap(String c) throws DaoException {<br />try {<br />DaoManager daoManager = DaoManager.getInstance(c);<br />SqlMapDaoTransaction trans = (SqlMapDaoTransaction) daoManager.getLocalTransaction();<br />SqlMap sqlMap = trans.getSqlMap();</p><p>return sqlMap;<br />} catch (Exception e) {<br />throw new DaoException(e);<br />}<br />}<br /></p></td></tr></tbody></table><p>三个主要的函数，第一个是得到默认的DAO对象，后两个是根据一个dao对象或者一个参数(也就是前面中是name值)。取得SqlMap对象，这个对象是主要的数据操作接口。</p><table class="content" bgcolor="#cccccc"><tbody><tr><td>/**<br />* @throws Exception<br />* 开始事务，所在session层必须使用它<br />*/<br />public static void startTransaction() throws Exception {<br />if (!DaoCommon.inTransaction()) {<br />DaoManager.getInstance().startTransaction();<br />}<br />} 
<p>public static boolean inTransaction() throws Exception {<br />try {<br />DaoManager.getInstance().getLocalTransaction();<br /><br />return true;<br />} catch (Exception e) {<br />return false;<br />}<br />}</p><p>/**<br />* @throws Exception<br />* 放弃事务<br />*/<br />public static void rollBack() {<br /><br />try {<br />DaoManager.getInstance().rollbackTransaction();<br />} catch (Exception e) {<br />LogFactory.getLog(DaoCommon.class).error(e, e);<br />}<br />}</p><p>/**<br />* @throws Exception<br />* 提交事务<br />*/<br />public static void commit() throws Exception {<br />DaoManager.getInstance().commitTransaction();<br />}</p></td></tr></tbody></table><p>下面的一些函数是对事务的一些封装。想必也很容易理解。</p><p>然后让我们来看CategoryDb的内容</p><table class="content" bgcolor="#cccccc"><tbody><tr><td>/*<br />* Created on 2003-10-11<br />*<br />* To change the template for this generated file go to<br />* Window - Preferences - Java - Code Generation - Code and Comments<br />*/<br />package com.ewuxi.champion.persistence.dao; 
<p>import com.ewuxi.champion.exception.DaoException;<br />import com.ewuxi.champion.persistence.vo.Category;<br />import com.ibatis.db.sqlmap.SqlMap;</p><p>/**<br />* @author champion<br />*<br />*category数据库操作对象<br />*/</p><p>public class CategoryDb {<br /><br />/**<br />* @param vo<br />* @throws DaoException<br />* 插入一条记录<br />*/<br />public void insert(Category vo) throws DaoException{<br />try {<br />SqlMap sqlMap=DaoCommon.getSqlMap(DaoCommon.getDefautDao());<br />sqlMap.executeUpdate("insertCategoryDao",vo);<br />} catch (Exception e) {<br />throw new DaoException(e);<br />}<br />}<br />/**<br />* @param vo<br />* @throws DaoException<br />* 删除一条记录<br />*/<br />public void delete(Category vo) throws DaoException{<br />try {<br />SqlMap sqlMap=DaoCommon.getSqlMap(DaoCommon.getDefautDao());<br />sqlMap.executeUpdate("deleteByPrimaryKeyCategoryDao",vo);<br />} catch (Exception e) {<br />throw new DaoException(e);<br />}<br />}<br />/**<br />* @param vo<br />* @throws DaoException<br />* 修改一条记录<br />*/<br />public void update(Category vo) throws DaoException{<br />try {<br />SqlMap sqlMap=DaoCommon.getSqlMap(DaoCommon.getDefautDao());<br />sqlMap.executeUpdate("updateByPrimaryKeyCategoryDao",vo);<br />} catch (Exception e) {<br />throw new DaoException(e);<br />}<br />}<br />/**<br />* @param vo<br />* @return<br />* @throws DaoException<br />* 查找一条记录<br />*/<br />public Category findByPk(Category vo) throws DaoException{<br />try {<br />SqlMap sqlMap=DaoCommon.getSqlMap(DaoCommon.getDefautDao());<br />return (Category) sqlMap.executeQueryForObject("findByPrimaryKeyCategoryDao",vo);<br />} catch (Exception e) {<br />throw new DaoException(e);<br />}<br />}<br /><br />}<br /></p><p><br /></p></td></tr></tbody></table><p>每一个函数都很类似的。关键就在这一句(Category) sqlMap.executeQueryForList("findByPrimaryKeyCategoryDao",vo);。看到"findByPrimaryKeyCategoryDao"，这个对应于前面Category.xml中的名字。而vo则是一个Category对象。</p><p>最后是CategoryDbTest类，这个是我们的单元测试程序</p><table class="content"><tbody><tr><td><p>/*<br />* Created on 2003-10-11<br />*<br />* To change the template for this generated file go to<br />* Window - Preferences - Java - Code Generation - Code and Comments<br />*/<br />package com.ewuxi.champion.persistence.dao;</p><p>import com.ewuxi.champion.exception.DaoException;<br />import com.ewuxi.champion.persistence.vo.Category;<br />import com.ibatis.db.sqlmap.SqlMap;</p><p>/**<br />* @author champion<br />*<br />*category数据库操作对象<br />*/</p><p>public class CategoryDb {<br /><br />/**<br />* @param vo<br />* @throws DaoException<br />* 插入一条记录<br />*/<br />public void insert(Category vo) throws DaoException{<br />try {<br />SqlMap sqlMap=DaoCommon.getSqlMap(DaoCommon.getDefautDao());<br />sqlMap.executeUpdate("insertCategoryDao",vo);<br />} catch (Exception e) {<br />throw new DaoException(e);<br />}<br />}<br />/**<br />* @param vo<br />* @throws DaoException<br />* 删除一条记录<br />*/<br />public void delete(Category vo) throws DaoException{<br />try {<br />SqlMap sqlMap=DaoCommon.getSqlMap(DaoCommon.getDefautDao());<br />sqlMap.executeUpdate("deleteByPrimaryKeyCategoryDao",vo);<br />} catch (Exception e) {<br />throw new DaoException(e);<br />}<br />}<br />/**<br />* @param vo<br />* @throws DaoException<br />* 修改一条记录<br />*/<br />public void update(Category vo) throws DaoException{<br />try {<br />SqlMap sqlMap=DaoCommon.getSqlMap(DaoCommon.getDefautDao());<br />sqlMap.executeUpdate("updateByPrimaryKeyCategoryDao",vo);<br />} catch (Exception e) {<br />throw new DaoException(e);<br />}<br />}<br />/**<br />* @param vo<br />* @return<br />* @throws DaoException<br />* 查找一条记录<br />*/<br />public Category findByPk(Category vo) throws DaoException{<br />try {<br />SqlMap sqlMap=DaoCommon.getSqlMap(DaoCommon.getDefautDao());<br />return (Category) sqlMap.executeQueryForObject("findByPrimaryKeyCategoryDao",vo);<br />} catch (Exception e) {<br />throw new DaoException(e);<br />}<br />}<br /><br />}<br /></p></td></tr></tbody></table></td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/realzar/aggbug/46324.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/realzar/" target="_blank">开源爱好者</a> 2006-05-16 09:40 <a href="http://www.blogjava.net/realzar/archive/2006/05/16/46324.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ibatis  开发指南  </title><link>http://www.blogjava.net/realzar/archive/2006/05/16/46303.html</link><dc:creator>开源爱好者</dc:creator><author>开源爱好者</author><pubDate>Mon, 15 May 2006 16:55:00 GMT</pubDate><guid>http://www.blogjava.net/realzar/archive/2006/05/16/46303.html</guid><wfw:comment>http://www.blogjava.net/realzar/comments/46303.html</wfw:comment><comments>http://www.blogjava.net/realzar/archive/2006/05/16/46303.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/realzar/comments/commentRss/46303.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/realzar/services/trackbacks/46303.html</trackback:ping><description><![CDATA[
		<li>
				<a href="http://sg.kehui.net/index.php?op=article&amp;file=read&amp;aid=57948">基于struts+spring+ibatis的轻量级J2EE开发</a>
				<font color="#999999">[yanwp 2006-01-26]</font>
		</li>
		<li>
				<a href="http://sg.kehui.net/index.php?op=article&amp;file=read&amp;aid=57469">iBATIS，循序渐进介绍如何做O/R Mapping...！</a>
				<font color="#999999">[yanwp 2006-01-26]</font>
		</li>
		<li>
				<a href="http://sg.kehui.net/index.php?op=article&amp;file=read&amp;aid=57467">基于struts+spring+ibatis的轻量级J2EE开发 </a>
				<font color="#999999">[yanwp 2006-01-26]</font>
		</li>
		<li>
				<a href="http://sg.kehui.net/index.php?op=article&amp;file=read&amp;aid=53361">Hibernate VS iBATIS</a>
				<font color="#999999">[yanwp 2006-01-26]</font>
		</li>
		<li>
				<a href="http://sg.kehui.net/index.php?op=article&amp;file=read&amp;aid=47912">的确不错的iBATIS SQL Maps</a>
				<font color="#999999">[yanwp 2006-01-26]</font>
		</li>
		<li>
				<a href="http://sg.kehui.net/index.php?op=article&amp;file=read&amp;aid=47141">从Jpetstore 开始IBATIS之旅</a>
				<font color="#999999">[yanwp 2006-01-26]</font>
		</li>
		<li>
				<a href="http://sg.kehui.net/index.php?op=article&amp;file=read&amp;aid=45799">Asp.net，IBatis For .Net，DAOFactory在Web开发中的数据表示 </a>
				<font color="#999999">[yanwp 2006-01-26]</font>
		</li>
		<li>
				<a href="http://sg.kehui.net/index.php?op=article&amp;file=read&amp;aid=44550">Hibernate、iBATIS 与 BLOB</a>
				<font color="#999999">[yanwp 2006-01-26]</font>
		</li>
		<li>
				<a href="http://sg.kehui.net/index.php?op=article&amp;file=read&amp;aid=43437">Hibernate、iBATIS 与 BLOB</a>
				<font color="#999999">[yanwp 2006-01-26]</font>
		</li>
		<li>
				<a href="http://sg.kehui.net/index.php?op=article&amp;file=read&amp;aid=43080">我的IBatisNet实践</a>
				<font color="#999999">[yanwp 2006-01-26]</font>
		</li>
<img src ="http://www.blogjava.net/realzar/aggbug/46303.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/realzar/" target="_blank">开源爱好者</a> 2006-05-16 00:55 <a href="http://www.blogjava.net/realzar/archive/2006/05/16/46303.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>IBATISNETNET 1.3 开发指南系列文章 </title><link>http://www.blogjava.net/realzar/archive/2006/05/16/46302.html</link><dc:creator>开源爱好者</dc:creator><author>开源爱好者</author><pubDate>Mon, 15 May 2006 16:44:00 GMT</pubDate><guid>http://www.blogjava.net/realzar/archive/2006/05/16/46302.html</guid><wfw:comment>http://www.blogjava.net/realzar/comments/46302.html</wfw:comment><comments>http://www.blogjava.net/realzar/archive/2006/05/16/46302.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/realzar/comments/commentRss/46302.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/realzar/services/trackbacks/46302.html</trackback:ping><description><![CDATA[月初发的一篇Post<a class="postTitle2" id="viewpost1_TitleUrl" href="http://www.cnblogs.com/shanyou/archive/2006/04/01/364147.html"><font color="#6faf30">准备写一个Ibatisnet开发指南</font></a>,得到非常强烈的反应，最近比较忙，完成的也很慢。现在很多的开发开始转向DotNet 2.0,IBatisNet 1.3也将直接支持DotNet 2.0的数据方面两大特性：Nullable和泛型，IBatisNet 1.3也直接支持Sql server 2005。所以这个开发指南约定使用VS 2005和IBatisNet 1.3版本。IBatisNet 1.3现在还是在beta阶段，但愿在IBatisNet 1.3正式Release的时候这个指南能够完成。<br />    <br />      <a class="titlelink" id="Editor_Results_rprSelectionList_ctl02_Hyperlink1" href="http://www.cnblogs.com/shanyou/articles/376093.html"><font color="#000000">Ibatisnet介绍</font></a> <br />      <a class="titlelink" id="Editor_Results_rprSelectionList_ctl01_LinkTitle" href="http://www.cnblogs.com/shanyou/articles/376094.html"><font color="#000000">Ibatisnet Quick Start</font></a>     <br /><br /><img src ="http://www.blogjava.net/realzar/aggbug/46302.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/realzar/" target="_blank">开源爱好者</a> 2006-05-16 00:44 <a href="http://www.blogjava.net/realzar/archive/2006/05/16/46302.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基于struts+spring+ibatis的 J2EE 开发</title><link>http://www.blogjava.net/realzar/archive/2006/05/16/46301.html</link><dc:creator>开源爱好者</dc:creator><author>开源爱好者</author><pubDate>Mon, 15 May 2006 16:42:00 GMT</pubDate><guid>http://www.blogjava.net/realzar/archive/2006/05/16/46301.html</guid><wfw:comment>http://www.blogjava.net/realzar/comments/46301.html</wfw:comment><comments>http://www.blogjava.net/realzar/archive/2006/05/16/46301.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/realzar/comments/commentRss/46301.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/realzar/services/trackbacks/46301.html</trackback:ping><description><![CDATA[
		<table class="top" cellspacing="0" cellpadding="0" width="96%" align="center" border="0">
				<tbody>
						<tr>
								<td>1、<a href="http://www.dingl.com/view.shtml?xh=501" target="_blank">基于struts+spring+ibatis的 J2EE 开发(5)</a> 2005-04-20</td>
						</tr>
						<tr>
								<td height="5">
								</td>
						</tr>
						<tr>
								<td>2、<a href="http://www.dingl.com/view.shtml?xh=500" target="_blank">基于struts+spring+ibatis的 J2EE 开发(4)</a> 2005-04-20</td>
						</tr>
						<tr>
								<td height="5">
								</td>
						</tr>
						<tr>
								<td>3、<a href="http://www.dingl.com/view.shtml?xh=499" target="_blank">基于struts+spring+ibatis的 J2EE 开发(3)</a> 2005-04-20</td>
						</tr>
						<tr>
								<td height="5">
								</td>
						</tr>
						<tr>
								<td>4、<a href="http://www.dingl.com/view.shtml?xh=498" target="_blank">基于struts+spring+ibatis的 J2EE 开发(2)</a> 2005-04-20</td>
						</tr>
						<tr>
								<td height="5">
								</td>
						</tr>
						<tr>
								<td>5、<a href="http://www.dingl.com/view.shtml?xh=497" target="_blank">基于struts+spring+ibatis的 J2EE 开发(1)</a> </td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/realzar/aggbug/46301.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/realzar/" target="_blank">开源爱好者</a> 2006-05-16 00:42 <a href="http://www.blogjava.net/realzar/archive/2006/05/16/46301.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>