浅谈在Spring中如何使用数据源(DBCP、C3P0、JNDI)

在 Spring 中,有以下三种方式来创建数据源:

  • 通过 JNDI 获取应用服务器中的数据源;
  • 在 Spring 容器中配置数据源;
  • 通过代码来创建数据源,这种方式适用于无容器依赖的单元测试。

1 配置数据源

Spring 在第三方依赖包中包含了 2 种数据源的实现包 一个是 Apache 的 DBCP;另一个是 C3P0。 我们可以在 Spring 配置文件中直接配置这些数据源 。

1.1 DBCP

DBCP (Database Connection Pool)是一个依赖 Jakarta commons-pool 对象池机制的数据库连接池,所以在类路径下还必须包括 commons-pool.jar。 下面是使用 DBCP 配置 MySql 数据源的配置片段:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  <property name="driverClassName" value="com.mysql.jdbc.Driver" />
  <property name="url" value="jdbc:mysql://localhost:3309/db" />
  <property name="username" value="root" />
  <property name="password" value="xxxxxx" />
</bean>

BasicDataSource 提供了 close() 方法用于关闭数据源,所以必须设定 destroy-method=”close”, 以便 Spring 容器关闭时,能够正常关闭数据源。

除以上必须的数据源属性外,还有一些常用的属性。

事务属性:

属性 默认值 说明
defaultAutoCommit true 连接默认为 auto-commit 状态。
defaultReadOnly 驱动默认值 连接默认的 read-only 状态 。如果没有设置则 setReadOnly 方法将不会被调用。( 某些驱动不支持只读模式 , 比如:Informix)
defaultTransactionIsolation 驱动默认值 连接默认的 TransactionIsolation 状态。有这些值:NONE、READ_COMMITTED、READ_UNCOMMITTED、REPEATABLE_READ、SERIALIZABLE。

连接数相关属性:

属性 默认值 说明
initialSize 0 初始化连接数:连接池启动时创建的初始化连接数量。
maxActive 8 最大活动连接 : 连接池在同一时间内能够分配的最大活动连接的数量。如果设置为非正数,则表示不限制。
maxIdle 8 最大空闲连接 : 连接池中容许保持空闲状态的最大连接数量 , 超过的空闲连接将被释放 , 如果设置为负数,则表示不限制。
minIdle 0 最小空闲连接 : 连接池中容许保持空闲状态的最小连接数量 , 低于这个数量将创建新的连接 , 如果设置为 0,则表示不创建。
maxWait 无限 最大等待时间 : 当没有可用连接时 , 连接池等待连接被归还的最大时间 ( 单位为毫秒 ) , 超出时间将抛出异常 , 如果设置为 -1,则表示无限等待。

连接监测与维护相关属性:

属性 默认值 说明
validationQuery 配置 SQL 查询语句 , 用于验证从连接池取出的连接是否可用。如果指定 , 则查询必须是一个 SQL SELECT,并且必须返回至少一行记录。MySQL 中是 “select 1”;在 Oracle 中是 "select 1 from dual"。
testOnBorrow true 指明是否从连接池中取出连接之前进行检测 , 如果检测失败 , 则从池中去除连接并尝试取出另一个新的连接。 注意 : 设置为 true 后如果要生效,则 validationQuery 参数必须正确被设置。
testOnReturn false 指明是否在归还到池中前进行检测。 注意 : 与 testOnBorrow 一样,设置为 true 后如果要生效,则 validationQuery 参数必须正确被设置。
testWhileIdle false 指明连接是否会被空闲连接回收器 ( 如果有 ) 所检测。 如果检测失败 , 则连接将从池中被移除。 注意 : 设置为 true 后如果要生效,则 validationQuery 参数必须正确被设置。
timeBetweenEvictionRunsMillis -1 空闲连接回收器线程运行的周期 , 以毫秒为单位。如果设置为非正数 , 则不运行空闲连接回收器线程。 注意 : 启用该参数时,则 validationQuery 参数必须正确被设置。
numTestsPerEvictionRun 3 在每次空闲连接回收器线程 ( 如果有 ) 运行时需要检测的连接数量。
minEvictableIdleTimeMillis 1000 * 60 * 30 连接在池中保持空闲而不被空闲连接回收器线程回收的最小时间值,以毫秒为单位。

