﻿<?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-　　　　　　　　　　　　　礼物 ^_^ -文章分类-ibatis + spring </title><link>http://www.blogjava.net/libin2722/category/27870.html</link><description>虚其心，可解天下之问；专其心，可治天下之学；静其心，可悟天下之理；恒其心，可成天下之业。</description><language>zh-cn</language><lastBuildDate>Mon, 19 Oct 2009 07:01:39 GMT</lastBuildDate><pubDate>Mon, 19 Oct 2009 07:01:39 GMT</pubDate><ttl>60</ttl><item><title>iBatis 新增时候主键的获取(MySql)</title><link>http://www.blogjava.net/libin2722/articles/297835.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Mon, 12 Oct 2009 00:45:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/articles/297835.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/297835.html</wfw:comment><comments>http://www.blogjava.net/libin2722/articles/297835.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/297835.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/297835.html</trackback:ping><description><![CDATA[&lt;insert id="insertAccount" parameterClass="java.util.Map"&gt;<br />        insert into usersrcaccount<br />        (<br />            USER_ID,<br />            SOURCETYPE,<br />            ACCOUNT,<br />            PASSWORD<br />        )<br />        values<br />        (<br />            #userId#,<br />            #sourceType#,<br />            #account#,<br />            #password#<br />        )<br />        &lt;selectKey resultClass="java.lang.Long" keyProperty="id" &gt;<br />            SELECT @@IDENTITY AS id<br />        &lt;/selectKey&gt;<br />    &lt;/insert&gt;<img src ="http://www.blogjava.net/libin2722/aggbug/297835.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2009-10-12 08:45 <a href="http://www.blogjava.net/libin2722/articles/297835.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ibatis中由SELECT语句自动生成COUNT语句</title><link>http://www.blogjava.net/libin2722/articles/197816.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Fri, 02 May 2008 16:31:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/articles/197816.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/197816.html</wfw:comment><comments>http://www.blogjava.net/libin2722/articles/197816.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/197816.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/197816.html</trackback:ping><description><![CDATA[下面的内容是基于ibatis2.2，以后的版本是否提供了类似功能不太清楚，甚至这个版本是否提供也没有细究（好像没有）。<br />
<br />
很多时候我们需要执行select语句对应的count语句，例如分页查询时要得到结果的记录数，但在ibatis的映射文件中我们只想写一条select语句，而count语句直接由这条语句生成，这可以省去很多不必要的语句关联，下面的代码可以实现这一点。<br />
<br />
CountStatementUtil.java<br />
<br />
java 代码<br />
package com.aladdin.dao.ibatis.ext;    <br />
<br />
import java.sql.Connection;    <br />
import java.sql.SQLException;    <br />
import java.util.List;    <br />
<br />
import com.aladdin.util.ReflectUtil;    <br />
import com.ibatis.common.jdbc.exception.NestedSQLException;    <br />
import com.ibatis.sqlmap.client.event.RowHandler;    <br />
import com.ibatis.sqlmap.engine.impl.ExtendedSqlMapClient;    <br />
import com.ibatis.sqlmap.engine.mapping.parameter.ParameterMap;    <br />
import com.ibatis.sqlmap.engine.mapping.result.AutoResultMap;    <br />
import com.ibatis.sqlmap.engine.mapping.result.BasicResultMap;    <br />
import com.ibatis.sqlmap.engine.mapping.result.ResultMap;    <br />
import com.ibatis.sqlmap.engine.mapping.sql.Sql;    <br />
import com.ibatis.sqlmap.engine.mapping.statement.ExecuteListener;    <br />
import com.ibatis.sqlmap.engine.mapping.statement.MappedStatement;    <br />
import com.ibatis.sqlmap.engine.mapping.statement.RowHandlerCallback;    <br />
import com.ibatis.sqlmap.engine.mapping.statement.SelectStatement;    <br />
import com.ibatis.sqlmap.engine.scope.ErrorContext;    <br />
import com.ibatis.sqlmap.engine.scope.RequestScope;    <br />
<br />
public class CountStatementUtil {    <br />
<br />
public static MappedStatement createCountStatement(MappedStatement selectStatement) {    <br />
return new CountStatement((SelectStatement) selectStatement);    <br />
}    <br />
<br />
public static String getCountStatementId(String selectStatementId) {    <br />
return "__" + selectStatementId + "Count__";    <br />
}    <br />
<br />
}    <br />
<br />
class CountStatement extends SelectStatement {    <br />
<br />
public CountStatement(SelectStatement selectStatement) {    <br />
super();    <br />
setId(CountStatementUtil.getCountStatementId(selectStatement    <br />
.getId()));    <br />
setResultSetType(selectStatement.getResultSetType());    <br />
setFetchSize(1);    <br />
setParameterMap(selectStatement.getParameterMap());    <br />
setParameterClass(selectStatement.getParameterClass());    <br />
setSql(selectStatement.getSql());    <br />
setResource(selectStatement.getResource());    <br />
setSqlMapClient(selectStatement.getSqlMapClient());    <br />
setTimeout(selectStatement.getTimeout());           <br />
List executeListeners = (List) ReflectUtil.getFieldValue(    <br />
selectStatement, "executeListeners", List.class);    <br />
if (executeListeners != null) {    <br />
for (Object listener : executeListeners) {    <br />
addExecuteListener((ExecuteListener) listener);    <br />
}    <br />
}    <br />
BasicResultMap resultMap = new AutoResultMap(    <br />
((ExtendedSqlMapClient) getSqlMapClient()).getDelegate(), false);    <br />
resultMap.setId(getId() + "-AutoResultMap");    <br />
resultMap.setResultClass(Long.class);    <br />
resultMap.setResource(getResource());    <br />
setResultMap(resultMap);    <br />
<br />
}    <br />
<br />
protected void executeQueryWithCallback(RequestScope request,    <br />
Connection conn, Object parameterObject, Object resultObject,    <br />
RowHandler rowHandler, int skipResults, int maxResults)    <br />
throws SQLException {    <br />
ErrorContext errorContext = request.getErrorContext();    <br />
errorContext    <br />
.setActivity("preparing the mapped statement for execution");    <br />
errorContext.setObjectId(this.getId());    <br />
errorContext.setResource(this.getResource());    <br />
<br />
try {    <br />
parameterObject = validateParameter(parameterObject);    <br />
<br />
Sql sql = getSql();    <br />
<br />
errorContext.setMoreInfo("Check the parameter map.");    <br />
ParameterMap parameterMap = sql.getParameterMap(request,    <br />
parameterObject);    <br />
<br />
errorContext.setMoreInfo("Check the result map.");    <br />
ResultMap resultMap = getResultMap(request, parameterObject, sql);    <br />
<br />
request.setResultMap(resultMap);    <br />
request.setParameterMap(parameterMap);    <br />
<br />
errorContext.setMoreInfo("Check the parameter map.");    <br />
Object[] parameters = parameterMap.getParameterObjectValues(    <br />
request, parameterObject);    <br />
<br />
errorContext.setMoreInfo("Check the SQL statement.");    <br />
String sqlString = getSqlString(request, parameterObject, sql);    <br />
<br />
errorContext.setActivity("executing mapped statement");    <br />
errorContext    <br />
.setMoreInfo("Check the SQL statement or the result map.");    <br />
RowHandlerCallback callback = new RowHandlerCallback(resultMap,    <br />
resultObject, rowHandler);    <br />
sqlExecuteQuery(request, conn, sqlString, parameters, skipResults,    <br />
maxResults, callback);    <br />
<br />
errorContext.setMoreInfo("Check the output parameters.");    <br />
if (parameterObject != null) {    <br />
postProcessParameterObject(request, parameterObject, parameters);    <br />
}    <br />
<br />
errorContext.reset();    <br />
sql.cleanup(request);    <br />
notifyListeners();    <br />
} catch (SQLException e) {    <br />
errorContext.setCause(e);    <br />
throw new NestedSQLException(errorContext.toString(), e    <br />
.getSQLState(), e.getErrorCode(), e);    <br />
} catch (Exception e) {    <br />
errorContext.setCause(e);    <br />
throw new NestedSQLException(errorContext.toString(), e);    <br />
}    <br />
}    <br />
<br />
private String getSqlString(RequestScope request, Object parameterObject,    <br />
Sql sql) {    <br />
String sqlString = sql.getSql(request, parameterObject);    <br />
int start = sqlString.toLowerCase().indexOf("from");    <br />
if (start &gt;= 0) {    <br />
sqlString = "SELECT COUNT(*) AS c " + sqlString.substring(start);    <br />
}    <br />
return sqlString;    <br />
}    <br />
<br />
private ResultMap getResultMap(RequestScope request,    <br />
Object parameterObject, Sql sql) {    <br />
return getResultMap();    <br />
}    <br />
<br />
}    <br />
<br />
上面代码中的getSqlString方法可以根据自己系统select语句的复杂程度完善，这里给出的是最简单的实现。<br />
<br />
使用上面的类即可由select语句生成count语句，下面是通过spring使用的代码：<br />
<br />
BaseDaoiBatis.java<br />
<br />
java 代码<br />
//...    <br />
public abstract class BaseDaoiBatis extends SqlMapClientDaoSupport {    <br />
<br />
//...    <br />
<br />
protected long getObjectTotal(String selectQuery, Object parameterObject) {    <br />
prepareCountQuery(selectQuery);    <br />
//...    <br />
return (Long) getSqlMapClientTemplate().queryForObject(    <br />
CountStatementUtil.getCountStatementId(selectQuery),    <br />
parameterObject);    <br />
}    <br />
<br />
protected void prepareCountQuery(String selectQuery) {    <br />
<br />
String countQuery = CountStatementUtil.getCountStatementId(selectQuery);    <br />
if (logger.isDebugEnabled()) {    <br />
logger.debug("Convert " + selectQuery + " to " + countQuery);    <br />
}    <br />
SqlMapClient sqlMapClient = getSqlMapClientTemplate().getSqlMapClient();    <br />
if (sqlMapClient instanceof ExtendedSqlMapClient) {    <br />
SqlMapExecutorDelegate delegate = ((ExtendedSqlMapClient) sqlMapClient)    <br />
.getDelegate();    <br />
try {    <br />
delegate.getMappedStatement(countQuery);    <br />
} catch (SqlMapException e) {    <br />
delegate.addMappedStatement(CountStatementUtil    <br />
.createCountStatement(delegate    <br />
.getMappedStatement(selectQuery)));    <br />
}    <br />
<br />
}    <br />
}    <br />
<br />
//...    <br />
}
<img src ="http://www.blogjava.net/libin2722/aggbug/197816.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-05-03 00:31 <a href="http://www.blogjava.net/libin2722/articles/197816.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>对ibatis分页功能的改进  </title><link>http://www.blogjava.net/libin2722/articles/192504.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Sun, 13 Apr 2008 00:51:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/articles/192504.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/192504.html</wfw:comment><comments>http://www.blogjava.net/libin2722/articles/192504.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/192504.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/192504.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 今天无意间看到了一篇关于这方面的文章，觉得是网上改进ibatis分页方面比较好的文章，这里转摘一下，希望能让更多的人用的到，也希望别人能把更好的解决方案贡献出来！function StorePage(){d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.g...&nbsp;&nbsp;<a href='http://www.blogjava.net/libin2722/articles/192504.html'>阅读全文</a><img src ="http://www.blogjava.net/libin2722/aggbug/192504.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-04-13 08:51 <a href="http://www.blogjava.net/libin2722/articles/192504.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基于struts+spring+ibatis的 J2EE 开发(2)</title><link>http://www.blogjava.net/libin2722/articles/165550.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 05 Dec 2007 08:04:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/articles/165550.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/165550.html</wfw:comment><comments>http://www.blogjava.net/libin2722/articles/165550.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/165550.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/165550.html</trackback:ping><description><![CDATA[<table cellspacing="0" cellpadding="0" width="96%" align="center" border="0">
    <tbody>
        <tr>
            <td class="big" valign="top" width="540">
            <p>&nbsp;</p>
            <p><a href="javascript:location.href='http://www.onedoor.cn/favorite/post?&amp;url='+encodeURIComponent(location.href)+'&amp;title='+encodeURIComponent(document.title)"><font style="font-weight: bold; font-size: 14px" color="red">将此文章收藏到豌豆网</font></a></p>
            <p>
            <div>2.4. 代码剖析<br />
            <br />
            下面就让我们开始进一步分析JpetStore4.0的源代码，为下面的改造铺路。BeanAction.java是唯一一个Struts action类，位于com.ibatis.struts包下。正如上文所言，它是一个通用的控制类，利用反射机制，把控制转移到form bean的某个方法来处理。详细处理过程参考其源代码，简单明晰。<br />
            <br />
            Form bean类位于com.ibatis.jpetstore.presentation包下，命名规则为***Bean。Form bean类全部继承于BaseBean类，而BaseBean类实际继承于ActionForm，因此，Form bean类就是Struts的 ActionForm，Form bean类的属性数据就由struts框架自动填充。而实际上，JpetStore4.0扩展了struts中ActionForm的应用： Form bean类还具有行为，更像一个BO,其行为（方法）由BeanAction根据配置（struts-config.xml）的URL来调用。虽然如此，我们还是把Form bean类定位于表现层。Struts-config.xml的配置里有3种映射方式，来告诉BeanAction把控制转到哪个form bean对象的哪个方法来处理。以这个请求连接为例http://localhost/jpetstore4/shop/viewOrder.do<br />
            <br />
            1. URL Pattern<br />
            <br />
            <center><ccid_nobr>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" style="font-size: 9pt" bgcolor="#e6e6e6">
                        <pre><ccid_code>&lt;action path="/shop/viewOrder" type="com.ibatis.struts.BeanAction"
                        name="orderBean" scope="session"
                        validate="false"&gt;
                        &lt;forward name="success" path="/order/ViewOrder.jsp"/&gt;
                        &lt;/action&gt;</ccid_code></pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </ccid_nobr></center><br />
            <br />
            此种方式表示，控制将被转发到"orderBean"这个form bean对象 的"viewOrder"方法（行为）来处理。方法名取"path"参数的以"/"分隔的最后一部分。 <br />
            <br />
            2. Method Parameter <br />
            <br />
            <center><ccid_nobr>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" style="font-size: 9pt" bgcolor="#e6e6e6">
                        <pre><ccid_code>&lt;action path="/shop/viewOrder" type="com.ibatis.struts.BeanAction"
                        name="orderBean" parameter="viewOrder" scope="session"
                        validate="false"&gt;
                        &lt;forward name="success" path="/order/ViewOrder.jsp"/&gt;
                        &lt;/action&gt;</ccid_code></pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </ccid_nobr></center><br />
            <br />
            此种方式表示，控制将被转发到"orderBean"这个form bean对象的"viewOrder"方法（行为）来处理。配置中的"parameter"参数表示form bean类上的方法。"parameter"参数优先于"path"参数。 <br />
            <br />
            3. No Method call <br />
            <br />
            <center><ccid_nobr>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" style="font-size: 9pt" bgcolor="#e6e6e6">
                        <pre><ccid_code>&lt;action path="/shop/viewOrder" type="com.ibatis.struts.BeanAction"
                        name="orderBean" parameter="*" scope="session"
                        validate="false"&gt;
                        &lt;forward name="success" path="/order/ViewOrder.jsp"/&gt;
                        &lt;/action&gt;</ccid_code></pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </ccid_nobr></center><br />
            <br />
            此种方式表示，form bean上没有任何方法被调用。如果存在"name"属性，则struts把表单参数等数据填充到form bean对象后，把控制转发到"success"。否则，如果name为空，则直接转发控制到"success"。这就相当于struts内置的org.apache.struts.actions.ForwardAction的功能 <br />
            <br />
            <center><ccid_nobr>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" style="font-size: 9pt" bgcolor="#e6e6e6">
                        <pre><ccid_code>&lt;action path="/shop/viewOrder" type="org.apache.struts.actions.ForwardAction"
                        parameter="/order/ViewOrder.jsp " scope="session" validate="false"&gt;
                        &lt;/action&gt;</ccid_code></pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </ccid_nobr></center><br />
            <br />
            Service类位于com.ibatis.jpetstore.service包下，属于业务层。这些类封装了业务以及相应的事务控制。Service类由form bean类来调用。 <br />
            <br />
            com.ibatis.jpetstore.persistence.iface包下的类是DAO接口，属于业务层，其屏蔽了底层的数据库操作，供具体的Service类来调用。DaoConfig类是工具类（DAO工厂类），Service类通过DaoConfig类来获得相应的DAO接口，而不用关心底层的具体数据库操作，实现了如图2中{耦合2}的解耦。 <br />
            <br />
            com.ibatis.jpetstore.persistence.sqlmapdao包下的类是对应DAO接口的具体实现，在JpetStore4.0中采用了ibatis来实现ORM。这些实现类继承BaseSqlMapDao类，而BaseSqlMapDao类则继承ibatis DAO 框架中的SqlMapDaoTemplate类。ibatis的配置文件存放在com.ibatis.jpetstore.persistence.sqlmapdao.sql目录下。这些类和配置文件位于数据层 <br />
            <br />
            Domain类位于com.ibatis.jpetstore.domain包下，是普通的javabean。在这里用作数据传输对象（DTO），贯穿视图层、业务层和数据层，用于在不同层之间传输数据。剩下的部分就比较简单了，请看具体的源代码，非常清晰。 <br />
            </div>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.blogjava.net/libin2722/aggbug/165550.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2007-12-05 16:04 <a href="http://www.blogjava.net/libin2722/articles/165550.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基于struts+spring+ibatis的 J2EE 开发(3)</title><link>http://www.blogjava.net/libin2722/articles/165549.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 05 Dec 2007 08:03:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/articles/165549.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/165549.html</wfw:comment><comments>http://www.blogjava.net/libin2722/articles/165549.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/165549.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/165549.html</trackback:ping><description><![CDATA[2.5. 需要改造的地方<br />
