?? 在Spring 中集成iBatis的配置是很简单了,下面是一个简单的配置示例:
?
Spring?的配置文件
?
?
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd "> <context:component-scan base-package="com.david.demo.common.*" /> <context:property-placeholder location="classpath:META-INF/config.properties" /> <!-- 定义数据源 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${jdbc.ams.driver}" /> <property name="jdbcUrl" value="${jdbc.ams.url}" /> <property name="user" value="${jdbc.ams.username}" /> <property name="password" value="${jdbc.ams.password}" /> <property name="initialPoolSize" value="${initialSize}" /> <property name="minPoolSize" value="${minPoolSize}" /> <property name="maxPoolSize" value="${maxActive}" /> <property name="acquireIncrement" value="${acquireIncrement}" /> <property name="maxIdleTime" value="${maxIdleTime}" /> </bean> <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configLocation" value="classpath:META-INF/sqlmap/sqlmap.xml" /> </bean> </beans>
?config.properties
jdbc.ams.driver=com.mysql.jdbc.Driver jdbc.ams.url=jdbc:mysql://localhost:3306/test jdbc.ams.username=root jdbc.ams.password=root initialSize=3 minPoolSize=5 maxActive=100 acquireIncrement=3 maxIdleTime=10
?sqlMap.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-config-2.dtd"> <sqlMapConfig> <!-- cacheModelsEnable 是否启用sqlMapClient上的缓存机制, enhancementEnabled 是否省队POJO启用字节码增强,提升getter/setter效率 lazyLoadingEnabled 是否启用延迟加载机制 errorTracingEnable 是否启用错误日志 maxRequest 最大并发请求数(Statement 并发数) maxSession 最大Session数(SqlMapClient 并发数) maxTransaction=<maxSession=<maxRequest maxTransactions 最大并发事务 useStatemnetNamespaces 是否启用命名空间 --> <settings cacheModelsEnabled="false" enhancementEnabled="true" lazyLoadingEnabled="true" errorTracingEnabled="true" useStatementNamespaces="true" maxRequests="3000" maxSessions="3000" maxTransactions="3000" /> <sqlMap resource="META-INF/sqlmap/sqlmap-Book.xml" /> </sqlMapConfig>
?sqlmap-Book.xml
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd"> <sqlMap namespace="demo"> <resultMap class="com.david.common.domain.Book" id="BooKMap"> <result property="id" column="id" javaType="int" /> <result property="name" column="name" javaType="java.lang.String" /> <result property="price" column="price" javaType="int" nullValue="0" /> <result property="extend" column="extend" typeHandler="com.david.demo.common.handler.ExtendTypeHandler"/> </resultMap> <typeAlias alias="Book" type="com.david.common.domain.Book" /> <parameterMap class="Book" id="book"> <parameter property="name" javaType="java.lang.String" nullValue="test"/> <parameter property="price" javaType="int" nullValue="0"/> <parameter property="extend" typeHandler="com.david.demo.common.handler.ExtendTypeHandler" /> </parameterMap> <insert id="insert" parameterMap="book"> insert into t_book (name,price,extend) values (?,?,?) <selectKey keyProperty="id" resultClass="Integer"> select LAST_INSERT_ID() </selectKey> </insert> <select id="select-all" resultMap="BooKMap"> select id,name,price,extend,gmt_create,gmt_modify from t_book </select> <delete id="delete-by-id"> delete from t_book where id=#id# </delete> </sqlMap>
?
?iBatis执行SQL的关键入口是SqlMapClientImpl。通过该类的源码可以发现,在构造方法中注入了一个SqlMapExecutorDelegate?实例,但该类并不真正执行Sql?而是通过SqlMapSession去执行的。
/** * Implementation of ExtendedSqlMapClient */ public class SqlMapClientImpl implements SqlMapClient, ExtendedSqlMapClient { private static final Log log = LogFactory.getLog(SqlMapClientImpl.class); /** * 执行SQL的代理 */ public SqlMapExecutorDelegate delegate; protected ThreadLocal localSqlMapSession = new ThreadLocal(); /** * Constructor to supply a delegate * * @param delegate - the delegate */ public SqlMapClientImpl(SqlMapExecutorDelegate delegate) { this.delegate = delegate; } public Object insert(String id, Object param) throws SQLException { return getLocalSqlMapSession().insert(id, param); } ... /** 获取当前线程的SqlMapSession,如果当前线程中没有SqlMapSession或SqlMapSession已经关闭,则创建一个新的SqlMapSession 并存入到当前线程中。 */ protected SqlMapSessionImpl getLocalSqlMapSession() { SqlMapSessionImpl sqlMapSession = (SqlMapSessionImpl) localSqlMapSession.get(); if (sqlMapSession == null || sqlMapSession.isClosed()) { // 使用当前SqlMapClientImpl 作为构造参数构造一个新的SqlMapSession实例 sqlMapSession = new SqlMapSessionImpl(this); // 将实例放入ThreadLocal中 localSqlMapSession.set(sqlMapSession); } return sqlMapSession; } ... }
?通过SqlMapSessionImpl?的源码可以发现,在构造函数中,将SqlMapClientImpl中的属性delegate赋值给了SqlMapSessionImpl的属性delegate,同时可以发现SqlMapExecutorDelegate是真正执行Sql的地方
** * Implementation of SqlMapSession */ public class SqlMapSessionImpl implements SqlMapSession { protected SqlMapExecutorDelegate delegate; protected SessionScope sessionScope; protected boolean closed; /** * Constructor * * @param client - the client that will use the session */ public SqlMapSessionImpl(SqlMapClientImpl client) { this.delegate = client.getDelegate(); this.sessionScope = this.delegate.beginSessionScope(); this.sessionScope.setSqlMapClient(client); this.sessionScope.setSqlMapExecutor(client); this.sessionScope.setSqlMapTxMgr(client); this.closed = false; } /** * Start the session */ public void open() { sessionScope.setSqlMapTxMgr(this); } /** * Getter to tell if the session is still open * * @return - the status of the session */ public boolean isClosed() { return closed; } public void close() { if (delegate != null && sessionScope != null) delegate.endSessionScope(sessionScope); if (sessionScope != null) sessionScope = null; if (delegate != null) delegate = null; if (!closed) closed = true; } // 使用SqlMapExecutorDelegate去执行SQL public Object insert(String id, Object param) throws SQLException { return delegate.insert(sessionScope, id, param); } ...
?
原文:http://zhangwei-david.iteye.com/blog/2187170