Data Source与数据库连接池简介

DataSource是作为DriverManager的替代品而推出的,DataSource 对象是获取连接的首选方法。

为何放弃DriverManager

DriverManager负责管理驱动程序,并且使用已注册的驱动程序进行连接。

//1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
//数据库连接所需参数
String username = "***";
String password = "***";
String url = "jdbc:mysql://localhost:3306/sampledb?useUnicode=true&characterEncoding=utf-8";
//2、获取连接对象
Connection conn = DriverManager.getConnection(url, user, password);

使用DriverManager的一般形式如上面代码所示。

直接使用DriverManager的这种形式,通常需要将驱动程序硬编码到项目中。而且最重要的是:DriverManager的getConnection方法获取的连接,是建立与数据库的连接。而建立与数据库的连接是一项较耗资源的工作,频繁的进行数据库连接建立操作会产生较大的系统开销。

随着企业级应用复杂度的提升以及对性能要求的提高,这一点是难以接受的。

连接池

既然每次使用时都重新建立与数据库之间的连接,会产生较大的系统开销。是否可以事先创建一些连接备用,当需要时,从这些连接中选择一个提供出去;当连接使用完毕后,并不是真正的关闭,而是将这些数据状态还原,然后继续等待下一个人使用?

比如滑雪场会租赁雪具滑雪服等,如果你不是资深玩家,你没有必要浪费钱买,即使你不差钱,每次去滑雪场都不能轻装上阵,每次都要携带很多装备,也是一件麻烦事。

这种没必要的花费或者麻烦其实都是一种开销。

连接池的核心与租用的理念有类似的点,重复使用可以提高连接的利用率,减少开销(当然连接池的使用并不需要你花费一笔租金)。

连接的持有是消耗空间的,但是现在绝大多数场景下,磁盘空间并没有那么金贵,我们更关心的是性能,所以空间换取时间,连接池的逻辑被广泛应用。

数据源

DriverManager只是建立与数据库之间的连接,如何才能将连接池的概念应用其中?

一种很自然的方式就是提供一个薄层的封装,建立一个中间层,这个中间层将DriverManager生成的连接,组织到连接池中,然后从池中提供连接。

Aqua Data Studio 连接 MYSQL datasource连接数据库_bc

Data Source就是DriverManager的一种替代角色,对外呈现就类似于一个DriverManager,拥有对外提供连接的能力。

直接使用DriverManager,驱动程序与管理器是“服务者—管理者”的形式,借助于管理者才能提供服务。而Data Source将驱动程序的概念淡化了,突出驱动程序能够提供的服务与能力,将驱动程序提供的服务与能力抽象为Data Source数据源这一角色。

Aqua Data Studio 连接 MYSQL datasource连接数据库_java_02

DataSource中获取的连接来自于连接池中,而池中的连接根本也还是从DriverManager获取而来。

有了数据源这一中间层,就可以实现连接池和分布式事务的管理。

对外呈现DataSource就是类似于DriverManager的一个存在。

DataSource的形式是JNDI (Java Naming Directory Interface)

DataSource是JNDI资源的一种,那么到底什么是JNDI呢?

可以简单认为JNDI是类似这样一个东西:

  • 一个哈希表,类型为<String,Object>
  • JNDI的两个最主要操作:bind和lookup。bind操作负责往哈希表里存对象,lookup则根据这个键值字符串往外取对象。
  • 开发人员可以使用键值——也就是一个字符串名称——来获取某个对象。

简言之就是JNDI可以给一个对象命名,然后可以通过名称找到这个对象。

数据源的概念在应用程序与数据库连接之间插入了一个中间层,进而可以实现连接池以及事务管理,并且以JNDI的形式,也能够以非常方便的形式使用。

Druid

数据源推荐使用alibaba的Druid:http://druid.io/

maven中央仓库: http://central.maven.org/maven2/com/alibaba/druid/

Druid是一个开源项目,源码托管在github上,源代码仓库地址是 https://github.com/alibaba/druid。

Wiki首页:
https://github.com/alibaba/druid/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98

与其他主流对比:https://github.com/alibaba/druid/wiki/%E5%90%84%E7%A7%8D%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5%E6%B1%A0%E5%AF%B9%E6%AF%94

在Spring中配置数据源

properties配置文件 jdbc.properties

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/dbname?useSSL=false
jdbc.username=root
jdbc.password=root

数据源配置类 JdbcConfig.java

public class JdbcConfig {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;

    @Bean
    public DataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driver);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);

        return dataSource;
    }
}

在Spring配置类 SpringConfig.java 中加载

@Configuration
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class})
public class SpringConfig {
}

总结

  • 数据源作为DriverManager的替代者,用于获取数据库连接,你应该总是使用DataSource
  • DataSource是应用程序与数据库连接的一个抽象的中间层,是一个接口
  • 对于DataSource已经有了很多优秀的实现,其中较为突出的为Druid,建议使用,Druid不仅仅提供了连接池的功能还提供了其他比如监控等功能,非常强大。

对于数据源的应用,除了用户名密码url还有其他的一些属性信息,比如最大连接数,建立连接的最大等待时间等,不同的连接池略微有出入,可以查看手册。

对于DataSource的一些实现,经常被叫做数据库连接池,比如Druid官方文档中说“Druid是Java语言中最好的数据库连接池“,本质核心就是DataSource的一个实现类,作为中间层使用,并且基本上都提供了附带的其他的服务,也就是说不仅仅实现了核心建筑,也基于核心之上构建了很多的外围建设。