<br />
JpetStore4.0的关键就在struts Action类和form bean类上，这也是其精华之一（虽然该实现方式是试验性，待扩充和验证），在此次改造中我们要保留下来，即控制层一点不变，表现层获取相应业务类的方式变了（要加载spring环境），其它保持不变。要特别关注的改动是业务层和持久层，幸运的是JpetStore4.0设计非常好，需要改动的地方非常少，而且由模式可循，如下：<br />
<br />
1. 业务层和数据层用Spring BeanFactory机制管理。<br />
2. 业务层的事务由spring 的aop通过声明来完成。<br />
3. 表现层（form bean）获取业务类的方法改由自定义工厂类来实现（加载spring环境）。<br />
<br />
3. JPetStore的改造<br />
<br />
3.1. 改造后的架构<br />
<br />
<center><img src="http://www.dingl.com/images/qt/397093.gif"  alt="" /></center><br />
<br />
其中红色部分是要增加的部分，蓝色部分是要修改的部分。下面就让我们逐一剖析。<br />
<br />
3.2. Spring Context的加载<br />
为了在Struts中加载Spring Context，一般会在struts-config.xml的最后添加如下部分：<br />
<br />
<center><ccid_nobr>
<table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
    <tbody>
        <tr>
            <td class="code" style="font-size: 9pt" bgcolor="#e6e6e6">
            <pre><ccid_code>&lt;plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"&gt;
            &lt;set-property property="contextConfigLocation"
            value="/WEB-INF/applicationContext.xml" /&gt;
            &lt;/plug-in&gt;</ccid_code></pre>
            </td>
        </tr>
    </tbody>
</table>
</ccid_nobr></center><br />
<br />
Spring在设计时就充分考虑到了与Struts的协同工作，通过内置的Struts Plug-in在两者之间提供了良好的结合点。但是，因为在这里我们一点也不改动JPetStore的控制层(这是JpetStore4.0的精华之一)，所以本文不准备采用此方式来加载ApplicationContext。我们利用的是spring framework 的BeanFactory机制,采用自定义的工具类（bean工厂类）来加载spring的配置文件，从中可以看出Spring有多灵活，它提供了各种不同的方式来使用其不同的部分/层次，您只需要用你想用的，不需要的部分可以不用。 <br />
<br />
具体的来说，就是在com.ibatis.spring包下创建CustomBeanFactory类，spring的配置文件applicationContext.xml也放在这个目录下。以下就是该类的全部代码，很简单： <br />
<br />
<center><ccid_nobr>
<table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
    <tbody>
        <tr>
            <td class="code" style="font-size: 9pt" bgcolor="#e6e6e6">
            <pre><ccid_code>public final class CustomBeanFactory {
            static XmlBeanFactory factory = null;
            static {
            Resource is = new
            InputStreamResource( CustomBeanFactory.class.getResourceAsStream("applicationContext.xml"));
            factory = new XmlBeanFactory(is);
            }
            public static Object getBean(String beanName){
            return factory.getBean(beanName);
            }
            }</ccid_code></pre>
            </td>
        </tr>
    </tbody>
</table>
</ccid_nobr></center><br />
<br />
实际上就是封装了Spring 的XMLBeanFactory而已，并且Spring的配置文件只需要加载一次，以后就可以直接用CustomBeanFactory.getBean("someBean")来获得需要的对象了(例如someBean)，而不需要知道具体的类。CustomBeanFactory类用于{耦合1}的解耦。CustomBeanFactory类在本文中只用于表现层的form bean对象获得service类的对象，因为我们没有把form bean对象配置在applicationContext.xml中。但是，为什么不把表现层的form bean类也配置起来呢，这样就用不着这CustomBeanFactory个类了，Spring会帮助我们创建需要的一切？问题的答案就在于form bean类是struts的ActionForm类！如果大家熟悉struts，就会知道ActionForm类是struts自动创建的：在一次请求中，struts判断，如果ActionForm实例不存在，就创建一个ActionForm对象，把客户提交的表单数据保存到ActionForm对象中。因此formbean类的对象就不能由spring来创建，但是service类以及数据层的DAO类可以，所以只有他们在spring中配置。所以，很自然的，我们就创建了CustomBeanFactory类，在表现层来衔接struts和spring。就这么简单，实现了另一种方式的{耦合一}的解耦。 <br />
<br />
3.3. 表现层 <br />
<br />
面分析到，struts和spring是在表现层衔接起来的，那么表现层就要做稍微的更改，即所需要的service类的对象创建上。以表现层的AccountBean类为例：原来的源代码如下 <br />
<br />
<center><ccid_nobr>
<table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
    <tbody>
        <tr>
            <td class="code" style="font-size: 9pt" bgcolor="#e6e6e6">
            <pre><ccid_code>private static final AccountService accountService
            = AccountService.getInstance();
            private static final CatalogService catalogService
            = CatalogService.getInstance();</ccid_code></pre>
            </td>
        </tr>
    </tbody>
</table>
</ccid_nobr></center><br />
<br />
改造后的源代码如下 <br />
<br />
<center><ccid_nobr>
<table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
    <tbody>
        <tr>
            <td class="code" style="font-size: 9pt" bgcolor="#e6e6e6">
            <pre><ccid_code>private static final AccountService accountService
            = (AccountService)CustomBeanFactory.getBean("AccountService");
            private static final CatalogService catalogService
            = (CatalogService)CustomBeanFactory.getBean("CatalogService");</ccid_code></pre>
            </td>
        </tr>
    </tbody>
</table>
</ccid_nobr></center><br />
<br />
其他的几个presentation类以同样方式改造。这样，表现层就完成了。关于表现层的其它部分如JSP等一概不动。也许您会说，没有看出什么特别之处的好处啊？你还是额外实现了一个工厂类。别着急，帷幕刚刚开启，spring是在表现层引入，但您发没发现： <br />
<br />
presentation类仅仅面向service类的接口编程，具体"AccountService"是哪个实现类，presentation类不知道，是在spring的配置文件里配置。（本例中，为了最大限度的保持原来的代码不作变化，没有抽象出接口）。Spring鼓励面向接口编程，因为是如此的方便和自然，当然您也可以不这么做。 <br />
<br />
CustomBeanFactory这个工厂类为什么会如此简单，因为其直接使用了Spring的BeanFactory。Spring从其核心而言，是一个DI容器，其设计哲学是提供一种无侵入式的高扩展性的框架。为了实现这个目标，Spring 大量引入了Java 的Reflection机制，通过动态调用的方式避免硬编码方式的约束，并在此基础上建立了其核心组件BeanFactory，以此作为其依赖注入机制的实现基础。org.springframework.beans包中包括了这些核心组件的实现类，核心中的核心为BeanWrapper和BeanFactory类。 <br />
<img src ="http://www.blogjava.net/libin2722/aggbug/165549.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2007-12-05 16:03 <a href="http://www.blogjava.net/libin2722/articles/165549.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基于struts+spring+ibatis的 J2EE 开发(4)</title><link>http://www.blogjava.net/libin2722/articles/165548.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 05 Dec 2007 08:02:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/articles/165548.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/165548.html</wfw:comment><comments>http://www.blogjava.net/libin2722/articles/165548.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/165548.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/165548.html</trackback:ping><description><![CDATA[3.4. 持久层在讨论业务层之前，我们先看一下持久层，如下图所示：<br />
<br />
<center><img src="http://www.dingl.com/images/qt/397095.jpg"  alt="" /></center><br />
<br />
在上文中，我们把iface包下的DAO接口归为业务层，在这里不需要做修改。ibatis的sql配置文件也不需要改。要改的是DAO实现类，并在spring的配置文件中配置起来。<br />
<br />
1、修改基类<br />
<br />
所有的DAO实现类都继承于BaseSqlMapDao类。修改BaseSqlMapDao类如下：<br />
<br />
<center><ccid_nobr>
<table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
    <tbody>
        <tr>
            <td class="code" style="font-size: 9pt" bgcolor="#e6e6e6">
            <pre><ccid_code>public class BaseSqlMapDao extends SqlMapClientDaoSupport
            {
            protected static final int PAGE_SIZE = 4;
            protected SqlMapClientTemplate smcTemplate
            = this.getSqlMapClientTemplate();
            public BaseSqlMapDao()
            {
            }
            }</ccid_code></pre>
            </td>
        </tr>
    </tbody>