缓存相关属性:

属性 默认值 说明
poolPreparedStatements false 开启连接池的 prepared statement 功能设置为 true 后,所有的 CallableStatement 和 PreparedStatement 都会被缓存起来。
maxOpenPreparedStatements 不限制 能够同时分配打开的 statements 的最大数量。0 表示不限制。

连接泄露回收相关属性:

属性 默认值 说明
removeAbandoned false 是否删除泄露的连接。如果设置为 true, 那么那些可能存在泄露的连接会被删除。假设 maxActive 为 10 个,活动连接为 8 个,空闲连接为 1 个,10-8-1=1,那么就会把删除这个连接(会先检测该活动连接未被使用的时间是否超过 removeAbandonedTimeout)。如果需要一个长连接操作,那么 removeAbandoned 需要设置的长一些,否则正常使用的连接可能会被误删除。
removeAbandonedTimeout 300 泄露的连接可以被删除的时间段,单位为秒。
logAbandoned false 当 Statement 或连接被泄露时是否打印堆栈日志 。

假设数据库用的是 MySQL,那么如果数据源配置不当,将可能会发生经典的 “8 小时问题 ”。 原因是 MySQL 在默认情况下如果发现一个连接的空闲时间超过 8 小时,那么会在数据库端自动关闭这个连接 。 而数据源并不知道这个连接已经被关闭了,所以当它将这个无用的连接返回给某个 DAO 时, DAO 就会抛出无法获取 connection 的异常 。

DBCP 的 testOnBorrow 默认设置为 true,所以从连接池中取出连接之前会先进行检测,因为不会发生 “8 小时问题 ”。 但如果每次取连接时都进行检测,那么在高并发应用下就会产生性能问题。

因此建议在高并发下,将 testOnBorrow 设置为 false;然后将 testWhileIdle 设置为 true,打开空闲连接回收器;最后把 timeBetweenEvictionRunsMillis 的值设定为小于 8 小时,这样那些被 MySQL 所关闭的空闲连接,就会被清除出去。这样不仅解决了 “8 小时问题 ”,而且还保证了高性能 O(∩_∩)O哈哈~

注意:因为 MySQL 本身的 interactive-timeout(单位为 s)参数,可以设定空闲连接的过期时间,所以我们要想获取到这个参数值,然后再设定 DBCP 的 timeBetweenEvictionRunsMillis 属性值。

1.2 C3P0

C3P0 是一个开放源代码的 JDBC 数据源实现项目,它实现了 JDBC3 和 JDBC2 扩展规范说明的 Connection 和 Statement 池。

下面是使用 C3P0 配置 MySql 数据源的配置片段:

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
  <property name="driverClass" value="oracle.jdbc.driver.OracleDriver" />
  <property name="jdbcUrl" value="jdbc:mysql://localhost:3309/db" />
  <property name="use" value="xxx" />
  <property name="password" value="xxxxxx" />
</bean>

C3P0 也提供了一个用于关闭数据源的 close() 方法,这样我们就可以保证 Spring 容器被关闭时,能够成功关闭数据源 。

