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生成的连接,组织到连接池中,然后从池中提供连接。
Data Source就是DriverManager的一种替代角色,对外呈现就类似于一个DriverManager,拥有对外提供连接的能力。
直接使用DriverManager,驱动程序与管理器是“服务者—管理者”的形式,借助于管理者才能提供服务。而Data Source将驱动程序的概念淡化了,突出驱动程序能够提供的服务与能力,将驱动程序提供的服务与能力抽象为Data Source数据源这一角色。
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的一个实现类,作为中间层使用,并且基本上都提供了附带的其他的服务,也就是说不仅仅实现了核心建筑,也基于核心之上构建了很多的外围建设。