</table>
</ccid_nobr></center><br />
<br />
使BaseSqlMapDao类改为继承于Spring提供的SqlMapClientDaoSupport类，并定义了一个保护属性smcTemplate，其类型为SqlMapClientTemplate。 <br />
<br />
2、修改DAO实现类 <br />
<br />
所有的DAO实现类还是继承于BaseSqlMapDao类，实现相应的DAO接口，但其相应的DAO操作委托SqlMapClientTemplate来执行，以AccountSqlMapDao类为例，部分代码如下： <br />
<br />
<center><ccid_nobr>
<table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
    <tbody>
        <tr>
            <td class="code" style="font-size: 9pt" bgcolor="#e6e6e6">
            <pre><ccid_code>public List getUsernameList()
            {
            return smcTemplate.queryForList("getUsernameList", null);
            }
            public Account getAccount(String username, String password)
            {
            Account account = new Account();
            account.setUsername(username);
            account.setPassword(password);
            return (Account)
            smcTemplate.queryForObject
            ("getAccountByUsernameAndPassword", account);
            }
            public void insertAccount(Account account)
            {
            smcTemplate.update("insertAccount", account);
            smcTemplate.update("insertProfile", account);
            smcTemplate.update("insertSignon", account);
            }</ccid_code></pre>
            </td>
        </tr>
    </tbody>
</table>
</ccid_nobr></center><br />
<br />
就这么简单，所有函数的签名都是一样的，只需要查找替换就可以了！ <br />
<img src ="http://www.blogjava.net/libin2722/aggbug/165548.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2007-12-05 16:02 <a href="http://www.blogjava.net/libin2722/articles/165548.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基于struts+spring+ibatis的 J2EE 开发(1)</title><link>http://www.blogjava.net/libin2722/articles/165547.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 05 Dec 2007 08:02:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/articles/165547.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/165547.html</wfw:comment><comments>http://www.blogjava.net/libin2722/articles/165547.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/165547.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/165547.html</trackback:ping><description><![CDATA[<div>1. 前言<br />
<br />
Struts 是目前Java Web MVC框架中不争的王者。经过长达五年的发展，Struts已经逐渐成长为一个稳定、成熟的框架，并且占有了MVC框架中最大的市场份额。但是Struts某些技术特性上已经落后于新兴的MVC框架。面对Spring MVC、Webwork2 这些设计更精密，扩展性更强的框架，Struts受到了前所未有的挑战。但站在产品开发的角度而言，Struts仍然是最稳妥的选择。本文的原型例子JpetStore 4.0就是基于Struts开发的，但是不拘泥于Struts的传统固定用法，例如只用了一个自定义Action类，并且在form bean类的定义上也是开创性的，令人耳目一新，稍后将具体剖析一下。<br />
<br />
Spring Framework 实际上是Expert One-on-One J2EE Design and Development 一书中所阐述的设计思想的具体实现。Spring Framework的功能非常多。包含AOP、ORM、DAO、Context、Web、MVC等几个部分组成。Web、MVC暂不用考虑，JpetStore 4.0用的是更成熟的Struts和JSP；DAO由于目前Hibernate、JDO、ibatis的流行，也不考虑，JpetStore 4.0用的就是ibatis。因此最需要用的是AOP、ORM、Context。Context中，最重要的是Beanfactory，它能将接口与实现分开，非常强大。目前AOP应用最成熟的还是在事务管理上。<br />
<br />
ibatis 是一个功能强大实用的SQL Map工具，不同于其他ORM工具（如hibernate），它是将SQL语句映射成Java对象，而对于ORM工具，它的SQL语句是根据映射定义生成的。ibatis 以SQL开发的工作量和数据库移植性上的让步，为系统设计提供了更大的自由空间。有ibatis代码生成的工具，可以根据DDL自动生成ibatis代码，能减少很多工作量。<br />
<br />
2. JpetStore简述<br />
<br />
2.1. 背景<br />
<br />
最初是Sun公司的J2EE petstore，其最主要目的是用于学习J2EE，但是其缺点也很明显，就是过度设计了。接着Oracle用J2EE petstore来比较各应用服务器的性能。微软推出了基于.Net平台的 Pet shop，用于竞争J2EE petstore。而JpetStore则是经过改良的基于struts的轻便框架J2EE web应用程序，相比来说，JpetStore设计和架构更优良，各层定义清晰，使用了很多最佳实践和模式，避免了很多"反模式"，如使用存储过程，在java代码中嵌入SQL语句，把HTML存储在数据库中等等。最新版本是JpetStore 4.0。<br />
<br />
2.2. JpetStore开发运行环境的建立<br />
<br />
1、开发环境<br />
<br />
Java SDK 1.4.2<br />
Apache Tomcat 4.1.31<br />
Eclipse-SDK-3.0.1-win32<br />
HSQLDB 1.7.2<br />
<br />
2、Eclipse插件<br />
<br />
EMF SDK 2.0.1：Eclipse建模框架，lomboz插件需要，可以使用runtime版本。<br />
lomboz 3.0：J2EE插件，用来在Eclipse中开发J2EE应用程序<br />
Spring IDE 1.0.3：Spring Bean配置管理插件<br />
xmlbuddy_2.0.10：编辑XML，用免费版功能即可<br />
tomcatPluginV3：tomcat管理插件<br />
Properties Editor：编辑java的属性文件,并可以预览以及自动存盘为Unicode格式。免去了手工或者ANT调用native2ascii的麻烦。<br />
2.3. 架构<br />
<br />
<center><a href="http://www.dingl.com/images/qt/397089.jpg"><img height="279" src="http://www.dingl.com/images/qt/397089.jpg" width="553" border="0"  alt="" /></a></center><br />
<br />
<center>图1 JpetStore架构图</center><br />
<br />
图1 是JPetStore架构图。参照这个架构图，让我们稍微剖析一下源代码，得出JpetStore 4.0的具体实现图（图2），思路一下子就豁然开朗了。前言中提到的非传统的struts开发模式，关键就在struts Action类和form bean类上。<br />
<br />
struts Action类只有一个：BeanAction。没错，确实是一个！与传统的struts编程方式很不同。再仔细研究BeanAction类，发现它其实是一个通用类，利用反射原理，根据URL来决定调用formbean的哪个方法。BeanAction大大简化了struts的编程模式，降低了对struts的依赖（与struts以及WEB容器有关的几个类都放在com.ibatis.struts包下，其它的类都可以直接复用）。利用这种模式，我们会很容易的把它移植到新的框架如JSF，spring。<br />
<br />
这样重心就转移到form bean上了，它已经不是普通意义上的form bean了。查看源代码，可以看到它不仅仅有数据和校验/重置方法，而且已经具有了行为，从这个意义上来说，它更像一个BO(Business Object)。这就是前文讲到的，BeanAction类利用反射原理，根据URL来决定调用form bean的哪个方法（行为）。form bean的这些方法的签名很简单，例如：<br />
<br />
<center><ccid_nobr>
<table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
    <tbody>
        <tr>
            <td class="code" style="font-size: 9pt" bgcolor="#e6e6e6">
            <pre><ccid_code>public String myActionMethod()
            {
            //..work
            return "success";
            }</ccid_code></pre>
            </td>
        </tr>
    </tbody>