属性 默认值 说明
acquireIncrement 当连接池中无空闲连接时, 一次性创建新连接的数量。
acquireRetryAttempts 30 在从数据库获取新连接失败后,重复尝试的次数。
acquireRetryDelay 1000 尝试获取连接之间的间隔时间,单位为毫秒。
autoCommitOnClose false 连接关闭时,将所有未提交的操作回滚 。
automaticTestTable null 会创建一张名为 Test 的空表,并使用其自带的查询语句进行测试 。 如果定义了这个参数,那么 preferredTestQuery 属性 将被忽略 。 我们不能在这张 Test 表上进行任何操作,它仅为 C3P0 测试所用。
breakAfterAcquireFailure false 获取连接失败时,将会引起所有等待获取连接的线程抛出异常 。 但是数据源仍有效保留,并在下次调用 getConnection() 时继续尝试获取连接 。 在尝试获取连接失败后,该数据源将申明已断开并永久关闭。
checkoutTimeout 0 当连接池中的连接用完时,客户端调用 getConnection() 后等待获取新连接的时间,单位:毫秒。超时后将抛出 SQLException 。设为 0 表示无限期等待 。
connectionTesterClassName com.mchange.v2.C3P0.impl.DefaultConnectionTester 通过实现 ConnectionTester 或 QueryConnectionTester 的类来测试连接,类名需设置为全限定名 。
idleConnectionTestPeriod 0 隔多少秒,检查连接池中的所有空闲连接。0 表示不检查。
initialPoolSize 3 初始化时创建的连接数,应在 minPoolSize 与 maxPoolSize 之间取值 。
maxIdleTime 0 最大空闲时间,超过空闲时间的连接将会被丢弃 。 为 0 或负数则表示永不丢弃 。
maxPoolSize 15 连接池中保留的最大连接数 。
maxStatements 0 JDBC 标准参数,用以控制数据源内加载的 PreparedStatement 数量 。 但由于预缓存的 Statement 属于单个 Connection 而不是整个连接池 。 所以设置这个参数需要多方面的考虑,如果 maxStatements 与 maxStatementsPerConnection 均为 0 ,则缓存被关闭 。
maxStatementsPerConnection 0 连接池内单个连接所拥有的最大缓存 Statement 数 。
numHelperThreads 3 C3P0 是异步操作的,缓慢的 JDBC 操作通过 HelperThreads 完成 。 通过多线程实现多个操作同时被执行,这样可以有效地提升性能。
preferredTestQuery null 定义所有连接测试都执行的测试语句。在使用连接测试的情况下,这个参数能够显著地提高测试速度。测试的表必须在初始数据源时就存在。
propertyCycle 300 修改系统配置参数生效时长,单位为 s。
testConnectionOnCheckout false 因性能消耗大,所以请只在需要时开启 。 如果设为 true 那么在每个 connection 提交的时候都将校验其有效性 。 建议使用 idleConnectionTestPeriod 或 automaticTestTable 等方法来提升连接测试的性能 。
testConnectionOnCheckin false 如果设为 true,那么在取得连接的同时将校验其连接的有效性。

2 JNDI 数据源

如果应用配置在高性能的应用服务器(如 WebLogic 或 Websphere 等)上,我们可能更希望使用应用服务器所提供的数据源 。 应用服务器的数据源使用 JNDI 方式来供调用者使用, Spring 为此专门提供了引用 JNDI 资源的 JndiObjectFactoryBean 类 。 下面是一个简单的配置:

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"
   p:jndiName="java:comp/env/jdbc/ds"/>

Spring2.0+ 为获取 J2EE 资源提供了一个 jee 命名空间,通过 jee 命名空间,可以有效地简化 J2EE 资源的引用:

<?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:p="http://www.springframework.org/schema/p"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
   http://www.springframework.org/schema/jee
   http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
   ">

  <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/ds"/>

</beans>

3 Spring 数据源实现类

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

Spring 数据源实现类既可以通过配置直接使用,也可以在代码中实例化调用:

DriverManagerDataSource dataSource=new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/spring4");
dataSource.setUsername("root");
dataSource.setPassword("");

