文档章节

Spring JDBC数据源分析

 宸明
发布于 09/19 19:55
字数 756
阅读 7
收藏 2

Spring数据源分析

Spring自带数据源DriverManagerDataSource

Spring本身提供了一个简单的数据源实现类DriverManagerDataSource ,它位于org.springframework.jdbc.datasource包中。这个类实现了javax.sql.DataSource接口,但 它并没有提供池化连接的机制,每次调用getConnection()获取新连接时,只是简单地创建一个新的连接。因此,这个数据源类比较适合在单元测试 或简单的独立应用中使用,因为它不需要额外的依赖类。分析这样一段代码:

package com.jason.spring.datasource.jdbc;

import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import javax.sql.DataSource;
import java.util.List;
import java.util.Map;
public class TestSpringJDBC {

    public static void main(String[] args) {
        final ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring/spring-jdbc.xml");
        final DataSource dataSource = (DataSource) applicationContext.getBean("jdbcDataSource");
        TransactionTemplate transactionTemplate = (TransactionTemplate) applicationContext.getBean("transactionTemplate");
        try {
            JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
            List<Map<String, Object>> map = jdbcTemplate.queryForList("select * from test.order for update ");
            System.out.println(map);
            transactionTemplate.execute(new TransactionCallbackWithoutResult() {

                @Override
                protected void doInTransactionWithoutResult(TransactionStatus status) {
                    try {
                        JdbcTemplate jdbcTemplate = (JdbcTemplate)applicationContext.getBean("jdbcTemplate");
                        List<Map<String, Object>> map = jdbcTemplate.queryForList("select * from test.order for update ");
                        System.out.println(map);
                    } catch (Exception e) {
                        status.setRollbackOnly();
                    }
                }
            });
            //System.in.read();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

对应的spring的配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
						http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
   <bean id="jdbcDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
       <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
       <property name="url" value="jdbc:mysql://localhost:3306/test"/>
       <property name="username" value="root"/>
       <property name="password" value="root"/>
   </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="jdbcDataSource"/>
    </bean>
    <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="jdbcDataSource"/>
    </bean>
    <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
        <property name="transactionManager" ref="dataSourceTransactionManager"/>
        <property name="isolationLevelName" value="ISOLATION_DEFAULT"/>
    </bean>

</beans>

会执行到JdbcTemplate中的如下方法:

public <T> T execute(StatementCallback<T> action) throws DataAccessException {
		Assert.notNull(action, "Callback object must not be null");

		Connection con = DataSourceUtils.getConnection(getDataSource());
		Statement stmt = null;
		try {
			Connection conToUse = con;
			if (this.nativeJdbcExtractor != null &&
					this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativeStatements()) {
				conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
			}
			stmt = conToUse.createStatement();
			applyStatementSettings(stmt);
			Statement stmtToUse = stmt;
			if (this.nativeJdbcExtractor != null) {
				stmtToUse = this.nativeJdbcExtractor.getNativeStatement(stmt);
			}
			T result = action.doInStatement(stmtToUse);
			handleWarnings(stmt);
			return result;
		}
		catch (SQLException ex) {
			// Release Connection early, to avoid potential connection pool deadlock
			// in the case when the exception translator hasn't been initialized yet.
			JdbcUtils.closeStatement(stmt);
			stmt = null;
			DataSourceUtils.releaseConnection(con, getDataSource());
			con = null;
			throw getExceptionTranslator().translate("StatementCallback", getSql(action), ex);
		}
		finally {
			JdbcUtils.closeStatement(stmt);
			DataSourceUtils.releaseConnection(con, getDataSource());
		}
	}

从该段代码可以看到,其Connection 是通过DataSourceUtils.getConnection(getDataSource())去拿到的,继续跟进去: 会到org.springframework.jdbc.datasource.DataSourceUtils中的:

public static Connection doGetConnection(DataSource dataSource) throws SQLException {
		Assert.notNull(dataSource, "No DataSource specified");

		ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
		if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) {
			conHolder.requested();
			if (!conHolder.hasConnection()) {
				logger.debug("Fetching resumed JDBC Connection from DataSource");
				conHolder.setConnection(dataSource.getConnection());
			}
			return conHolder.getConnection();
		}
		// Else we either got no holder or an empty thread-bound holder here.

		logger.debug("Fetching JDBC Connection from DataSource");
		Connection con = dataSource.getConnection();

		if (TransactionSynchronizationManager.isSynchronizationActive()) {
			logger.debug("Registering transaction synchronization for JDBC Connection");
			// Use same Connection for further JDBC actions within the transaction.
			// Thread-bound object will get removed by synchronization at transaction completion.
			ConnectionHolder holderToUse = conHolder;
			if (holderToUse == null) {
				holderToUse = new ConnectionHolder(con);
			}
			else {
				holderToUse.setConnection(con);
			}
			holderToUse.requested();
			TransactionSynchronizationManager.registerSynchronization(
					new ConnectionSynchronization(holderToUse, dataSource));
			holderToUse.setSynchronizedWithTransaction(true);
			if (holderToUse != conHolder) {
				TransactionSynchronizationManager.bindResource(dataSource, holderToUse);
			}
		}

		return con;
	}

在资源释放时,会有区别:无事务时,直接释放数据源,有事务时,暂时不真正的释放数据源

	public static void doReleaseConnection(Connection con, DataSource dataSource) throws SQLException {
		if (con == null) {
			return;
		}
		if (dataSource != null) {
			ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
			if (conHolder != null && connectionEquals(conHolder, con)) {
				// It's the transactional Connection: Don't close it.
				conHolder.released();
				return;
			}
		}
		logger.debug("Returning JDBC Connection to DataSource");
		doCloseConnection(con, dataSource);
	}

Spring事务管理

TransactionSynchronizationManager类分析

© 著作权归作者所有

共有 人打赏支持
粉丝 15
博文 49
码字总数 72942
作品 0
程序员
Spring MVC 使用 JNDI 配置的DataSource

稍微看了下,Spring 中JNDI 的使用,弄了个小例子。有很多不完备的地方,以后慢慢看,再改吧。 <一> 技术使用 Spring MVC JDBC Template Maven JNDI <二> 一些配置 Maven POM 配置 spring-c...

平江夜弹
2015/06/29
0
0
【死磕Sharding-jdbc】—orchestration简介&使用

原文作者:阿飞Javaer 原文链接:https://www.jianshu.com/p/c33191385767 orchestration简介 sharding-jdbc2.x核心功能之一就是orchestration,即编排治理,什么意思呢?官方文档介绍--2.0...

飞哥-Javaer
08/09
0
0
Spring AOP根据JdbcTemplate方法名动态设置数据源

说明:现在的场景是,采用MySQL Replication的方式在两台不同服务器部署并配置主从(Master-Slave)复制; 并需要程序上的数据操作方法访问不同的数据库,比如,update方法访问主数据库服务器...

cwalet
2011/11/28
0
9
Spring AOP根据JdbcTemplate方法名动态设置数据源

说明:现在的场景是,采用数据库(Mysql)复制(binlog)的方式在两台不同服务器部署并配置主从(Master-Slave)关系;并需要程序上的数据操作方法来访问不同的数据库,比如,update方法访问...

happy圈圈
2014/08/26
0
0
Hasor JDBC 的难关,嵌套事务处理思路

本文存属提醒我自己不要忘记的事情。也是向大家展示 Hasor 对于 JDBC 方面即将的又一个重大的进步。目前该方案还在实施中。 前段时间闲着没事分析了下 Spring JDBC ,觉得 Spring JDBC 的设计...

哈库纳
2013/12/29
0
9

没有更多内容

加载失败,请刷新页面

加载更多

hive数据导入导出

- 导入主要方式 load从本地加载 load从hdfs中加载 insert into方式加载 location指定源数据路径 like指定、克隆 ctas语句指定(create table tableName as ...) 手动将数据copy到表目录 5、 ...

Mr_yul
10分钟前
0
0
基于基线版本新建分支,并合并之前未合并到基线版本的分支

`合并feature2到feature5继续开发 git checkout -b feature2 origin/feature2 git pull git checkout -b baseline origin/baseline git pull git checkout -b feature5 git merge feature2 ......

philonic
17分钟前
0
0
统一认证服务CAS 5安装

简要介绍统一认证服务(CAS,Central Authentication Service,注:常称为单点登录系统)5.2.X的安装及配置。 CAS环境:Centos7.5+Tomcat8.5+jdk-8u181。后台用户管理采用openldap,其安装请...

阿笨哥
17分钟前
0
0
多线程糗事百科案例

爬取糗事百科段子,假设页面的URL是:http://www.qiushibaike.com/8hr/page/1 要求 1.使用requests获取页面信息,用XPath / re 做数据提取 2.获取每个帖子里的用户头像链接、用户姓名、段子内...

代码打碟手
20分钟前
0
0
09-《深度拆解JVM》JVM是怎么实现invokedynamic的?(上)

一、问题引入 前不久,“虚拟机”赛马俱乐部来了个年轻人,标榜自己是动态语言,是先进分子。 这一天,先进分子牵着一头鹿进来,说要参加赛马。咱部里的老学究 Java 就不同意了呀,鹿又不是马...

飞鱼说编程
26分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部