</table>
</ccid_nobr></center><br />
<br />
方法的返回值直接就是字符串，对应的是forward的名称，而不再是ActionForward对象，创建ActionForward对象的任务已经由BeanAction类代劳了。另外，程序还提供了ActionContext工具类，该工具类封装了request 、response、form parameters、request attributes、session attributes和 application attributes中的数据存取操作，简单而线程安全，form bean类使用该工具类可以进一步从表现层框架解耦。在这里需要特别指出的是，BeanAction类是对struts扩展的一个有益尝试，虽然提供了非常好的应用开发模式，但是它还非常新，一直在发展中。 <br />
<br />
<center><img src="http://www.dingl.com/images/qt/397091.gif"  alt="" /></center><br />
<br />
<center>图2 JpetStore 4.0具体实现</center></div>
<img src ="http://www.blogjava.net/libin2722/aggbug/165547.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2007-12-05 16:02 <a href="http://www.blogjava.net/libin2722/articles/165547.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基于struts+spring+ibatis的 J2EE 开发(5)</title><link>http://www.blogjava.net/libin2722/articles/165533.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 05 Dec 2007 07:41:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/articles/165533.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/165533.html</wfw:comment><comments>http://www.blogjava.net/libin2722/articles/165533.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/165533.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/165533.html</trackback:ping><description><![CDATA[<table cellspacing="0" cellpadding="0" width="96%" align="center" border="0">
    <tbody>
        <tr>
            <td class="big" valign="top" width="540">
            <p>&nbsp;</p>
            <p><a href="javascript:location.href='http://www.onedoor.cn/favorite/post?&amp;url='+encodeURIComponent(location.href)+'&amp;title='+encodeURIComponent(document.title)"><font style="font-weight: bold; font-size: 14px" color="red">将此文章收藏到豌豆网</font></a></p>
            <p>
            <div>3、除去工厂类以及相应的配置文件<br />
            <br />
            除去DaoConfig.java这个DAO工厂类和相应的配置文件dao.xml，因为DAO的获取现在要用spring来管理。<br />
            <br />
            4、DAO在Spring中的配置（applicationContext.xml）<br />
            <br />
            <center><ccid_nobr>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" style="font-size: 9pt" bgcolor="#e6e6e6">
                        <pre><ccid_code>&lt;bean id="dataSource"
                        class="org.springframework.jdbc.datasource.DriverManagerDataSource"&gt;
                        &lt;property name="driverClassName"&gt;
                        &lt;value&gt;org.hsqldb.jdbcDriver&lt;/value&gt;
                        &lt;/property&gt;
                        &lt;property name="url"&gt;
                        &lt;value&gt;jdbc:hsqldb:hsql://localhost/xdb&lt;/value&gt;
                        &lt;/property&gt;
                        &lt;property name="username"&gt;
                        &lt;value&gt;sa&lt;/value&gt;
                        &lt;/property&gt;
                        &lt;property name="password"&gt;
                        &lt;value&gt;&lt;/value&gt;
                        &lt;/property&gt;
                        &lt;/bean&gt;
                        &lt;!-- ibatis sqlMapClient config --&gt;
                        &lt;bean id="sqlMapClient"
                        class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"&gt;
                        &lt;property name="configLocation"&gt;
                        &lt;value&gt;
                        classpath:com\ibatis\jpetstore\persistence\sqlmapdao\sql\sql-map-config.xml
                        &lt;/value&gt;
                        &lt;/property&gt;
                        &lt;property name="dataSource"&gt;
                        &lt;ref bean="dataSource"/&gt;
                        &lt;/property&gt;
                        &lt;/bean&gt;
                        &lt;!-- Transactions --&gt;
                        &lt;bean id="TransactionManager"
                        class="org.springframework.jdbc.datasource.DataSourceTransactionManager"&gt;
                        &lt;property name="dataSource"&gt;
                        &lt;ref bean="dataSource"/&gt;
                        &lt;/property&gt;
                        &lt;/bean&gt;
                        &lt;!-- persistence layer --&gt;
                        &lt;bean id="AccountDao"
                        class="com.ibatis.jpetstore.persistence.sqlmapdao.AccountSqlMapDao"&gt;
                        &lt;property name="sqlMapClient"&gt;
                        &lt;ref local="sqlMapClient"/&gt;
                        &lt;/property&gt;
                        &lt;/bean&gt;</ccid_code></pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </ccid_nobr></center><br />
            <br />
            1. 我们首先创建一个数据源dataSource，在这里配置的是hsqldb数据库。如果是ORACLE数据库，driverClassName的值是"oracle.jdbc.driver.OracleDriver"，URL的值类似于"jdbc:oracle:thin:@wugfMobile:1521:cdcf"。数据源现在由spring来管理，那么现在我们就可以去掉properties目录下database.properties这个配置文件了；还有不要忘记修改sql-map-config.xml，去掉
            <properties resource="properties/database.properties"  />对它的引用。 <br />
            <br />
            2. sqlMapClient节点。这个是针对ibatis SqlMap的SqlMapClientFactoryBean配置。实际上配置了一个sqlMapClient的创建工厂类。configLocation属性配置了ibatis映射文件的名称。dataSource属性指向了使用的数据源，这样所有使用sqlMapClient的DAO都默认使用了该数据源，除非在DAO的配置中另外显式指定。 <br />
            <br />
            3. TransactionManager节点。定义了事务，使用的是DataSourceTransactionManager。 <br />
            <br />
            4. 下面就可以定义DAO节点了，如AccountDao，它的实现类是com.ibatis.jpetstore.persistence.sqlmapdao.AccountSqlMapDao，使用的SQL配置从sqlMapClient中读取，数据库连接没有特别列出，那么就是默认使用sqlMapClient配置的数据源datasource。 <br />
            <br />
            这样，我们就把持久层改造完了，其他的DAO配置类似于AccountDao。怎么样？简单吧。这次有接口了：） AccountDao接口－&gt;AccountSqlMapDao实现。 <br />
            <br />
            3.5. 业务层 <br />
            <br />
            业务层的位置以及相关类，如下图所示：在这个例子中只有3个业务类，我们以OrderService类为例来改造，这个类是最复杂的，其中涉及了事务。 <br />
            <br />
            1、在ApplicationContext配置文件中增加bean的配置： <br />
            <br />
            <center><ccid_nobr>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" style="font-size: 9pt" bgcolor="#e6e6e6">
                        <pre><ccid_code>&lt;bean id="OrderService"
                        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"&gt;
                        &lt;property name="transactionManager"&gt;
                        &lt;ref local="TransactionManager"&gt;&lt;/ref&gt;
                        &lt;/property&gt;
                        &lt;property name="target"&gt;
                        &lt;bean class="com.ibatis.jpetstore.service.OrderService"&gt;
                        &lt;property name="itemDao"&gt;
                        &lt;ref bean="ItemDao"/&gt;
                        &lt;/property&gt;
                        &lt;property name="orderDao"&gt;
                        &lt;ref bean="OrderDao"/&gt;
                        &lt;/property&gt;
                        &lt;property name="sequenceDao"&gt;
                        &lt;ref bean="SequenceDao"/&gt;
                        &lt;/property&gt;
                        &lt;/bean&gt;
                        &lt;/property&gt;
                        &lt;property name="transactionAttributes"&gt;
                        &lt;props&gt;
                        &lt;prop key="insert*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt;
                        &lt;/props&gt;
                        &lt;/property&gt;
                        &lt;/bean&gt;</ccid_code></pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </ccid_nobr></center><br />
            <br />
            定义了一个OrderService，还是很容易懂的。为了简单起见，使用了嵌套bean，其实现类是com.ibatis.jpetstore.service.OrderService，分别引用了ItemDao，OrderDao，SequenceDao。该bean的insert*实现了事务管理(AOP方式)。TransactionProxyFactoryBean自动创建一个事务advisor， 该advisor包括一个基于事务属性的pointcut,因此只有事务性的方法被拦截。 <br />
            <br />
            2、业务类的修改，以OrderService为例： <br />
            <br />
            <center><ccid_nobr>
            <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
                <tbody>
                    <tr>
                        <td class="code" style="font-size: 9pt" bgcolor="#e6e6e6">
                        <pre><ccid_code>public class OrderService {
                        /* Private Fields */
                        private ItemDao itemDao;
                        private OrderDao orderDao;
                        private SequenceDao sequenceDao;
                        /* Constructors */
                        public OrderService() {
                        }
                        /**
                        * @param itemDao 要设置的 itemDao。
                        */
                        public final void setItemDao(ItemDao itemDao) {
                        this.itemDao = itemDao;
                        }
                        /**
                        * @param orderDao 要设置的 orderDao。
                        */
                        public final void setOrderDao(OrderDao orderDao) {
                        this.orderDao = orderDao;
                        }
                        /**
                        * @param sequenceDao 要设置的 sequenceDao。
                        */
                        public final void setSequenceDao(SequenceDao sequenceDao) {
                        this.sequenceDao = sequenceDao;
                        }
                        //剩下的部分
                        &#8230;&#8230;.
                        }</ccid_code></pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            </ccid_nobr></center><br />
            <br />
            红色部分为修改部分。Spring采用的是Type2的设置依赖注入，所以我们只需要定义属性和相应的设值函数就可以了，ItemDao，OrderDao，SequenceDao的值由spring在运行期间注入。构造函数就可以为空了，另外也不需要自己编写代码处理事务了（事务在配置中声明），daoManager.startTransaction();等与事务相关的语句也可以去掉了。和原来的代码比较一下，是不是处理精简了很多！可以更关注业务的实现。 <br />
            <br />
            4. 结束语 <br />
            <br />
            ibatis是一个功能强大实用的SQL Map工具，可以直接控制SQL,为系统设计提供了更大的自由空间。其提供的最新示例程序JpetStore 4.0,设计优雅，应用了迄今为止很多最佳实践和设计模式，非常适于学习以及在此基础上创建轻量级的J2EE WEB应用程序。JpetStore 4.0是基于struts的，本文在此基础上，最大程度保持了原有设计的精华以及最小的代码改动量，在业务层和持久化层引入了Spring。在您阅读了本文以及改造后的源代码后，会深切的感受到Spring带来的种种好处：自然的面向接口的编程，业务对象的依赖注入，一致的数据存取框架和声明式的事务处理，统一的配置文件&#8230;更重要的是Spring既是全面的又是模块化的，Spring有分层的体系结构，这意味着您能选择仅仅使用它任何一个独立的部分，就像本文，而它的架构又是内部一致。 <br />
            </div>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.blogjava.net/libin2722/aggbug/165533.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2007-12-05 15:41 <a href="http://www.blogjava.net/libin2722/articles/165533.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基于struts+spring+ibatis的轻量级J2EE开发</title><link>http://www.blogjava.net/libin2722/articles/165532.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 05 Dec 2007 07:40:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/articles/165532.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/165532.html</wfw:comment><comments>http://www.blogjava.net/libin2722/articles/165532.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/165532.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/165532.html</trackback:ping><description><![CDATA[<blockquote>大多数IT 组织都必须解决三个主要问题：1．帮助组织减少成本 2．增加并且保持客户 3．加快业务效率。完成这些问题一般都需要实现对多个业务系统的数据和业务逻辑的无缝访问，也就是说，要实施系统集成工程，以便联结业务流程、实现数据的访问与共享。</blockquote><!--start RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--end RESERVED FOR FUTURE USE INCLUDE FILES-->
<p>JpetStore 4.0是ibatis的最新示例程序，基于Struts MVC框架（注：非传统Struts开发模式），以ibatis作为持久化层。该示例程序设计优雅，层次清晰，可以学习以及作为一个高效率的编程模型参考。本文是在其基础上，采用Spring对其中间层（业务层）进行改造。使开发量进一步减少，同时又拥有了Spring的一些好处&#8230;</p>
<p><a name="N10042"><span class="atitle">1. 前言</span></a></p>
<p>JpetStore 4.0是ibatis的最新示例程序。ibatis是开源的持久层产品，包含SQL Maps 2.0 和 Data Access Objects 2.0 框架。JpetStore示例程序很好的展示了如何利用ibatis来开发一个典型的J2EE web应用程序。JpetStore有如下特点：</p>
<ul>
    <li>ibatis数据层
    <li>POJO业务层
    <li>POJO领域类
    <li>Struts MVC
    <li>JSP 表示层 </li>
</ul>
<p>以下是本文用到的关键技术介绍，本文假设您已经对Struts，SpringFramewok，ibatis有一定的了解，如果不是，请首先查阅附录中的参考资料。</p>
<ul>
    <li>Struts 是目前Java Web MVC框架中不争的王者。经过长达五年的发展，Struts已经逐渐成长为一个稳定、成熟的框架，并且占有了MVC框架中最大的市场份额。但是Struts某些技术特性上已经落后于新兴的MVC框架。面对Spring MVC、Webwork2 这些设计更精密，扩展性更强的框架，Struts受到了前所未有的挑战。但站在产品开发的角度而言，Struts仍然是最稳妥的选择。本文的原型例子JpetStore 4.0就是基于Struts开发的，但是不拘泥于Struts的传统固定用法，例如只用了一个自定义Action类，并且在form bean类的定义上也是开创性的，令人耳目一新，稍后将具体剖析一下。
    <li>Spring Framework 实际上是Expert One-on-One J2EE Design and Development 一书中所阐述的设计思想的具体实现。Spring Framework的功能非常多。包含AOP、ORM、DAO、Context、Web、MVC等几个部分组成。Web、MVC暂不用考虑，JpetStore 4.0用的是更成熟的Struts和JSP；DAO由于目前Hibernate、JDO、ibatis的流行，也不考虑，JpetStore 4.0用的就是ibatis。因此最需要用的是AOP、ORM、Context。Context中，最重要的是Beanfactory，它能将接口与实现分开，非常强大。目前AOP应用最成熟的还是在事务管理上。
    <li>ibatis 是一个功能强大实用的SQL Map工具，不同于其他ORM工具（如hibernate），它是将SQL语句映射成Java对象，而对于ORM工具，它的SQL语句是根据映射定义生成的。ibatis 以SQL开发的工作量和数据库移植性上的让步，为系统设计提供了更大的自由空间。有ibatis代码生成的工具，可以根据DDL自动生成ibatis代码，能减少很多工作量。 </li>
</ul>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
            <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" cellpadding="0" align="right">
    <tbody>
        <tr align="right">
            <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
            <table cellspacing="0" cellpadding="0" border="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                        </td>
                        <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/java/j-s-s-i/?ca=j-t10#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="N1006C"><span class="atitle">2. JpetStore简述</span></a></p>
<p><a name="N10072"><span class="smalltitle">2.1. 背景</span></a></p>
<p>最初是Sun公司的J2EE petstore，其最主要目的是用于学习J2EE，但是其缺点也很明显，就是过度设计了。接着Oracle用J2EE petstore来比较各应用服务器的性能。微软推出了基于.Net平台的 Pet shop，用于竞争J2EE petstore。而JpetStore则是经过改良的基于struts的轻便框架J2EE web应用程序，相比来说，JpetStore设计和架构更优良，各层定义清晰，使用了很多最佳实践和模式，避免了很多"反模式"，如使用存储过程，在java代码中嵌入SQL语句，把HTML存储在数据库中等等。最新版本是JpetStore 4.0。</p>
<p><a name="N1007B"><span class="smalltitle">2.2. JpetStore开发运行环境的建立</span></a></p>
<p>1、开发环境</p>
<ul>
    <li>Java SDK 1.4.2
    <li>Apache Tomcat 4.1.31
    <li>Eclipse-SDK-3.0.1-win32
    <li>HSQLDB 1.7.2 </li>
</ul>
<p>2、Eclipse插件</p>
<ul>
    <li>EMF SDK 2.0.1：Eclipse建模框架，lomboz插件需要，可以使用runtime版本。
    <li>lomboz 3.0：J2EE插件，用来在Eclipse中开发J2EE应用程序
    <li>Spring IDE 1.0.3：Spring Bean配置管理插件
    <li>xmlbuddy_2.0.10：编辑XML，用免费版功能即可
    <li>tomcatPluginV3：tomcat管理插件
    <li>Properties Editor：编辑java的属性文件,并可以预览以及自动存盘为Unicode格式。免去了手工或者ANT调用native2ascii的麻烦。 </li>
</ul>
<p>3、示例源程序</p>
<ul>
    <li>ibatis示例程序JpetStore 4.0 http://www.ibatis.com/jpetstore/jpetstore.html
    <li>改造后的源程序（+spring）（源码链接） </li>