try {
  Connection connection=dataSource.getConnection();
  if(connection.isClosed()){
    System.out.println("连接已关闭");
  }else{
    System.out.println("连接已开启");
  }
} catch (SQLException e) {
  e.printStackTrace();
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Spring Boot 2.0多数据源配置方法实例详解

    两个数据库实例,一个负责读,一个负责写. datasource-reader: type: com.alibaba.druid.pool.DruidDataSource url: jdbc:mysql://192.168.43.61:3306/test?useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false username: icbc password: icbc driver-class-na

  • 解决spring boot 1.5.4 配置多数据源的问题

    spring boot 已经支持多数据源配置了,无需网上好多那些编写什么类的,特别麻烦,看看如下解决方案,官方的,放心! 1.首先定义数据源配置 #=====================multiple database config============================ #ds1 first.datasource.url=jdbc:mysql://localhost/test?characterEncoding=utf8&useSSL=true first.datasou

  • springboot配置多数据源的实例(MongoDB主从)

    相信看过上一篇文章的小伙伴已经知道了, 这章要讲的就是MongoDB主从配置. 在这边文章中,你将要学到的是在项目中配置主从数据库,并且兼容其他数据库哟..这些都是博主项目中需要并且比较重要的知识哦~ 好了,废话不多说,直接进主题. 1.pom依赖 <span style="white-space:pre"> </span><dependency> <groupId>org.springframework.boot</groupId

  • Spring配置多个数据源并实现动态切换示例

    1.配置两个不同的数据源,如下(由于项目使用的是druid数据库连接,配置可以会复杂点比较): <!-- 数据源配置1 --> <bean id="testDataSource1" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name=&quo

  • Spring Boot多数据源及其事务管理配置方法

    准备工作 先给我们的项目添加Spring-JDBC依赖和需要访问数据库的驱动依赖. 配置文件 spring.datasource.prod.driverClassName=com.mysql.jdbc.Driver spring.datasource.prod.url=jdbc:mysql://127.0.0.1:3306/prod spring.datasource.prod.username=root spring.datasource.prod.password=123456 spring

  • Spring jndi数据源配置方法详解

    本文实例为大家分享了Spring jndi数据源配置代码,供大家参考,具体内容如下 xml配置: <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver

  • springboot下配置多数据源的方法

    一.springboot 简介 SpringBoot使开发独立的,产品级别的基于Spring的应用变得非常简单,你只需"just run". 我们为Spring平台及第三方库提 供开箱即用的设置,这样你就可以有条不紊地开始.多数Spring Boot应用需要很少的Spring配置. 你可以使用SpringBoot创建Java应用,并使用 java -jar 启动它或采用传统的war部署方式.我们也提供了一个运行"spring 脚本"的命令行工具. 二.传统的Dat

  • 详解springboot采用多数据源对JdbcTemplate配置的方法

    springboot多数据源配置,代码如下 DataSourceConfig package com.rookie.bigdata.config; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.

  • 浅谈在Spring中如何使用数据源(DBCP、C3P0、JNDI)

    在 Spring 中,有以下三种方式来创建数据源: 通过 JNDI 获取应用服务器中的数据源: 在 Spring 容器中配置数据源: 通过代码来创建数据源,这种方式适用于无容器依赖的单元测试. 1 配置数据源 Spring 在第三方依赖包中包含了 2 种数据源的实现包 一个是 Apache 的 DBCP:另一个是 C3P0. 我们可以在 Spring 配置文件中直接配置这些数据源 . 1.1 DBCP DBCP (Database Connection Pool)是一个依赖 Jakarta co

  • 浅谈一下Spring中的createBean

    目录 找到BeanClass并且加载类 实例化前 实例化 Supplier创建对象 工厂方法创建对象 推断构造方法 BeanDefionition 的后置处理 实例化后 属性填充 Aware回调 初始化前 初始化 初始化后 总结BeanPostProcessor 找到BeanClass并且加载类 protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws

  • 浅谈SSH框架中spring的原理

    在ssh项目中,是有明确分工的,spring的作用就相当于将struts和hibernate连接起来,是将两个没有关系的框架的特性,方法,action都放在spring的配置文件中使他们建立关系.取他门各自所长.而这些做法他们自己不知道,他们是听命于spring调度的,他的的任务只是做好自己的事情. 这样做的好处就是任务结构分明,struts只管理显示与做什么,hibernate只关心怎么做,而spring就相当于领导,所以一切的类都要交给spring的工厂创建,这是一种良好的开发模式,体现了一

  • 浅谈springboot项目中定时任务如何优雅退出

    在一个springboot项目中需要跑定时任务处理批数据时,突然有个Kill命令或者一个Ctrl+C的命令,此时我们需要当批数据处理完毕后才允许定时任务关闭,也就是当定时任务结束时才允许Kill命令生效. 启动类 启动类上我们获取到相应的上下文,捕捉相应命令.在这里插入代码片 @SpringBootApplication /**指定mapper对应包的路径*/ @MapperScan("com.youlanw.kz.dao") /**开启计划任务*/ @EnableScheduling

  • 浅谈Java开发中的安全编码问题

    1 - 输入校验 编码原则:针对各种语言本身的保留字符,做到数据与代码相分离. 1.1 SQL 注入防范 严重性高,可能性低. (1) 参数校验,拦截非法参数(推荐白名单): public String sanitizeUser(String username) { return Pattern.matches("[A-Za-z0-9_]+", username) ? username : "unauthorized user"; } (2) 使用预编译: Stri

  • 浅谈在springboot中使用定时任务的方式

    springboot定时任务 在springboot环境下有多种方法,这里记录下使用过的其中两种:1.使用注解,2.通过实现接口的方式. 使用注解的方式虽然比较简单,但是如果项目需要用户对定时周期进行修改操作,只使用注解就比较难实现.所以可以使用实现接口的方式.通过对接口的实现,可以在项目运行时根据需要修改任务执行周期,只需要关闭原任务再开启新任务即可. 1.使用注解方式 ​ 首先需要在启动类下添加 @EnableScheduling 注解(@EnableAsync是开启异步的注解) packa

  • 浅谈XML Schema中的elementFormDefault属性

    elementFormDefault属性与命名空间相关,其值可设置为qualified或unqualified 如果设置为qualified: 在XML文档中使用局部元素时,必须使用限定短名作为前缀 sean.xsd: <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:sean=&

  • 浅谈iOS开发中static变量的三大作用

    (1)先来介绍它的第一条也是最重要的一条:隐藏 当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性.为理解这句话,我举例来说明.我们要同时编译两个源文件,一个是a.c,另一个是main.c. 下面是a.c的内容 char a = 'A'; // global variable void msg() { printf("Hello\n"); } 下面是main.c的内容 int main(void) { extern char a; // extern v

  • 浅谈Go语言中的结构体struct & 接口Interface & 反射

    结构体struct struct 用来自定义复杂数据结构,可以包含多个字段(属性),可以嵌套: go中的struct类型理解为类,可以定义方法,和函数定义有些许区别: struct类型是值类型. struct定义 type User struct { Name string Age int32 mess string } var user User var user1 *User = &User{} var user2 *User = new(User) struct使用 下面示例中user1和

  • 浅谈pyhton学习中出现的各种问题(新手必看)

    目前比较杂乱无章,后续还会有一些添加补充 1.标识符 (1)标识符是区分大小写的. (2)标示符以字母或下划线开头,可包括字母,下划线和数字. (3)以下划线开头的标识符是有特殊意义的. 2.参数前加星号(*)的意义 面对实际情况时无法提前得知要传入的参数的个数,因此在参数前加星号从而允许函数接受任意多的参数,情况如下: (1)参数前加一个星号(*),传入的参数存储为元组的形式: (2)参数前加两个星号(*),传入的参数存储为字典的形式,并且调用时采用例如'a=1,b=2,c=3'的形式. 3.

随机推荐