- 浏览: 87608 次
- 性别:
- 来自: 厦门
最新评论
-
zhengyong7232:
SELECT t.province,DECODE(landsc ...
列转行 -
meepo3927:
不是特么很懂
列转行
《Spring技术内幕》学习笔记13——SqlMapClientTemplate对Ibatis的封装
- 博客分类:
- java
1. SqlMapClientFactoryBean :
Spring 中通过 SqlMapClientTemplate 提供对 Ibatis 的支持,与 Spring 对 Hibernate 的支持类似, Spring 中 SqlMapClientFactoryBean 就是管理 Ibatis 的 IoC 容器,我们首先分析 SqlMapClientFactoryBean 的源码:
//Spring管理Ibatis的IoC容器
public class SqlMapClientFactoryBean implements FactoryBean<SqlMapClient>, InitializingBean {
//当前线程绑定Ibatis blob/clob等大字段数据处理器资源
private static final ThreadLocal<LobHandler> configTimeLobHandlerHolder = new ThreadLocal<LobHandler>();
public static LobHandler getConfigTimeLobHandler() {
return configTimeLobHandlerHolder.get();
}
//Ibatis配置文件路径
private Resource[] configLocations;
//Ibatis映射文件路径
private Resource[] mappingLocations;
//Ibatis sqlMapClient属性
private Properties sqlMapClientProperties;
//数据源
private DataSource dataSource;
//使用Spring事务包装数据源
private boolean useTransactionAwareDataSource = true;
//事务配置类
private Class transactionConfigClass = ExternalTransactionConfig.class;
//事务配置属性
private Properties transactionConfigProperties;
//blob/clob等lob类型处理器
private LobHandler lobHandler;
//Ibatis sqlMapClient
private SqlMapClient sqlMapClient;
public SqlMapClientFactoryBean() {
this.transactionConfigProperties = new Properties();
//不允许事务自动提交
this.transactionConfigProperties.setProperty("SetAutoCommitAllowed", "false");
}
//指定Ibatis sqlMapClient配置文件路径
public void setConfigLocation(Resource configLocation) {
this.configLocations = (configLocation != null ? new Resource[] {configLocation} : null);
}
//指定多个sqlMapClient配置文件路径,这些配置文件在运行时合并
public void setConfigLocations(Resource[] configLocations) {
this.configLocations = configLocations;
}
//指定Ibatis映射文件路径,这些映射文件在运行时被合并到SqlMapClient的配置中
public void setMappingLocations(Resource[] mappingLocations) {
this.mappingLocations = mappingLocations;
}
//指定Ibatis SqlMapClient可选的属性,即在SqlMapClient配置文件中通过属性
//文件设置的属性
public void setSqlMapClientProperties(Properties sqlMapClientProperties) {
this.sqlMapClientProperties = sqlMapClientProperties;
}
//设置Ibatis使用的数据源
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
//设置数据源是否使用事务包装
public void setUseTransactionAwareDataSource(boolean useTransactionAwareDataSource) {
this.useTransactionAwareDataSource = useTransactionAwareDataSource;
}
//设置Ibatis使用的事务配置类,默认是//com.ibatis.sqlmap.engine.transaction.external.ExternalTransactionConfig
public void setTransactionConfigClass(Class transactionConfigClass) {
if (transactionConfigClass == null || !TransactionConfig.class.isAssignableFrom(transactionConfigClass)) {
throw new IllegalArgumentException("Invalid transactionConfigClass: does not implement " +
"com.ibatis.sqlmap.engine.transaction.TransactionConfig");
}
this.transactionConfigClass = transactionConfigClass;
}
//设置Ibatis事务配置类属性
public void setTransactionConfigProperties(Properties transactionConfigProperties) {
this.transactionConfigProperties = transactionConfigProperties;
}
//设置Ibatis使用的处理clob/blob等大字段的处理器
public void setLobHandler(LobHandler lobHandler) {
this.lobHandler = lobHandler;
}
//IoC容器初始化完成之后的回调方法,是InitializingBean接口的实现方法
public void afterPropertiesSet() throws Exception {
//配置lob处理器
if (this.lobHandler != null) {
configTimeLobHandlerHolder.set(this.lobHandler);
}
//创建Ibatis的SqlMapClient
try {
this.sqlMapClient = buildSqlMapClient(this.configLocations, this.mappingLocations, this.sqlMapClientProperties);
//为创建的SqlMapClient设置数据源
if (this.dataSource != null) {
//创建事务配置实例
TransactionConfig transactionConfig = (TransactionConfig) this.transactionConfigClass.newInstance();
//获取数据源
DataSource dataSourceToUse = this.dataSource;
//如果Ibatis配置指定使用事务包装的数据源,并且当前获取到的数据源
//不是事务包装数据源代理类型
if (this.useTransactionAwareDataSource && !(this.dataSource instanceof TransactionAwareDataSourceProxy)) {
//为指定数据源创建事务包装代理
dataSourceToUse = new TransactionAwareDataSourceProxy(this.dataSource);
}
//事务配置对象设置数据源
transactionConfig.setDataSource(dataSourceToUse);
//初始化事务配置对象 transactionConfig.initialize(this.transactionConfigProperties);
applyTransactionConfig(this.sqlMapClient, transactionConfig);
}
}
//创建SqlMapClient成功后,清除当前线程绑定的Lob处理器资源
finally {
if (this.lobHandler != null) {
configTimeLobHandlerHolder.remove();
}
}
}
//具体创建SqlMapClient的方法,根据给定的Ibatis配置文件、Ibatis映射文件
//和Ibatis配置中的属性文件创建SqlMapClient
protected SqlMapClient buildSqlMapClient(
Resource[] configLocations, Resource[] mappingLocations, Properties properties)
throws IOException {
//如果给定Ibatis配置文件路径为空
if (ObjectUtils.isEmpty(configLocations)) {
throw new IllegalArgumentException("At least 1 'configLocation' entry is required");
}
SqlMapClient client = null;
//创建Ibatis配置文件解析器
SqlMapConfigParser configParser = new SqlMapConfigParser();
//遍历所有的Ibatis配置文件
for (Resource configLocation : configLocations) {
//获取Ibatis配置文件输入流
InputStream is = configLocation.getInputStream();
try {
//创建Ibatis SqlMapClient
client = configParser.parse(is, properties);
}
catch (RuntimeException ex) {
throw new NestedIOException("Failed to parse config resource: " + configLocation, ex.getCause());
}
}
//如果Ibatis映射文件不为null
if (mappingLocations != null) {
//根据Ibatis配置文件解析器创建Ibatis映射文件解析器
SqlMapParser mapParser = SqlMapParserFactory.createSqlMapParser(configParser);
//遍历所给定的Ibatis映射文件
for (Resource mappingLocation : mappingLocations) {
try {
//解析Ibatis映射文件
mapParser.parse(mappingLocation.getInputStream());
}
catch (NodeletException ex) {
throw new NestedIOException("Failed to parse mapping resource: " + mappingLocation, ex);
}
}
}
//返回创建的SqlMapClient对象
return client;
}
//将Ibatis配置中指定的事务配置应用到SqlMapClient上
protected void applyTransactionConfig(SqlMapClient sqlMapClient, TransactionConfig transactionConfig) {
//如果SqlMapClient不是ExtendedSqlMapClient类型,则无法将Ibatis配置//中指定的事务配置应用到SqlMapClient对象
if (!(sqlMapClient instanceof ExtendedSqlMapClient)) {
throw new IllegalArgumentException(
"Cannot set TransactionConfig with DataSource for SqlMapClient if not of type " +
"ExtendedSqlMapClient: " + sqlMapClient);
}
ExtendedSqlMapClient extendedClient = (ExtendedSqlMapClient) sqlMapClient;
//设置最大并发Ibatis事务数量 transactionConfig.setMaximumConcurrentTransactions(extendedClient.getDelegate().getMaxTransactions());
//为SqlMapClient设置事务处理器
extendedClient.getDelegate().setTxManager(new TransactionManager(transactionConfig));
}
//Spring IoC容器中对应用提供的一个获取被管理对象的方法,应该通过此方法获
//取被Spring IoC容器管理的Ibatis SqlMapClient对象
public SqlMapClient getObject() {
return this.sqlMapClient;
}
//获取SqlMapClient的类型
public Class<? extends SqlMapClient> getObjectType() {
return (this.sqlMapClient != null ? this.sqlMapClient.getClass() : SqlMapClient.class);
}
//默认Spring IoC容器中管理的对象是单态模式的
public boolean isSingleton() {
return true;
}
//Ibatis映射解析器工厂,内部类
private static class SqlMapParserFactory {
//创建Ibatis映射解析器
public static SqlMapParser createSqlMapParser(SqlMapConfigParser configParser) {
XmlParserState state = null;
try {
//使用JDK反射机制获取SqlMapConfigParser类中的state字段
Field stateField = SqlMapConfigParser.class.getDeclaredField("state");
//使用JDK反射机制使state字段可以被访问,主要解决private、//protect和默认访问权限没有提供get方法的情况
stateField.setAccessible(true);
//使用Ibatis配置解析器获取指定字段的值
state = (XmlParserState) stateField.get(configParser);
}
catch (Exception ex) {
throw new IllegalStateException("iBATIS 2.3.2 'state' field not found in SqlMapConfigParser class - " +
"please upgrade to IBATIS 2.3.2 or higher in order to use the new 'mappingLocations' feature. " + ex);
}
//为指定字段值创建Ibatis映射解析器
return new SqlMapParser(state);
}
}
195.}
SqlMapClientFactoryBean 实现了 Spring 的 FactoryBean 接口,是 Spring 中管理 Ibatis 的 IoC 容器,在 IoC 容器初始化过程中主要完成定位 Ibatis 配置文件和 Ibatis 映射文件等工作。同时 SqlMapClientFactoryBean 实现了 InitializingBean 接口,实现了 afterPropertiesSet 方法,该方法是在 IoC 容器初始化完成之后由 IoC 容器进行回调的,在该方法中主要是根据定义的 Ibatis 配置和映射文件创建 Ibatis 的 SqlMapClient 对象的过程。
2.SqlMapClientTemplate :
Spring 通过 SqlMapClientTemplate 对 Ibatis 一些通用操作做统一的封装处理,同时也对 Ibatis 的 API 做了一些封装,方便开发者使用,下面我们继续分析 SqlMapClientTemplate 对 Ibatis 封装的实现。
(1).execute 方法的实现:
同 JdbcTemplate 和 HibernateTemplate 一样, Spring 在 SqlMapClientTemplate 中也是通过 execute 方法封装 Ibatis 增删改查前的通用操作,同时在 execute 方法中调用相应的回调对象的回调方法来真正完成 Ibatis 的处理操作, execute 方法源码如下:
public <T> T execute(SqlMapClientCallback<T> action) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
Assert.notNull(this.sqlMapClient, "No SqlMapClient specified");
//通过SqlMapClient对象打开一个Ibatis SqlMapSession
SqlMapSession session = this.sqlMapClient.openSession();
if (logger.isDebugEnabled()) {
logger.debug("Opened SqlMapSession [" + session + "] for iBATIS operation");
}
Connection ibatisCon = null;
try {
Connection springCon = null;
//获取数据源
DataSource dataSource = getDataSource();
//根据数据源是否是事务包装数据源代理类型,判断数据源是否需要事务包装
boolean transactionAware = (dataSource instanceof TransactionAwareDataSourceProxy);
try {
//获取连接
ibatisCon = session.getCurrentConnection();
//如果当前Ibatis SqlMapSession还没有创建过连接
if (ibatisCon == null) {
//如果Ibatis数据源已经在Spring事务管理之下,则直接使用数据源//创建连接,否则,使用DataSourceUtils创建连接,并且创建的连//接置于Spring事务管理之中
springCon = (transactionAware ?
dataSource.getConnection() : DataSourceUtils.doGetConnection(dataSource));
session.setUserConnection(springCon);
if (logger.isDebugEnabled()) {
logger.debug("Obtained JDBC Connection [" + springCon + "] for iBATIS operation");
}
}
//如果当前Ibatis SqlMapSession已经创建过连接,则直接使用
else {
if (logger.isDebugEnabled()) {
logger.debug("Reusing JDBC Connection [" + ibatisCon + "] for iBATIS operation");
}
}
}
catch (SQLException ex) {
throw new CannotGetJdbcConnectionException("Could not get JDBC Connection", ex);
}
//调用具体增删改查操作回调对象的方法
try {
return action.doInSqlMapClient(session);
}
catch (SQLException ex) {
throw getExceptionTranslator().translate("SqlMapClient operation", null, ex);
}
finally {
try {
//释放连接
if (springCon != null) {
if (transactionAware) {
springCon.close();
}
else {
DataSourceUtils.doReleaseConnection(springCon, dataSource);
}
}
}
catch (Throwable ex) {
logger.debug("Could not close JDBC Connection", ex);
}
}
}
//关闭Ibatis的SqlMapSession
finally {
if (ibatisCon == null) {
session.close();
}
}
}
(2).Spring 封装 Ibatis API 的方法:
我们以 Spring 的 queryForObject 方法为例,分析 Spring 封装 Ibatis API 的实现,源码如下
//查询对象
public Object queryForObject(final String statementName, final Object parameterObject)
throws DataAccessException {
//调用execute方法,参数是实现了SqlMapClientCallback接口的匿名内部类,
//execute方法中回调该对象的doInSqlMapClient方法
return execute(new SqlMapClientCallback<Object>() {
//真正调用Ibatis API做具体操作处理的方法
public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException {
//调用Ibatis SqlMapSession对象的queryForObejct方法
return executor.queryForObject(statementName, parameterObject);
}
});
}
Spring 中通过 SqlMapClientTemplate 提供对 Ibatis 的支持,与 Spring 对 Hibernate 的支持类似, Spring 中 SqlMapClientFactoryBean 就是管理 Ibatis 的 IoC 容器,我们首先分析 SqlMapClientFactoryBean 的源码:
//Spring管理Ibatis的IoC容器
public class SqlMapClientFactoryBean implements FactoryBean<SqlMapClient>, InitializingBean {
//当前线程绑定Ibatis blob/clob等大字段数据处理器资源
private static final ThreadLocal<LobHandler> configTimeLobHandlerHolder = new ThreadLocal<LobHandler>();
public static LobHandler getConfigTimeLobHandler() {
return configTimeLobHandlerHolder.get();
}
//Ibatis配置文件路径
private Resource[] configLocations;
//Ibatis映射文件路径
private Resource[] mappingLocations;
//Ibatis sqlMapClient属性
private Properties sqlMapClientProperties;
//数据源
private DataSource dataSource;
//使用Spring事务包装数据源
private boolean useTransactionAwareDataSource = true;
//事务配置类
private Class transactionConfigClass = ExternalTransactionConfig.class;
//事务配置属性
private Properties transactionConfigProperties;
//blob/clob等lob类型处理器
private LobHandler lobHandler;
//Ibatis sqlMapClient
private SqlMapClient sqlMapClient;
public SqlMapClientFactoryBean() {
this.transactionConfigProperties = new Properties();
//不允许事务自动提交
this.transactionConfigProperties.setProperty("SetAutoCommitAllowed", "false");
}
//指定Ibatis sqlMapClient配置文件路径
public void setConfigLocation(Resource configLocation) {
this.configLocations = (configLocation != null ? new Resource[] {configLocation} : null);
}
//指定多个sqlMapClient配置文件路径,这些配置文件在运行时合并
public void setConfigLocations(Resource[] configLocations) {
this.configLocations = configLocations;
}
//指定Ibatis映射文件路径,这些映射文件在运行时被合并到SqlMapClient的配置中
public void setMappingLocations(Resource[] mappingLocations) {
this.mappingLocations = mappingLocations;
}
//指定Ibatis SqlMapClient可选的属性,即在SqlMapClient配置文件中通过属性
//文件设置的属性
public void setSqlMapClientProperties(Properties sqlMapClientProperties) {
this.sqlMapClientProperties = sqlMapClientProperties;
}
//设置Ibatis使用的数据源
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
//设置数据源是否使用事务包装
public void setUseTransactionAwareDataSource(boolean useTransactionAwareDataSource) {
this.useTransactionAwareDataSource = useTransactionAwareDataSource;
}
//设置Ibatis使用的事务配置类,默认是//com.ibatis.sqlmap.engine.transaction.external.ExternalTransactionConfig
public void setTransactionConfigClass(Class transactionConfigClass) {
if (transactionConfigClass == null || !TransactionConfig.class.isAssignableFrom(transactionConfigClass)) {
throw new IllegalArgumentException("Invalid transactionConfigClass: does not implement " +
"com.ibatis.sqlmap.engine.transaction.TransactionConfig");
}
this.transactionConfigClass = transactionConfigClass;
}
//设置Ibatis事务配置类属性
public void setTransactionConfigProperties(Properties transactionConfigProperties) {
this.transactionConfigProperties = transactionConfigProperties;
}
//设置Ibatis使用的处理clob/blob等大字段的处理器
public void setLobHandler(LobHandler lobHandler) {
this.lobHandler = lobHandler;
}
//IoC容器初始化完成之后的回调方法,是InitializingBean接口的实现方法
public void afterPropertiesSet() throws Exception {
//配置lob处理器
if (this.lobHandler != null) {
configTimeLobHandlerHolder.set(this.lobHandler);
}
//创建Ibatis的SqlMapClient
try {
this.sqlMapClient = buildSqlMapClient(this.configLocations, this.mappingLocations, this.sqlMapClientProperties);
//为创建的SqlMapClient设置数据源
if (this.dataSource != null) {
//创建事务配置实例
TransactionConfig transactionConfig = (TransactionConfig) this.transactionConfigClass.newInstance();
//获取数据源
DataSource dataSourceToUse = this.dataSource;
//如果Ibatis配置指定使用事务包装的数据源,并且当前获取到的数据源
//不是事务包装数据源代理类型
if (this.useTransactionAwareDataSource && !(this.dataSource instanceof TransactionAwareDataSourceProxy)) {
//为指定数据源创建事务包装代理
dataSourceToUse = new TransactionAwareDataSourceProxy(this.dataSource);
}
//事务配置对象设置数据源
transactionConfig.setDataSource(dataSourceToUse);
//初始化事务配置对象 transactionConfig.initialize(this.transactionConfigProperties);
applyTransactionConfig(this.sqlMapClient, transactionConfig);
}
}
//创建SqlMapClient成功后,清除当前线程绑定的Lob处理器资源
finally {
if (this.lobHandler != null) {
configTimeLobHandlerHolder.remove();
}
}
}
//具体创建SqlMapClient的方法,根据给定的Ibatis配置文件、Ibatis映射文件
//和Ibatis配置中的属性文件创建SqlMapClient
protected SqlMapClient buildSqlMapClient(
Resource[] configLocations, Resource[] mappingLocations, Properties properties)
throws IOException {
//如果给定Ibatis配置文件路径为空
if (ObjectUtils.isEmpty(configLocations)) {
throw new IllegalArgumentException("At least 1 'configLocation' entry is required");
}
SqlMapClient client = null;
//创建Ibatis配置文件解析器
SqlMapConfigParser configParser = new SqlMapConfigParser();
//遍历所有的Ibatis配置文件
for (Resource configLocation : configLocations) {
//获取Ibatis配置文件输入流
InputStream is = configLocation.getInputStream();
try {
//创建Ibatis SqlMapClient
client = configParser.parse(is, properties);
}
catch (RuntimeException ex) {
throw new NestedIOException("Failed to parse config resource: " + configLocation, ex.getCause());
}
}
//如果Ibatis映射文件不为null
if (mappingLocations != null) {
//根据Ibatis配置文件解析器创建Ibatis映射文件解析器
SqlMapParser mapParser = SqlMapParserFactory.createSqlMapParser(configParser);
//遍历所给定的Ibatis映射文件
for (Resource mappingLocation : mappingLocations) {
try {
//解析Ibatis映射文件
mapParser.parse(mappingLocation.getInputStream());
}
catch (NodeletException ex) {
throw new NestedIOException("Failed to parse mapping resource: " + mappingLocation, ex);
}
}
}
//返回创建的SqlMapClient对象
return client;
}
//将Ibatis配置中指定的事务配置应用到SqlMapClient上
protected void applyTransactionConfig(SqlMapClient sqlMapClient, TransactionConfig transactionConfig) {
//如果SqlMapClient不是ExtendedSqlMapClient类型,则无法将Ibatis配置//中指定的事务配置应用到SqlMapClient对象
if (!(sqlMapClient instanceof ExtendedSqlMapClient)) {
throw new IllegalArgumentException(
"Cannot set TransactionConfig with DataSource for SqlMapClient if not of type " +
"ExtendedSqlMapClient: " + sqlMapClient);
}
ExtendedSqlMapClient extendedClient = (ExtendedSqlMapClient) sqlMapClient;
//设置最大并发Ibatis事务数量 transactionConfig.setMaximumConcurrentTransactions(extendedClient.getDelegate().getMaxTransactions());
//为SqlMapClient设置事务处理器
extendedClient.getDelegate().setTxManager(new TransactionManager(transactionConfig));
}
//Spring IoC容器中对应用提供的一个获取被管理对象的方法,应该通过此方法获
//取被Spring IoC容器管理的Ibatis SqlMapClient对象
public SqlMapClient getObject() {
return this.sqlMapClient;
}
//获取SqlMapClient的类型
public Class<? extends SqlMapClient> getObjectType() {
return (this.sqlMapClient != null ? this.sqlMapClient.getClass() : SqlMapClient.class);
}
//默认Spring IoC容器中管理的对象是单态模式的
public boolean isSingleton() {
return true;
}
//Ibatis映射解析器工厂,内部类
private static class SqlMapParserFactory {
//创建Ibatis映射解析器
public static SqlMapParser createSqlMapParser(SqlMapConfigParser configParser) {
XmlParserState state = null;
try {
//使用JDK反射机制获取SqlMapConfigParser类中的state字段
Field stateField = SqlMapConfigParser.class.getDeclaredField("state");
//使用JDK反射机制使state字段可以被访问,主要解决private、//protect和默认访问权限没有提供get方法的情况
stateField.setAccessible(true);
//使用Ibatis配置解析器获取指定字段的值
state = (XmlParserState) stateField.get(configParser);
}
catch (Exception ex) {
throw new IllegalStateException("iBATIS 2.3.2 'state' field not found in SqlMapConfigParser class - " +
"please upgrade to IBATIS 2.3.2 or higher in order to use the new 'mappingLocations' feature. " + ex);
}
//为指定字段值创建Ibatis映射解析器
return new SqlMapParser(state);
}
}
195.}
SqlMapClientFactoryBean 实现了 Spring 的 FactoryBean 接口,是 Spring 中管理 Ibatis 的 IoC 容器,在 IoC 容器初始化过程中主要完成定位 Ibatis 配置文件和 Ibatis 映射文件等工作。同时 SqlMapClientFactoryBean 实现了 InitializingBean 接口,实现了 afterPropertiesSet 方法,该方法是在 IoC 容器初始化完成之后由 IoC 容器进行回调的,在该方法中主要是根据定义的 Ibatis 配置和映射文件创建 Ibatis 的 SqlMapClient 对象的过程。
2.SqlMapClientTemplate :
Spring 通过 SqlMapClientTemplate 对 Ibatis 一些通用操作做统一的封装处理,同时也对 Ibatis 的 API 做了一些封装,方便开发者使用,下面我们继续分析 SqlMapClientTemplate 对 Ibatis 封装的实现。
(1).execute 方法的实现:
同 JdbcTemplate 和 HibernateTemplate 一样, Spring 在 SqlMapClientTemplate 中也是通过 execute 方法封装 Ibatis 增删改查前的通用操作,同时在 execute 方法中调用相应的回调对象的回调方法来真正完成 Ibatis 的处理操作, execute 方法源码如下:
public <T> T execute(SqlMapClientCallback<T> action) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
Assert.notNull(this.sqlMapClient, "No SqlMapClient specified");
//通过SqlMapClient对象打开一个Ibatis SqlMapSession
SqlMapSession session = this.sqlMapClient.openSession();
if (logger.isDebugEnabled()) {
logger.debug("Opened SqlMapSession [" + session + "] for iBATIS operation");
}
Connection ibatisCon = null;
try {
Connection springCon = null;
//获取数据源
DataSource dataSource = getDataSource();
//根据数据源是否是事务包装数据源代理类型,判断数据源是否需要事务包装
boolean transactionAware = (dataSource instanceof TransactionAwareDataSourceProxy);
try {
//获取连接
ibatisCon = session.getCurrentConnection();
//如果当前Ibatis SqlMapSession还没有创建过连接
if (ibatisCon == null) {
//如果Ibatis数据源已经在Spring事务管理之下,则直接使用数据源//创建连接,否则,使用DataSourceUtils创建连接,并且创建的连//接置于Spring事务管理之中
springCon = (transactionAware ?
dataSource.getConnection() : DataSourceUtils.doGetConnection(dataSource));
session.setUserConnection(springCon);
if (logger.isDebugEnabled()) {
logger.debug("Obtained JDBC Connection [" + springCon + "] for iBATIS operation");
}
}
//如果当前Ibatis SqlMapSession已经创建过连接,则直接使用
else {
if (logger.isDebugEnabled()) {
logger.debug("Reusing JDBC Connection [" + ibatisCon + "] for iBATIS operation");
}
}
}
catch (SQLException ex) {
throw new CannotGetJdbcConnectionException("Could not get JDBC Connection", ex);
}
//调用具体增删改查操作回调对象的方法
try {
return action.doInSqlMapClient(session);
}
catch (SQLException ex) {
throw getExceptionTranslator().translate("SqlMapClient operation", null, ex);
}
finally {
try {
//释放连接
if (springCon != null) {
if (transactionAware) {
springCon.close();
}
else {
DataSourceUtils.doReleaseConnection(springCon, dataSource);
}
}
}
catch (Throwable ex) {
logger.debug("Could not close JDBC Connection", ex);
}
}
}
//关闭Ibatis的SqlMapSession
finally {
if (ibatisCon == null) {
session.close();
}
}
}
(2).Spring 封装 Ibatis API 的方法:
我们以 Spring 的 queryForObject 方法为例,分析 Spring 封装 Ibatis API 的实现,源码如下
//查询对象
public Object queryForObject(final String statementName, final Object parameterObject)
throws DataAccessException {
//调用execute方法,参数是实现了SqlMapClientCallback接口的匿名内部类,
//execute方法中回调该对象的doInSqlMapClient方法
return execute(new SqlMapClientCallback<Object>() {
//真正调用Ibatis API做具体操作处理的方法
public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException {
//调用Ibatis SqlMapSession对象的queryForObejct方法
return executor.queryForObject(statementName, parameterObject);
}
});
}
发表评论
-
最小生成树之Kruskal算法
2013-12-15 00:54 1066这篇文章实现最小生成树的Kruskal算法Kruskal算 ... -
排序算法--插入排序
2013-12-15 00:47 1037插入排序原理:假设 ... -
poi创建下拉框
2013-04-16 19:01 0package finance.tools.salesper ... -
Spring中Transactional配置
2013-04-11 20:43 979Spring中Transactional配置 标签: 杂谈 分 ... -
Hibernate将Enum枚举类型映射为Int类型 .
2013-04-09 16:46 1506最近要用Hibernate做一个枚举类型的映射,在MySQL ... -
Hibernate 更灵活的用法 HibernateCallback
2013-01-22 14:41 1392在项目中用Hibernate的DetachedCriter ... -
spring源代码分析(2)--BeanFactory
2013-01-20 12:38 1388我们首先来看下BeanFacroty接口 pa ... -
spring源代码分析(1)--Resource的分析
2013-01-20 12:22 4006我们知道,在spring中,配置文件是通过资源形式加载的, ... -
DefaultListableBeanFactory研究
2013-01-18 10:49 5876DefaultSingletonBeanRegistry完 ... -
jvm的内存调优
2013-01-11 15:54 8321) 堆 运行时数 ... -
struts2中Action的name 和package的name和namespace是什么作用
2013-01-02 12:16 9601在struts2的 struts.xml 配置中 例: ... -
深入探索 高效的Java异常处理框架
2012-10-22 14:09 879摘要:本文从Java异常最基本的概念、语法开始讲述了Java异 ... -
JAVA对ArrayList排序
2012-10-16 21:53 16486java如何对ArrayList中对象按照该对象某属性排序 ... -
ThreadPoolExecutor使用和思考(中)-keepAliveTime及拒绝策略
2012-09-11 00:48 929工作中多处接触到了ThreadPoolExecutor。趁着现 ... -
ThreadPoolExecutor使用和思考(上)-线程池大小设置与BlockingQueue的三种实现区别
2012-09-11 00:45 1620工作中多处接触到了ThreadPoolExecutor。趁着现 ... -
Spring IOC之BeanFactory
2012-09-10 12:39 1284BeanFactory ,作为 Spring 基础的 IoC ... -
Java5 并发学习
2012-09-10 11:33 797在Java5之后 ... -
Spring对事务管理的支持的发展历程(基础篇
2012-08-31 17:43 918Connection conn = DataS ... -
CXF ,在Client端用于把 Date 类型转换成 XMLGregorianCalendar .
2012-08-31 16:54 1623import javax.xml.datatype.Datat ... -
《Spring技术内幕》学习笔记10——Web环境中Spring的启动过程
2012-07-30 09:04 9811.Spring 不但可以在 JavaSE 环境中应用,在 W ...
相关推荐
最近想在最新的Spring5.0中集成ibatis(不是mybatis),发现已经不在支持SqlmapClientTemplate和SqlmapClientFactoryBean,于是搞了这个工具jar来进行支持如下配置 <bean id="sqlMapClient" class="org.spring...
Spring通过DAO模式,提供了对iBATIS的良好支持。SqlMapClient对象是iBATIS中的主要对象,我们可以通过配置让spring来管理SqlMapClient对象的创建。 与hibernate类似,Spring 提供了SqlMapClientDaoSupport对象,我们...
<bean id="sqlMapClientTemplate" class="org.springframework.orm.ibatis.SqlMapClientTemplate"> <!-- 配置 transactionManager事物管理--> <bean id="transactionManager" class="org.springframework....
13.8. Spring对分段文件上传(multipart file upload)的支持 13.8.1. 介绍 13.8.2. 使用MultipartResolver 13.8.3. 在表单中处理分段文件上传 13.9. 使用Spring的表单标签库 13.9.1. 配置标签库 13.9.2. form标签 ...
13.8. Spring对分段文件上传(multipart file upload)的支持 13.8.1. 介绍 13.8.2. 使用MultipartResolver 13.8.3. 在表单中处理分段文件上传 13.9. 使用Spring的表单标签库 13.9.1. 配置 13.9.2. form标签 ...
13.8. Spring对分段文件上传(multipart file upload)的支持 13.8.1. 介绍 13.8.2. 使用MultipartResolver 13.8.3. 在表单中处理分段文件上传 13.9. 使用Spring的表单标签库 13.9.1. 配置 13.9.2. form标签 ...
4.1 学习Spring的DAO理念 4.1.1 理解Spring的DataAccessException 4.1.2 与DataSource一起工作 4.1.3 一致的DAO支持 4.2 在Spring中使用JDBC 4.2.1 JDBC代码的问题 4.2.2 使用...
<bean id="sqlMapClientTemplate" class="org.springframework.orm.ibatis.SqlMapClientTemplate"> <property name="sqlMapClient"> <ref bean="sqlMapClient" /> </property> </bean> <!-- 配置要...
ControlFlowFactory.Jdk13ControlFlow ControlFlowFactory.Jdk14ControlFlow ControlFlowPointcut Controller Controller ControllerClassNameHandlerMapping Conventions CookieGenerator ...