</ul>
<p><a name="N100B7"><span class="smalltitle">2.3. 架构</span></a></p>
<br />
<a name="N100BF"><strong>图1 JpetStore架构图</strong></a><br />
<img height="279" alt="图1 JpetStore架构图" src="http://www.ibm.com/developerworks/cn/java/j-s-s-i/images/image002.jpg" width="553" border="0" /> <br />
<p>图1 是JPetStore架构图，更详细的内容请参见JPetStore的白皮书。参照这个架构图，让我们稍微剖析一下源代码，得出JpetStore 4.0的具体实现图（见图2），思路一下子就豁然开朗了。前言中提到的非传统的struts开发模式，关键就在struts Action类和form bean类上。</p>
<p>struts Action类只有一个：BeanAction。没错，确实是一个！与传统的struts编程方式很不同。再仔细研究BeanAction类，发现它其实是一个通用类，利用反射原理，根据URL来决定调用formbean的哪个方法。BeanAction大大简化了struts的编程模式，降低了对struts的依赖（与struts以及WEB容器有关的几个类都放在com.ibatis.struts包下，其它的类都可以直接复用）。利用这种模式，我们会很容易的把它移植到新的框架如JSF，spring。</p>
<p>这样重心就转移到form bean上了，它已经不是普通意义上的form bean了。查看源代码，可以看到它不仅仅有数据和校验/重置方法，而且已经具有了行为，从这个意义上来说，它更像一个BO(Business Object)。这就是前文讲到的，BeanAction类利用反射原理，根据URL来决定调用form bean的哪个方法（行为）。form bean的这些方法的签名很简单，例如：</p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode"> public String myActionMethod() {
            //..work
            return "success";
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>方法的返回值直接就是字符串，对应的是forward的名称，而不再是ActionForward对象，创建ActionForward对象的任务已经由BeanAction类代劳了。</p>
<p>另外，程序还提供了ActionContext工具类，该工具类封装了request 、response、form parameters、request attributes、session attributes和 application attributes中的数据存取操作，简单而线程安全，form bean类使用该工具类可以进一步从表现层框架解耦。</p>
<p>在这里需要特别指出的是，BeanAction类是对struts扩展的一个有益尝试，虽然提供了非常好的应用开发模式，但是它还非常新，一直在发展中。</p>
<br />
<a name="N100EC"><strong>图2 JpetStore 4.0具体实现</strong></a><br />
<img height="588" alt="图2 JpetStore 4.0具体实现" src="http://www.ibm.com/developerworks/cn/java/j-s-s-i/images/image004.gif" width="582" border="0" /> <br />
<p><a name="N100FC"><span class="smalltitle">2.4. 代码剖析</span></a></p>
<p>下面就让我们开始进一步分析JpetStore4.0的源代码，为下面的改造铺路。</p>
<ul>
    <li>BeanAction.java是唯一一个Struts action类，位于com.ibatis.struts包下。正如上文所言，它是一个通用的控制类，利用反射机制，把控制转移到form bean的某个方法来处理。详细处理过程参考其源代码，简单明晰。
    <li>
    <p>Form bean类位于com.ibatis.jpetstore.presentation包下，命名规则为***Bean。Form bean类全部继承于BaseBean类，而BaseBean类实际继承于ActionForm，因此，Form bean类就是Struts的 ActionForm，Form bean类的属性数据就由struts框架自动填充。而实际上，JpetStore4.0扩展了struts中ActionForm的应用： Form bean类还具有行为，更像一个BO,其行为（方法）由BeanAction根据配置（struts-config.xml）的URL来调用。虽然如此，我们还是把Form bean类定位于表现层。</p>
    <p>Struts-config.xml的配置里有3种映射方式，来告诉BeanAction把控制转到哪个form bean对象的哪个方法来处理。</p>
    <p>以这个请求连接为例http://localhost/jpetstore4/shop/viewOrder.do</p>
    <p>1. URL Pattern</p>
    <table cellspacing="0" cellpadding="0" width="100%" border="0">
        <tbody>
            <tr>
                <td class="code-outline">
                <pre class="displaycode">    &lt;action path="/shop/viewOrder" type="com.ibatis.struts.BeanAction"
                name="orderBean" scope="session"
                validate="false"&gt;
                &lt;forward name="success" path="/order/ViewOrder.jsp"/&gt;
                &lt;/action&gt;
                </pre>
                </td>
            </tr>
        </tbody>
    </table>
    <br />
    <p>此种方式表示，控制将被转发到"orderBean"这个form bean对象 的"viewOrder"方法（行为）来处理。方法名取"path"参数的以"/"分隔的最后一部分。</p>
    <p>2. Method Parameter</p>
    <table cellspacing="0" cellpadding="0" width="100%" border="0">
        <tbody>
            <tr>
                <td class="code-outline">
                <pre class="displaycode">    &lt;action path="/shop/viewOrder" type="com.ibatis.struts.BeanAction"
                name="orderBean" parameter="viewOrder" scope="session"
                validate="false"&gt;
                &lt;forward name="success" path="/order/ViewOrder.jsp"/&gt;
                &lt;/action&gt;
                </pre>
                </td>
            </tr>
        </tbody>
    </table>
    <br />
    <p>此种方式表示，控制将被转发到"orderBean"这个form bean对象的"viewOrder"方法（行为）来处理。配置中的"parameter"参数表示form bean类上的方法。"parameter"参数优先于"path"参数。</p>
    <p>3. No Method call</p>
    <table cellspacing="0" cellpadding="0" width="100%" border="0">
        <tbody>
            <tr>
                <td class="code-outline">
                <pre class="displaycode">    &lt;action path="/shop/viewOrder" type="com.ibatis.struts.BeanAction"
                name="orderBean" parameter="*" scope="session"
                validate="false"&gt;
                &lt;forward name="success" path="/order/ViewOrder.jsp"/&gt;
                &lt;/action&gt;
                </pre>
                </td>
            </tr>
        </tbody>
    </table>
    <br />
    <p>此种方式表示，form bean上没有任何方法被调用。如果存在"name"属性，则struts把表单参数等数据填充到form bean对象后，把控制转发到"success"。否则，如果name为空，则直接转发控制到"success"。</p>
    <p>这就相当于struts内置的org.apache.struts.actions.ForwardAction的功能</p>
    <table cellspacing="0" cellpadding="0" width="100%" border="0">
        <tbody>
            <tr>
                <td class="code-outline">
                <pre class="displaycode"> &lt;action path="/shop/viewOrder" type="org.apache.struts.actions.ForwardAction"
                parameter="/order/ViewOrder.jsp " scope="session" validate="false"&gt;
                &lt;/action&gt;
                </pre>
                </td>
            </tr>
        </tbody>
    </table>
    <br />
    <li>Service类位于com.ibatis.jpetstore.service包下，属于业务层。这些类封装了业务以及相应的事务控制。Service类由form bean类来调用。
    <li>com.ibatis.jpetstore.persistence.iface包下的类是DAO接口，属于业务层，其屏蔽了底层的数据库操作，供具体的Service类来调用。DaoConfig类是工具类（DAO工厂类），Service类通过DaoConfig类来获得相应的DAO接口，而不用关心底层的具体数据库操作，实现了如图2中{耦合2}的解耦。
    <li>com.ibatis.jpetstore.persistence.sqlmapdao包下的类是对应DAO接口的具体实现，在JpetStore4.0中采用了ibatis来实现ORM。这些实现类继承BaseSqlMapDao类，而BaseSqlMapDao类则继承ibatis DAO 框架中的SqlMapDaoTemplate类。ibatis的配置文件存放在com.ibatis.jpetstore.persistence.sqlmapdao.sql目录下。这些类和配置文件位于数据层
    <li>Domain类位于com.ibatis.jpetstore.domain包下，是普通的javabean。在这里用作数据传输对象（DTO），贯穿视图层、业务层和数据层，用于在不同层之间传输数据。</li>
</ul>
<p>剩下的部分就比较简单了，请看具体的源代码，非常清晰。</p>
<p><a name="N10149"><span class="smalltitle">2.5. 需要改造的地方</span></a></p>
<p>JpetStore4.0的关键就在struts Action类和form bean类上，这也是其精华之一（虽然该实现方式是试验性，待扩充和验证），在此次改造中我们要保留下来，即控制层一点不变，表现层获取相应业务类的方式变了（要加载spring环境），其它保持不变。要特别关注的改动是业务层和持久层，幸运的是JpetStore4.0设计非常好，需要改动的地方非常少，而且由模式可循，如下：</p>
<p>1. 业务层和数据层用Spring BeanFactory机制管理。</p>
<p>2. 业务层的事务由spring 的aop通过声明来完成。</p>
<p>3. 表现层（form bean）获取业务类的方法改由自定义工厂类来实现（加载spring环境）。</p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
            <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" cellpadding="0" align="right">
    <tbody>
        <tr align="right">
            <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
            <table cellspacing="0" cellpadding="0" border="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                        </td>
                        <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/java/j-s-s-i/?ca=j-t10#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="N1015B"><span class="atitle">3. JPetStore的改造</span></a></p>
<p><a name="N10161"><span class="smalltitle">3.1. 改造后的架构</span></a></p>
<br />
<img height="640" alt="" src="http://www.ibm.com/developerworks/cn/java/j-s-s-i/images/image005.gif" width="582" border="0" /> <br />
<p>其中红色部分是要增加的部分，蓝色部分是要修改的部分。下面就让我们逐一剖析。</p>
<p><a name="N1017B"><span class="smalltitle">3.2. Spring Context的加载</span></a></p>
<p>为了在Struts中加载Spring Context，一般会在struts-config.xml的最后添加如下部分：</p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">&lt;plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"&gt;
            &lt;set-property property="contextConfigLocation"
            value="/WEB-INF/applicationContext.xml" /&gt;
            &lt;/plug-in&gt;
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>Spring在设计时就充分考虑到了与Struts的协同工作，通过内置的Struts Plug-in在两者之间提供了良好的结合点。但是，因为在这里我们一点也不改动JPetStore的控制层(这是JpetStore4.0的精华之一)，所以本文不准备采用此方式来加载ApplicationContext。我们利用的是spring framework 的BeanFactory机制,采用自定义的工具类（bean工厂类）来加载spring的配置文件，从中可以看出Spring有多灵活，它提供了各种不同的方式来使用其不同的部分/层次，您只需要用你想用的，不需要的部分可以不用。</p>
<p>具体的来说，就是在com.ibatis.spring包下创建CustomBeanFactory类，spring的配置文件applicationContext.xml也放在这个目录下。以下就是该类的全部代码，很简单：</p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public final class CustomBeanFactory {
            static XmlBeanFactory factory = null;
            static {
            Resource is = new
            InputStreamResource( CustomBeanFactory.class.getResourceAsStream("applicationContext.xml"));
            factory = new XmlBeanFactory(is);
            }
            public static Object getBean(String beanName){
            return factory.getBean(beanName);
            }
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>实际上就是封装了Spring 的XMLBeanFactory而已，并且Spring的配置文件只需要加载一次，以后就可以直接用CustomBeanFactory.getBean("someBean")来获得需要的对象了(例如someBean)，而不需要知道具体的类。CustomBeanFactory类用于{耦合1}的解耦。</p>
<p>CustomBeanFactory类在本文中只用于表现层的form bean对象获得service类的对象，因为我们没有把form bean对象配置在applicationContext.xml中。但是，为什么不把表现层的form bean类也配置起来呢，这样就用不着这CustomBeanFactory个类了，Spring会帮助我们创建需要的一切？问题的答案就在于form bean类是struts的ActionForm类！如果大家熟悉struts，就会知道ActionForm类是struts自动创建的：在一次请求中，struts判断，如果ActionForm实例不存在，就创建一个ActionForm对象，把客户提交的表单数据保存到ActionForm对象中。因此formbean类的对象就不能由spring来创建，但是service类以及数据层的DAO类可以，所以只有他们在spring中配置。</p>
<p>所以，很自然的，我们就创建了CustomBeanFactory类，在表现层来衔接struts和spring。就这么简单，实现了另一种方式的{耦合一}的解耦。</p>
<p><a name="N101A5"><span class="smalltitle">3.3. 表现层</span></a></p>
上
<p>面分析到，struts和spring是在表现层衔接起来的，那么表现层就要做稍微的更改，即所需要的service类的对象创建上。以表现层的AccountBean类为例：</p>
<p>原来的源代码如下</p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">    private static final AccountService accountService = AccountService.getInstance();
            private static final CatalogService catalogService = CatalogService.getInstance();
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>改造后的源代码如下</p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">  private static final AccountService accountService = (AccountService)CustomBeanFactory.getBean("AccountService");
            private static final CatalogService catalogService = (CatalogService)CustomBeanFactory.getBean("CatalogService");
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>其他的几个presentation类以同样方式改造。这样，表现层就完成了。关于表现层的其它部分如JSP等一概不动。也许您会说，没有看出什么特别之处的好处啊？你还是额外实现了一个工厂类。别着急，帷幕刚刚开启，spring是在表现层引入，但您发没发现：</p>
<ul>
    <li>presentation类仅仅面向service类的接口编程，具体"AccountService"是哪个实现类，presentation类不知道，是在spring的配置文件里配置。（本例中，为了最大限度的保持原来的代码不作变化，没有抽象出接口）。Spring鼓励面向接口编程，因为是如此的方便和自然，当然您也可以不这么做。
    <li>CustomBeanFactory这个工厂类为什么会如此简单，因为其直接使用了Spring的BeanFactory。Spring从其核心而言，是一个DI容器，其设计哲学是提供一种无侵入式的高扩展性的框架。为了实现这个目标，Spring 大量引入了Java 的Reflection机制，通过动态调用的方式避免硬编码方式的约束，并在此基础上建立了其核心组件BeanFactory，以此作为其依赖注入机制的实现基础。org.springframework.beans包中包括了这些核心组件的实现类，核心中的核心为BeanWrapper和BeanFactory类。 </li>
</ul>
<p><a name="N101D2"><span class="smalltitle">3.4. 持久层</span></a></p>
<p>在讨论业务层之前，我们先看一下持久层，如下图所示：</p>
<br />
<img height="416" alt="" src="http://www.ibm.com/developerworks/cn/java/j-s-s-i/images/image007.jpg" width="320" border="0" /> <br />
<p>在上文中，我们把iface包下的DAO接口归为业务层，在这里不需要做修改。ibatis的sql配置文件也不需要改。要改的是DAO实现类，并在spring的配置文件中配置起来。</p>
<p>1、修改基类</p>
<p>所有的DAO实现类都继承于BaseSqlMapDao类。修改BaseSqlMapDao类如下：</p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public class BaseSqlMapDao extends SqlMapClientDaoSupport {
            protected static final int PAGE_SIZE = 4;
            protected SqlMapClientTemplate smcTemplate = this.getSqlMapClientTemplate();
            public BaseSqlMapDao() {
            }
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>使BaseSqlMapDao类改为继承于Spring提供的SqlMapClientDaoSupport类，并定义了一个保护属性smcTemplate，其类型为SqlMapClientTemplate。关于SqlMapClientTemplate类的详细说明请参照附录中的"Spring中文参考手册"</p>
<p>2、修改DAO实现类</p>
<p>所有的DAO实现类还是继承于BaseSqlMapDao类，实现相应的DAO接口，但其相应的DAO操作委托SqlMapClientTemplate来执行，以AccountSqlMapDao类为例，部分代码如下：</p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">    public List getUsernameList() {
            return smcTemplate.queryForList("getUsernameList", null);
            }
            public Account getAccount(String username, String password) {
            Account account = new Account();
            account.setUsername(username);
            account.setPassword(password);
            return (Account) smcTemplate.queryForObject("getAccountByUsernameAndPassword", account);
            }
            public void insertAccount(Account account) {
            smcTemplate.update("insertAccount", account);
            smcTemplate.update("insertProfile", account);
            smcTemplate.update("insertSignon", account);
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>就这么简单，所有函数的签名都是一样的，只需要查找替换就可以了！</p>
<p>3、除去工厂类以及相应的配置文件</p>
<p>除去DaoConfig.java这个DAO工厂类和相应的配置文件dao.xml，因为DAO的获取现在要用spring来管理。</p>
<p>4、DAO在Spring中的配置（applicationContext.xml）</p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">    &lt;bean id="dataSource"
            class="org.springframework.jdbc.datasource.DriverManagerDataSource"&gt;
            &lt;property name="driverClassName"&gt;
            &lt;value&gt;org.hsqldb.jdbcDriver&lt;/value&gt;
            &lt;/property&gt;
            &lt;property name="url"&gt;
            &lt;value&gt;jdbc:hsqldb:hsql://localhost/xdb&lt;/value&gt;
            &lt;/property&gt;
            &lt;property name="username"&gt;
            &lt;value&gt;sa&lt;/value&gt;
            &lt;/property&gt;
            &lt;property name="password"&gt;
            &lt;value&gt;&lt;/value&gt;
            &lt;/property&gt;
            &lt;/bean&gt;
            &lt;!-- ibatis sqlMapClient config --&gt;
            &lt;bean id="sqlMapClient"
            class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"&gt;
            &lt;property name="configLocation"&gt;
            &lt;value&gt;
            classpath:com\ibatis\jpetstore\persistence\sqlmapdao\sql\sql-map-config.xml
            &lt;/value&gt;
            &lt;/property&gt;
            &lt;property name="dataSource"&gt;
            &lt;ref bean="dataSource"/&gt;
            &lt;/property&gt;
            &lt;/bean&gt;
            &lt;!-- Transactions --&gt;
            &lt;bean id="TransactionManager"
            class="org.springframework.jdbc.datasource.DataSourceTransactionManager"&gt;
            &lt;property name="dataSource"&gt;
            &lt;ref bean="dataSource"/&gt;
            &lt;/property&gt;
            &lt;/bean&gt;
            &lt;!-- persistence layer --&gt;
            &lt;bean id="AccountDao"
            class="com.ibatis.jpetstore.persistence.sqlmapdao.AccountSqlMapDao"&gt;
            &lt;property name="sqlMapClient"&gt;
            &lt;ref local="sqlMapClient"/&gt;
            &lt;/property&gt;
            &lt;/bean&gt;
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>具体的语法请参照附录中的"Spring中文参考手册"。在这里只简单解释一下：</p>
<p>1. 我们首先创建一个数据源dataSource，在这里配置的是hsqldb数据库。如果是ORACLE数据库，driverClassName的值是"oracle.jdbc.driver.OracleDriver"，URL的值类似于"jdbc:oracle:thin:@wugfMobile:1521:cdcf"。数据源现在由spring来管理，那么现在我们就可以去掉properties目录下database.properties这个配置文件了；还有不要忘记修改sql-map-config.xml，去掉&lt;properties resource="properties/database.properties"/&gt;对它的引用。</p>
<p>2. sqlMapClient节点。这个是针对ibatis SqlMap的SqlMapClientFactoryBean配置。实际上配置了一个sqlMapClient的创建工厂类。configLocation属性配置了ibatis映射文件的名称。dataSource属性指向了使用的数据源，这样所有使用sqlMapClient的DAO都默认使用了该数据源，除非在DAO的配置中另外显式指定。</p>
<p>3. TransactionManager节点。定义了事务，使用的是DataSourceTransactionManager。</p>
<p>4. 下面就可以定义DAO节点了，如AccountDao，它的实现类是com.ibatis.jpetstore.persistence.sqlmapdao.AccountSqlMapDao，使用的SQL配置从sqlMapClient中读取，数据库连接没有特别列出，那么就是默认使用sqlMapClient配置的数据源datasource。</p>
<p>这样，我们就把持久层改造完了，其他的DAO配置类似于AccountDao。怎么样？简单吧。这次有接口了：） AccountDao接口－&gt;AccountSqlMapDao实现。</p>
<p><a name="N10237"><span class="smalltitle">3.5. 业务层</span></a></p>
<p>业务层的位置以及相关类，如下图所示：</p>
<br />
<img height="240" alt="" src="http://www.ibm.com/developerworks/cn/java/j-s-s-i/images/image009.jpg" width="259" border="0" /> <br />
<p>在这个例子中只有3个业务类，我们以OrderService类为例来改造，这个类是最复杂的，其中涉及了事务。</p>
<p>1、在ApplicationContext配置文件中增加bean的配置：</p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">    &lt;bean id="OrderService"
            class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"&gt;
            &lt;property name="transactionManager"&gt;
            &lt;ref local="TransactionManager"&gt;&lt;/ref&gt;
            &lt;/property&gt;
            &lt;property name="target"&gt;
            &lt;bean class="com.ibatis.jpetstore.service.OrderService"&gt;
            &lt;property name="itemDao"&gt;
            &lt;ref bean="ItemDao"/&gt;
            &lt;/property&gt;
            &lt;property name="orderDao"&gt;
            &lt;ref bean="OrderDao"/&gt;
            &lt;/property&gt;
            &lt;property name="sequenceDao"&gt;
            &lt;ref bean="SequenceDao"/&gt;
            &lt;/property&gt;
            &lt;/bean&gt;
            &lt;/property&gt;
            &lt;property name="transactionAttributes"&gt;
            &lt;props&gt;
            &lt;prop key="insert*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt;
            &lt;/props&gt;
            &lt;/property&gt;
            &lt;/bean&gt;
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>定义了一个OrderService，还是很容易懂的。为了简单起见，使用了嵌套bean，其实现类是com.ibatis.jpetstore.service.OrderService，分别引用了ItemDao，OrderDao，SequenceDao。该bean的insert*实现了事务管理(AOP方式)。TransactionProxyFactoryBean自动创建一个事务advisor， 该advisor包括一个基于事务属性的pointcut,因此只有事务性的方法被拦截。</p>
<p>2、业务类的修改</p>
<p>以OrderService为例：</p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public class OrderService {
            /* Private Fields */
            private ItemDao itemDao;
            private OrderDao orderDao;
            private SequenceDao sequenceDao;
            /* Constructors */
            public OrderService() {
            }
            /**
            * @param itemDao 要设置的 itemDao。
            */
            public final void setItemDao(ItemDao itemDao) {
            this.itemDao = itemDao;
            }
            /**
            * @param orderDao 要设置的 orderDao。
            */
            public final void setOrderDao(OrderDao orderDao) {
            this.orderDao = orderDao;
            }
            /**
            * @param sequenceDao 要设置的 sequenceDao。
            */
            public final void setSequenceDao(SequenceDao sequenceDao) {
            this.sequenceDao = sequenceDao;
            }
            //剩下的部分
            &#8230;&#8230;.
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>红色部分为修改部分。Spring采用的是Type2的设置依赖注入，所以我们只需要定义属性和相应的设值函数就可以了，ItemDao，OrderDao，SequenceDao的值由spring在运行期间注入。构造函数就可以为空了，另外也不需要自己编写代码处理事务了（事务在配置中声明），daoManager.startTransaction();等与事务相关的语句也可以去掉了。和原来的代码比较一下，是不是处理精简了很多！可以更关注业务的实现。</p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
            <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" cellpadding="0" align="right">
    <tbody>
        <tr align="right">
            <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
            <table cellspacing="0" cellpadding="0" border="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                        </td>
                        <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/java/j-s-s-i/?ca=j-t10#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="N10275"><span class="atitle">4. 结束语</span></a></p>
<p>ibatis是一个功能强大实用的SQL Map工具，可以直接控制SQL,为系统设计提供了更大的自由空间。其提供的最新示例程序JpetStore 4.0,设计优雅，应用了迄今为止很多最佳实践和设计模式，非常适于学习以及在此基础上创建轻量级的J2EE WEB应用程序。JpetStore 4.0是基于struts的，本文在此基础上，最大程度保持了原有设计的精华以及最小的代码改动量，在业务层和持久化层引入了Spring。在您阅读了本文以及改造后的源代码后，会深切的感受到Spring带来的种种好处：自然的面向接口的编程，业务对象的依赖注入，一致的数据存取框架和声明式的事务处理，统一的配置文件&#8230;更重要的是Spring既是全面的又是模块化的，Spring有分层的体系结构，这意味着您能选择仅仅使用它任何一个独立的部分，就像本文，而它的架构又是内部一致。</p>
<br />
<br />
<p><a name="resources"><span class="atitle">参考资料 </span></a></p>
<ul>
    <li>jpetstore相关各种资料和源程序 <a href="http://www.ibatis.com/jpetstore/jpetstore.html">http://www.ibatis.com/jpetstore/jpetstore.html</a><br />
    <br />
    <li>Spring中文参考手册<a href="http://www.jactiongroup.net/reference/html/index.html">http://www.jactiongroup.net/reference/html/index.html</a><br />
    <br />
    <li>Spring 开发指南 夏昕<br />
    <br />
    <li>Struts <a href="http://struts.apache.org/">http://struts.apache.org/</a><br />
    </li>
</ul>
<img src ="http://www.blogjava.net/libin2722/aggbug/165532.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2007-12-05 15:40 <a href="http://www.blogjava.net/libin2722/articles/165532.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>精通Spring——Java轻量级架构开发实践</title><link>http://www.blogjava.net/libin2722/articles/165531.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 05 Dec 2007 07:39:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/articles/165531.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/165531.html</wfw:comment><comments>http://www.blogjava.net/libin2722/articles/165531.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/165531.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/165531.html</trackback:ping><description><![CDATA[<div style="font-size: 15px; text-align: center"><a href="http://book.csdn.net/bookfiles/92/100922653.shtml">10.3 Spring对IBatis的支持&nbsp; </a></div>
<div style="font-size: 15px; text-align: center"><a href="http://book.csdn.net/">http://book.csdn.net/</a> 2006-8-15 16:27:00 </div>
<div style="border-right: #0b5f98 1px solid; border-top: #0b5f98 1px solid; float: left; margin: 0px auto; border-left: #0b5f98 1px solid; width: 600px; border-bottom: #0b5f98 1px solid">
<div style="padding-right: 1px; padding-left: 1px; float: left; padding-bottom: 1px; width: 16px; color: white; padding-top: 1px; background-color: #0b5f98">图书导读 </div>
<div style="padding-left: 2px; float: right; width: 570px; line-height: 16pt; text-align: left">
<h1 id="divCurrentNode" style="padding-left: 2px; font-size: 12px; width: 100%; color: #b83507; text-align: left">当前章节:<a href="http://book.csdn.net/bookfiles/92/100922653.shtml"><font color="red">10.3 Spring对IBatis的支持</font></a></h1>
<div id="divRelateNode" style="padding-left: 2px">
<div style="float: left; width: 49%">&#183;<a href="http://book.csdn.net/bookfiles/92/100922650.shtml">4.1 模式（Pattern）入门</a></div>
<div style="float: right; width: 49%">&#183;<a href="http://book.csdn.net/bookfiles/92/100922651.shtml">4.2 工厂模式（Design Pattern：Factory Method）的精髓</a></div>
<div style="float: left; width: 49%">&#183;<a href="http://book.csdn.net/bookfiles/92/100922652.shtml">4.3 单例模式（Design Pattern：Singleton）</a></div>
<div style="float: right; width: 49%">&#183;<a href="http://book.csdn.net/bookfiles/92/100922654.shtml">10.4 Spring对Hibernate的支持</a></div>
<div style="float: left; width: 49%">&#183;<a href="http://book.csdn.net/bookfiles/92/100922655.shtml">10.5 小结</a></div>
<div style="float: right; width: 49%">&#183;<a href="http://book.csdn.net/bookfiles/92/100922656.shtml">18.1 模仿对象</a></div>
</div>
</div>
</div>
<div id="main">
<div id="text">
<div id="csdn_zhaig_ad_yahoo_2">
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td>
            <dl>
            <dt><a href="http://tagegg.csdn.net/b.aspx?action=click&amp;unionuser=22&amp;adurl=http%3a%2f%2fwww.jobg.cn&amp;adid=1388&amp;tag=" target="_blank">IT 游戏 开发人才专业招聘网站</a></dt>
            <dd>每日上万个IT简历更新,快捷有效的招聘求职 </dd>
            <dd><a href="http://tagegg.csdn.net/b.aspx?action=click&amp;unionuser=22&amp;adurl=http%3a%2f%2fwww.jobg.cn&amp;adid=1388&amp;tag=" target="_blank">www.jobg.cn</a></dd>
            <dt><a href="http://tagegg.csdn.net/b.aspx?action=click&amp;unionuser=22&amp;adurl=http%3a%2f%2fwww.kettas.com.cn%2fad1_bk_ty.asp&amp;adid=1356&amp;tag=" target="_blank">非常4＋1大学生实训计划，首付6800</a></dt>
            <dd>4个月的全套Java技术体系的实训, 1个月的企业大型真实项目的实战开发。 </dd>
            <dd><a href="http://tagegg.csdn.net/b.aspx?action=click&amp;unionuser=22&amp;adurl=http%3a%2f%2fwww.kettas.com.cn%2fad1_bk_ty.asp&amp;adid=1356&amp;tag=" target="_blank">www.kettas.com.cn/</a></dd>
            <dt><a href="http://tagegg.csdn.net/b.aspx?action=click&amp;unionuser=22&amp;adurl=http%3a%2f%2flive.csdn.net%2fIssue15%2fLivePlay.aspx&amp;adid=|368&amp;tag=" target="_blank">近距离接触开源ERP</a></dt>
            <dd>开源带来了哪些方面的好处？ 开源后的运营方向又是怎样？ </dd>
            <dd><a href="http://tagegg.csdn.net/b.aspx?action=click&amp;unionuser=22&amp;adurl=http%3a%2f%2flive.csdn.net%2fIssue15%2fLivePlay.aspx&amp;adid=|368&amp;tag=" target="_blank">live.csdn.net</a></dd></dl></td>
        </tr>
    </tbody>
</table>
</div>
<p style="text-indent: 20.4pt">Spring<span style="font-family: 宋体">对</span>IBatis<span style="font-family: 宋体">提供了完善的内建支持。使用</span>Spring<span style="font-family: 宋体">提供的</span>IBatis<span style="font-family: 宋体">辅助类，可以大大简化原有的</span>IBatis<span style="font-family: 宋体">访问代码。这些辅助类位于</span>org.springframework.orm.ibatis<span style="font-family: 宋体">包下，目前</span>Spring<span style="font-family: 宋体">可同时支持</span>IBatis1.3.x<span style="font-family: 宋体">和</span>2.0<span style="font-family: 宋体">。</span> <span style="font-family: 宋体">此外，针对</span>IBatis<span style="font-family: 宋体">，</span>Spring<span style="font-family: 宋体">也提供了和</span>JdbcTemplate<span style="font-family: 宋体">一致的异常处理方式</span></p>
<h3 style="margin: 15pt 0cm 15pt 48pt; vertical-align: baseline; text-indent: -48pt; line-height: 15.7pt"><span style="font-weight: normal; font-size: 13pt; font-family: Arial">10.3.1<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-weight: normal; font-size: 13pt; font-family: 黑体">标准</span><span style="font-weight: normal; font-size: 13pt; font-family: Arial">JavaBean</span><span style="font-weight: normal; font-size: 13pt; font-family: 黑体">实体和映射</span></h3>
<p style="text-indent: 20.4pt">Spring<span style="font-family: 宋体">宠物店非常典型的展现了</span>Spring<span style="font-family: 宋体">和</span>IBatis<span style="font-family: 宋体">的整合，下文将围绕宠物店展开介绍。</span></p>
<p style="text-indent: 20.4pt"><span style="font-family: 宋体">首先来看宠物店中的一个领域对象（它是一个标准的</span>JavaBean<span style="font-family: 宋体">）和它的映射文件，如代码</span>10.13~10.14<span style="font-family: 宋体">所示。</span></p>
<div style="border-right: windowtext 1pt solid; padding-right: 4pt; border-top: windowtext 1pt solid; padding-left: 4pt; padding-bottom: 1pt; margin-left: 20.4pt; border-left: windowtext 1pt solid; margin-right: 0cm; padding-top: 1pt; border-bottom: windowtext 1pt solid">
<p style="border-right: medium none; padding-right: 0cm; border-top: medium none; padding-left: 0cm; padding-bottom: 0cm; margin-left: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: medium none"><span style="font-family: 黑体">代码</span>10.13&nbsp; Product.java</p>
</div>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">public class Product implements Serializable {</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; private String productId;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; private String categoryId;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; private String name;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; private String description;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt">&nbsp;<span style="font-family: 宋体">省略</span><span style="font-family: 'Courier New'">getter/setter...</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">}</span></p>
<div style="border-right: windowtext 1pt solid; padding-right: 4pt; border-top: windowtext 1pt solid; padding-left: 4pt; padding-bottom: 1pt; margin-left: 20.4pt; border-left: windowtext 1pt solid; margin-right: 0cm; padding-top: 1pt; border-bottom: windowtext 1pt solid">
<p style="border-right: medium none; padding-right: 0cm; border-top: medium none; padding-left: 0cm; padding-bottom: 0cm; margin-left: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: medium none"><span style="font-family: 黑体">代码</span>10.14&nbsp; Product.xml</p>
</div>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&lt;sqlMap namespace="Product"&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; ...</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; &lt;resultMap id="result"</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;class="org.springframework.samples.jpetstore.domain.Product"&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; &lt;result property="productId" column="productid" columnIndex="1"/&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; ...</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; &lt;/resultMap&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; &lt;select id="getProduct" resultMap="result"&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; select productid, name, descn, category from product where productid = #value#</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; &lt;/select&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; &lt;select id="getProductListByCategory" resultMap="result"&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; select productid, name, descn, category from product where category = #value#</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; &lt;/select&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; ...</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&lt;/sqlMap&gt;</span></p>
<h3 style="margin: 15pt 0cm; vertical-align: baseline; text-indent: 0cm; line-height: 15.7pt"><span style="font-weight: normal; font-size: 13pt; font-family: Arial">10.3.2</span>&nbsp;<span style="font-weight: normal; font-size: 13pt; font-family: 黑体">衔接</span><span style="font-weight: normal; font-size: 13pt; font-family: Arial">IBatis</span><span style="font-weight: normal; font-size: 13pt; font-family: 黑体">配置和</span><span style="font-weight: normal; font-size: 13pt; font-family: Arial">DAO</span><span style="font-weight: normal; font-size: 13pt; font-family: 黑体">实现</span></h3>
<p style="text-indent: 20.4pt"><span style="font-family: 宋体">接着给出</span>IBatis<span style="font-family: 宋体">的基本配置文件，如代码</span>10.15<span style="font-family: 宋体">所示。</span></p>
<div style="border-right: windowtext 1pt solid; padding-right: 4pt; border-top: windowtext 1pt solid; padding-left: 4pt; padding-bottom: 1pt; margin-left: 20.4pt; border-left: windowtext 1pt solid; margin-right: 0cm; padding-top: 1pt; border-bottom: windowtext 1pt solid">
<p style="border-right: medium none; padding-right: 0cm; border-top: medium none; padding-left: 0cm; padding-bottom: 0cm; margin-left: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: medium none"><span style="font-family: 黑体">代码</span>10.15&nbsp; sql-map-config.xml</p>
</div>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&lt;sqlMapConfig&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; ...</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; &lt;sqlMap resource="org/springframework/samples/jpetstore/dao/ibatis/maps/<strong>Product.xml</strong>"/&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; ...</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&lt;/sqlMapConfig&gt;</span></p>
<p style="text-indent: 20.4pt"><span style="font-family: 宋体">在宠物店中，该文件仅包含了所有领域对象的映射文件，而挪走了关于</span>IBatis<span style="font-family: 宋体">的事务和数据源配置（即</span>IBatis<span style="font-family: 宋体">配置文件中的</span>transactionManager<span style="font-family: 宋体">元素和它的子元素</span>dataSource<span style="font-family: 宋体">）。</span></p>
<p style="margin: 7.65pt 0cm"><strong><span style="font-family: 楷体_GB2312">注意：</span></strong><span style="font-family: 楷体_GB2312">在稍后将要给出的</span>Spring<span style="font-family: 楷体_GB2312">配置文件中接手了这些配置，这是一个整合点。</span></p>
<p style="text-indent: 20.4pt"><span style="font-family: 宋体">在宠物店中，持久和数据访问都是通过</span>DAO<span style="font-family: 宋体">来实现的。对于</span>Product<span style="font-family: 宋体">，存在一个与其对应的</span>SqlMapProductDao<span style="font-family: 宋体">，如代码</span>10.16<span style="font-family: 宋体">所示。</span></p>
<div style="border-right: windowtext 1pt solid; padding-right: 4pt; border-top: windowtext 1pt solid; padding-left: 4pt; padding-bottom: 1pt; margin-left: 20.4pt; border-left: windowtext 1pt solid; margin-right: 0cm; padding-top: 1pt; border-bottom: windowtext 1pt solid">
<p style="border-right: medium none; padding-right: 0cm; border-top: medium none; padding-left: 0cm; padding-bottom: 0cm; margin-left: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: medium none"><span style="font-family: 黑体">代码</span>10.16&nbsp; SqlMapProductDao.java</p>
</div>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">package org.springframework.samples.jpetstore.dao.ibatis;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">import java.util.ArrayList;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">import java.util.List;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">import java.util.StringTokenizer;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">import org.springframework.dao.DataAccessException;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">import org.springframework.samples.jpetstore.dao.ProductDao;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">import org.springframework.samples.jpetstore.domain.Product;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">public class SqlMapProductDao</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; extends <strong>SqlMapClientDaoSupport</strong></span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; implements ProductDao {</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; public List getProductListByCategory(String categoryId)</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; throws DataAccessException {</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; return <strong>getSqlMapClientTemplate().queryForList</strong>("getProductListByCategory",</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;categoryId);</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; }</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; public Product getProduct(String productId)</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; throws DataAccessException {</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; return (Product) <strong>getSqlMapClientTemplate().queryForObject</strong>("getProduct", productId);</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; }</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; ...</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">}</span></p>
<p style="text-indent: 20.4pt"><span style="font-family: 宋体">上述代码中出现了</span>Spring<span style="font-family: 宋体">提供的</span>IBatis DAO<span style="font-family: 宋体">支持类和获取</span>SqlMapClientTemplate<span style="font-family: 宋体">的父类模板方法，这和</span>JdbcDaoSupport<span style="font-family: 宋体">及</span>JdbcTemplate<span style="font-family: 宋体">的使用具有一致的概念。并且，这些操作都统一的抛出</span>Spring<span style="font-family: 宋体">的通用数据访问异常</span>DataAccessException<span style="font-family: 宋体">。</span></p>
<p style="margin: 7.65pt 0cm"><strong><span style="font-family: 楷体_GB2312">注意：</span></strong><span style="font-family: 楷体_GB2312">在早期的</span>IBatis1.3.x<span style="font-family: 楷体_GB2312">版本中</span>Dao<span style="font-family: 楷体_GB2312">支持类和模板类分别被命名为</span>SqlMapDaoSupport<span style="font-family: 楷体_GB2312">和</span>SqlMapTemplate<span style="font-family: 楷体_GB2312">，在使用时不要混淆。</span></p>
<h3 style="margin: 15pt 0cm; vertical-align: baseline; text-indent: 0cm; line-height: 15.7pt"><span style="font-weight: normal; font-size: 13pt; font-family: Arial">10.3.3</span>&nbsp;<span style="font-weight: normal; font-size: 13pt; font-family: 黑体">关键整合点：</span><span style="font-weight: normal; font-size: 13pt; font-family: Arial">Spring</span><span style="font-weight: normal; font-size: 13pt; font-family: 黑体">配置文件</span></h3>
<p style="text-indent: 20.4pt"><span style="font-family: 宋体">有了以上的</span>DAO<span style="font-family: 宋体">组件后，来看一下</span>Spring<span style="font-family: 宋体">的配置，这是一个关键的整合点，如代码</span>10.17<span style="font-family: 宋体">所示。</span></p>
<div style="border-right: windowtext 1pt solid; padding-right: 4pt; border-top: windowtext 1pt solid; padding-left: 4pt; padding-bottom: 1pt; margin-left: 20.4pt; border-left: windowtext 1pt solid; margin-right: 0cm; padding-top: 1pt; border-bottom: windowtext 1pt solid">
<p style="border-right: medium none; padding-right: 0cm; border-top: medium none; padding-left: 0cm; padding-bottom: 0cm; margin-left: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: medium none"><span style="font-family: 黑体">代码</span>10.17&nbsp; dataAccessContext-local.xml</p>
</div>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">"http://www.springframework.org/dtd/spring-beans.dtd"&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&lt;beans&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; &lt;!-- </span><span style="font-family: 宋体">相关数据源和事务管理的定义</span><span style="font-family: 'Courier New'"> --&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; &lt;bean id="<strong>dataSource</strong>"</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; &lt;property name="driverClassName" value="${jdbc.driverClassName}"/&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; &lt;property name="url" value="${jdbc.url}"/&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; &lt;property name="username" value="${jdbc.username}"/&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; &lt;property name="password" value="${jdbc.password}"/&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; &lt;/bean&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; &lt;!-- Transaction manager for a single JDBC DataSource --&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; &lt;bean id="<strong>transactionManager</strong>"</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; class="org.springframework.jdbc.datasource.DataSourceTransactionManager"&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; &lt;property name="dataSource" ref="dataSource"/&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; &lt;/bean&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; &lt;!-- Spring</span><span style="font-family: 宋体">提供的</span><span style="font-family: 'Courier New'">iBatis</span><span style="font-family: 宋体">的</span><span style="font-family: 'Courier New'">SqlMap</span><span style="font-family: 宋体">配置</span><span style="font-family: 'Courier New'">--&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><strong><span style="font-family: 'Courier New'">&nbsp; &lt;bean id="sqlMapClient"</span></strong></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><strong><span style="font-family: 'Courier New'">class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"&gt;</span></strong></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><strong><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; &lt;property name="configLocation" value="WEB-INF/sql-map-config.xml"/&gt;</span></strong></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><strong><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; &lt;property name="dataSource" ref="dataSource"/&gt;</span></strong></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><strong><span style="font-family: 'Courier New'">&nbsp; &lt;/bean&gt;</span></strong></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; &lt;!-- DAO</span><span style="font-family: 宋体">定义</span><span style="font-family: 'Courier New'">--&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; ...</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; &lt;bean id="productDao"</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapProductDao"&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; &lt;property name="<strong>sqlMapClient</strong>" ref="sqlMapClient"/&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; &lt;/bean&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; ...</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&lt;/beans&gt;</span></p>
<p style="text-indent: 20.4pt"><span style="font-family: 宋体">可以发现，</span>Spring<span style="font-family: 宋体">在上述文件中分别配置了数据源和事务管理的策略，其中挪去了原先在</span>IBatis<span style="font-family: 宋体">文件中的配置。</span></p>
<p style="margin: 7.65pt 0cm"><strong><span style="font-family: 楷体_GB2312">说明：</span></strong><span style="font-family: 楷体_GB2312">这样做的好处是可以通过</span>Spring IoC<span style="font-family: 楷体_GB2312">容器统一的管理资源，在稍后还可以看到，</span>Spring<span style="font-family: 楷体_GB2312">提供的声明性事务管理就是借助于统一的数据源和事务管理配置。</span></p>
<p style="text-indent: 20.4pt">SqlMapClientFactoryBean<span style="font-family: 宋体">又是一个工厂</span>bean<span style="font-family: 宋体">，它暴露了两个关键属性用于注射</span>IBatis<span style="font-family: 宋体">配置文件和相关的数据源。在工厂内部，通过读取</span>IBatis<span style="font-family: 宋体">配置文件，</span>Spring<span style="font-family: 宋体">会创建出</span>IBatis<span style="font-family: 宋体">的核心组件</span>SqlMapClient<span style="font-family: 宋体">，并向相关的</span>DAO<span style="font-family: 宋体">进行注射。</span></p>
<p style="text-indent: 20.4pt">SqlMapProductDao<span style="font-family: 宋体">继承了</span>SqlMapClientDaoSupport<span style="font-family: 宋体">，后者暴露出一个</span>sqlMapClient<span style="font-family: 宋体">属性，用于接受</span>Spring<span style="font-family: 宋体">的注射。</span>SqlMapClientDaoSupport<span style="font-family: 宋体">会对其中封装的</span>SqlMapClientTemplate<span style="font-family: 宋体">做相应的设置，所以</span>DAO<span style="font-family: 宋体">子类便可在取用</span>SqlMapClientTemplate<span style="font-family: 宋体">时正常地工作了。</span></p>
<h3 style="margin: 15pt 0cm; vertical-align: baseline; text-indent: 0cm; line-height: 15.7pt"><span style="font-weight: normal; font-size: 13pt; font-family: Arial">10.3.4</span>&nbsp;<span style="font-weight: normal; font-size: 13pt; font-family: 黑体">添加声明式事务管理</span></h3>
<p style="text-indent: 20.4pt"><span style="font-family: 宋体">以上的</span>IBatis DAO<span style="font-family: 宋体">可以很自方便地被注射到相应的业务对象，并参与到</span>Spring<span style="font-family: 宋体">提供的声明性事务中，配置如代码</span>10.18<span style="font-family: 宋体">所示。</span></p>
<div style="border-right: windowtext 1pt solid; padding-right: 4pt; border-top: windowtext 1pt solid; padding-left: 4pt; padding-bottom: 1pt; margin-left: 20.4pt; border-left: windowtext 1pt solid; margin-right: 0cm; padding-top: 1pt; border-bottom: windowtext 1pt solid">
<p style="border-right: medium none; padding-right: 0cm; border-top: medium none; padding-left: 0cm; padding-bottom: 0cm; margin-left: 0cm; border-left: medium none; padding-top: 0cm; border-bottom: medium none"><span style="font-family: 黑体">代码</span>10.18&nbsp;&nbsp; applicationContext.xml</p>
</div>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">"http://www.springframework.org/dtd/spring-beans.dtd"&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&lt;beans&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; &lt;!-- </span><span style="font-family: 宋体">通用属性文件定义</span><span style="font-family: 'Courier New'"> --&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; &lt;bean id="propertyConfigurer"</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; &lt;property name="locations"&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;list&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;WEB-INF/jdbc.properties&lt;/value&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/list&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; &lt;/property&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; &lt;/bean&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; &lt;!-- </span><span style="font-family: 宋体">业务对象定义</span><span style="font-family: 'Courier New'"> --&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; ...</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; &lt;bean id="baseTransactionProxy"</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">abstract="true"&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; &lt;property name="transactionManager" ref="<strong>transactionManager</strong>"/&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; &lt;property name="transactionAttributes"&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;props&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop key="insert*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop key="update*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop key="*"&gt;PROPAGATION_REQUIRED,readOnly&lt;/prop&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/props&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; &lt;/property&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; &lt;/bean&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; &lt;bean id="petStore" parent="baseTransactionProxy"&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; &lt;property name="target"&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;bean class="org.springframework.samples.jpetstore.domain.logic.PetStoreImpl"&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="<strong>productDao</strong>" ref="productDao"/&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/bean&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&nbsp; &lt;/bean&gt;</span></p>
<p style="margin-left: 20.4pt; line-height: 10pt"><span style="font-family: 'Courier New'">&lt;/beans&gt;</span></p>
<p style="text-indent: 20.4pt"><span style="font-family: 宋体">至此就基本完成了</span>Spring IoC<span style="font-family: 宋体">和</span>IBatis<span style="font-family: 宋体">的整合了，当然也可以通过编程的方式来使用</span>Spring<span style="font-family: 宋体">所提供的模板和支持类。</span></p>
</div>
</div>
<img src ="http://www.blogjava.net/libin2722/aggbug/165531.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2007-12-05 15:39 <a href="http://www.blogjava.net/libin2722/articles/165531.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> spring结合ibatis的一点经验，同网友分享</title><link>http://www.blogjava.net/libin2722/articles/165529.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 05 Dec 2007 07:39:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/articles/165529.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/165529.html</wfw:comment><comments>http://www.blogjava.net/libin2722/articles/165529.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/165529.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/165529.html</trackback:ping><description><![CDATA[1、 &nbsp;Spring要结合Ibatis要在Spring的应用程序上下文中配置：<br />
<table cellspacing="1" cellpadding="4" width="98%" align="center" bgcolor="#bad5ef" border="0">
    <form>
        <tbody>
            <tr>
                <td style="font-size: 12px" bgcolor="#e6eef7" height="25">程序代码：</td>
            </tr>
            <tr>
                <td style="font-size: 12px" bgcolor="#ffffff">&lt;bean&nbsp;id=<span style="color: #2a00ff">"dataSource"</span><br />
                class=<span style="color: #2a00ff">"org.apache.commons.dbcp.BasicDataSource"</span><br />
                destroy-method=<span style="color: #2a00ff">"close"</span>&gt;<br />
                &lt;property&nbsp;name=<span style="color: #2a00ff">"driverClassName"</span><br />
                value=<span style="color: #2a00ff">"${jdbc.driverClassName}"</span>&nbsp;/&gt;<br />
                &lt;property&nbsp;name=<span style="color: #2a00ff">"url"</span>&nbsp;value=<span style="color: #2a00ff">"${jdbc.url}"</span>&nbsp;/&gt;<br />
                &lt;property&nbsp;name=<span style="color: #2a00ff">"username"</span>&nbsp;value=<span style="color: #2a00ff">"${jdbc.username}"</span>&nbsp;/&gt;<br />
                &lt;property&nbsp;name=<span style="color: #2a00ff">"password"</span>&nbsp;value=<span style="color: #2a00ff">"${jdbc.password}"</span>&nbsp;/&gt;<br />
                &lt;/bean&gt;<br />
                <br />
                &lt;!--&nbsp;Spring&nbsp;iBatis&nbsp;SqlMapClient&nbsp;--&gt;<br />
                &lt;bean&nbsp;id=<span style="color: #2a00ff">"sqlMapClient"</span><br />
                class=<span style="color: #2a00ff">"org.springframework.orm.ibatis.SqlMapClientFactoryBean"</span>&gt;<br />
                &lt;property&nbsp;name=<span style="color: #2a00ff">"configLocation"</span><br />
                value=<span style="color: #2a00ff">"classpath:resource/sqlmap-config.xml"</span>&nbsp;/&gt;<br />
                &lt;property&nbsp;name=<span style="color: #2a00ff">"dataSource"</span>&nbsp;ref=<span style="color: #2a00ff">"dataSource"</span>&nbsp;/&gt;<br />
                &lt;/bean&gt;</td>
            </tr>
        </form>
    </tbody>
</table>
<br />
数据源也可以在sqlmap-config中配置。<br />
2、如果DAO的实现类是实现SqlMapClientDaoSupport的，则在应用程序上下文中中配置如下：<br />
<table cellspacing="1" cellpadding="4" width="98%" align="center" bgcolor="#bad5ef" border="0">
    <form>
        <tbody>
            <tr>
                <td style="font-size: 12px" bgcolor="#e6eef7" height="25">程序代码：</td>
            </tr>
            <tr>
                <td style="font-size: 12px" bgcolor="#ffffff">&lt;bean&nbsp;id=<span style="color: #2a00ff">"userInfoSqlMapDaoImpl"</span><br />
                class=<span style="color: #2a00ff">"com.sample.persistence.sqlmap.ibatis.UserInfoSqlMapDaoImpl"</span>&gt;<br />
                &lt;property&nbsp;name=<span style="color: #2a00ff">"sqlMapClient"</span>&nbsp;ref=<span style="color: #2a00ff">"sqlMapClient"</span>&nbsp;/&gt;<br />
                &lt;/bean&gt;<br />
                </td>
            </tr>
        </form>
    </tbody>
</table>
<br />
如果实现类没有其他的属性可以象上面的配置，如果还有其他的属性，则还要加其他的属性。
<img src ="http://www.blogjava.net/libin2722/aggbug/165529.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2007-12-05 15:39 <a href="http://www.blogjava.net/libin2722/articles/165529.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>