一、什么是 JDBC?

1、定义:

一套JDBC接口代码能同时操作所有的关系型数据库,真正执行的是驱动jar包。

Java database connectivity 即java数据库连接,可以理解为java语言操作数据库,对数据库进行增删改查。

数据库有多种,如mysql、oracle、DB2、SQLServer,我们期望实现一套java代码能同时操作所有的关系型数据库

sun公司定义接口,数据库厂商提供实现类(数据库驱动)。

JDBC的本质:官方定义的一套操作所有关系型数据库的规则(即接口),各个数据库厂商去实现这套接口,提供数据库驱动jar包,我们可以使用这套JDBC接口编程真正执行的代码是驱动jar包中的实现类中的实现方法。(类似于多态)

这一套接口就可以操作不同的数据库,sun公司仅仅定义了接口,如果你想用java语言操作mysql,mysql数据库厂商写一个实现类,即每一个数据库厂商都写一个不同的实现类来操作不同的数据库。每一个实现类都实现了相同的JDBC接口,将来我们在写代码的时候,只需要调用接口,具体的实现类由不同的公司实现的,不用我们写实现类。我们给实现类起名为数据库驱动

2、使用 JDBC 的好处

1) 程序员如果要开发访问数据库的程序,只需要会调用 JDBC 接口中的方法即可,不用关注类是如何实现的。

2) 使用同一套 Java 代码,进行少量的修改就可以访问其他 JDBC 支持的数据库

JDBC与连接池-冯金伟博客园

二、JDBC 访问数据库的步骤

JDBC与连接池-冯金伟博客园

1) 注册和加载驱动(可以省略)

2) 获取连接

3) Connection 获取 Statement 对象

4) 使用 Statement 对象执行 SQL 语句后得到结果集

5) 返回结果集

6) 释放资源

JDBC快速入门:

 JDBC与连接池-冯金伟博客园

步骤:

1、导入驱动jar包:复制mysql-connector-java-5.1.37-bin.jarjar包中放的是class文件)到项目的libs目录下,libs目录右键,选择Add as library,这样jar包才会真正加入到项目中

2、 将实现类(Driver)加载进内存,Driver类中的静态代码块自动执行,从而实现注册驱动,真正注册驱动的是DriverManager。

JDBC与连接池-冯金伟博客园

Class.forName(全类名”)方法将字节码文件加载进内存,返回类对象

mysql-connector-java 5之后的jar包,加载Driver类进内存的代码Class.forName()可以省略不写,即没有间接注册驱动,程序也能正常运行,因为mysql-connector-java-5.1.37-bin.jar包下的META-INF目录下的services目录下的java.sql.Driver文件中把Driver的全类名写进来了,这样如果你没有注册驱动,可以自动注册驱动

JDBC与连接池-冯金伟博客园

 JDBC与连接池-冯金伟博客园

建议将来写代码的时候不要省略,因为mysql-connector-java 5之前的驱动包就不能使用这些代码了,即不能向下兼容

3、 获取数据库连接对象Connection。(这个对象是java代码与数据库间的桥梁对象)

jdbc:mysql://ip地址或域名:端口/数据库名称

如果连接的是本机的mysql服务器,并且mysql服务的默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称

4、 定义sql语句,然后把sql发送给数据库,数据库就会执行sql语句,从而达到java代码操作数据库的要求求。

5、 Connection对象创建执行sql语句的对象statement

6、 statement执行sql,接收返回的结果集

7、 处理结果集

JDBC与连接池-冯金伟博客园

8、 释放资源,否则会造成内存的泄露。

三、数据库连接池

1、为什么使用连接池?

之前每一个类都需要获取一个连接,用完之后就释放了,每一次都这样。但是获取连接的操作是向操作系统申请资源,而申请资源是非常耗时的操作,如果连接用完就释放,导致我们的程序会比较慢,下面学习连接池来解决性能比较低,资源浪费的情况

现在,用户在访问数据库时,在系统初始化之后和用户访问之前,创建了一个容器,并在容器中申请了很多的连接对象装在容器中,当程序访问数据库的时候,不会向系统底层申请连接了,而是从容器中获取一个连接对象,从而去访问数据库,访问完了之后,不会把连接释放掉,而是把连接对象归还给容器。这样做的好处是:节约了系统资源,访问的速度快了,连接对象被复用,

数据库连接池:其实就是一个存放数据库连接的容器(集合)。

2、数据库连接池_实现介绍

Javax.sql.DataSource接口就是连接池,DataSource对象是获取连接的首选方法,由驱动程序供应商实现DataSource接口,即谁提供数据库的驱动谁去实现DataSource。

数据库连接池的实现类:

C3P0框架DataSource实现类是com.mchange.v2.c3p0.ComboPooledDataSource

MyBatis框架DataSource类是org.apache.ibatis.datasource.pooled.PooledDataSource

Druid框架DataSource类是com.alibaba.druid.pool.DruidDataSource

Druid由阿里巴巴提供,号称全球最好的数据库连接池技术

ComboPooledDataSource和类DruidDataSource都实现了DataSource接口, 

获取连接DataSource接口有Connection getConnection()方法

归还连接Connection.close()。如果连接对象Connection是从连接池中获取的,那么调用Connection.close()方法,则不会关闭连接了,而是归还连接。连接池把close()方法给增强了

3、druid连接池

导入依赖

<!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--数据库连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>${druid.version}</version>
        </dependency>

数据库配置:

#数据库
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:mysql://ip:3306/zwh?serverTimezone=Hongkong&useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true
spring.datasource.username=root
spring.datasource.password=root

4、Mybatis连接池的分类

JDBC与连接池-冯金伟博客园

 JDBC与连接池-冯金伟博客园

Mybatis内部分别定义了实现java.sql.DataSource接口的UnpooledDataSource、PooledDataSource类来分别表示UNPOOLEDPOOLED类型的数据源。

1)、POOLED:采用传统的javax.sql.DataSource规范中的连接池,mybatis中有针对规范的实现。每次都是从连接池中获取连接

 JDBC与连接池-冯金伟博客园JDBC与连接池-冯金伟博客园

 JDBC与连接池-冯金伟博客园

 JDBC与连接池-冯金伟博客园

如果空闲连接idleConnections(是一个ArrayList集合)不为空,表示还有空闲连接,就从集合中拿出一个连接来用;如果没有空闲连接,并且活跃的连接activeConnection(是一个ArrayList集合)数小于连接池的最大活跃连接数poolMaximumActiveConnection,则创建一个连接,如果没有空闲连接,并且活跃的连接activeConnections数大于等于连接池的最大活跃连接数,则从活跃的连接集合activeConnections中取出第一个连接(最先进入activeConnections的连接)oldestActiveConnection来给我们用。

2)、UNPOOLED:采用传统的获取连接的方式,虽然也实现了Javax.sql.DataSource接口,但是并没有使用池的思想。每次使用都是重新获取连接

 JDBC与连接池-冯金伟博客园

3)、JNDI:采用服务器提供的JNDI技术实现,来获取DataSource对象,不同的服务器所能拿到的DataSource是不一样的,注意,如果不是web或maven的war工程是不能使用的。我们使用的是tomcat服务器,采用的连接池就是DBCP连接池

实际开发中用POOLED,即用池的思想来管理连接。

5、springboot2.0默认连接池

 Springboot2.0以后默认数据库连接池选择了Hikari(性能高)

项目启动时,如果控制台打印如下:

JDBC与连接池-冯金伟博客园

说明使用了springboot默认的连接池。

性能方面 hikariCP>druid>tomcat-jdbc>dbcp>c3p0,hikariCP的高性能得益于最大限度的避免锁竞争。

配置默认数据库连接池(Hikari)

步骤一:起步依赖

<!--jdbc起步依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- mysql数据库驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

步骤二:数据库连接信息配置

# jdbc_config   datasource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/datebook?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull
spring.datasource.username=root
spring.datasource.password=root
# Hikari will use the above plus the following to setup connection pooling
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.maximum-pool-size=15
spring.datasource.hikari.auto-commit=true
spring.datasource.hikari.idle-timeout=30000
spring.datasource.hikari.pool-name=DatebookHikariCP
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.connection-test-query=SELECT 1

hikariCP连接池常用配置:

5、autoCommit
此属性控制从池返回的连接的默认自动提交行为。它是一个布尔值。 默认值:true

6、 connectionTimeout
此属性控制客户端(即您)将等待来自池的连接的最大毫秒数。如果在没有可用连接的情况下超过此时间,则会抛出SQLException。最低可接受的连接超时时间为250 ms。 默认值:30000(30秒)

7、 idleTimeout
此属性控制允许连接在池中闲置的最长时间。 此设置仅适用于minimumIdle定义为小于maximumPoolSize。一旦池达到连接,空闲连接将不会退出minimumIdle。连接是否因闲置而退出,最大变化量为+30秒,平均变化量为+15秒。在超时之前,连接永远不会退出。值为0意味着空闲连接永远不会从池中删除。允许的最小值是10000ms(10秒)。 默认值:600000(10分钟)

8、 maxLifetime
此属性控制池中连接的最大生存期。正在使用的连接永远不会退休,只有在关闭后才会被删除。在逐个连接的基础上,应用较小的负面衰减来避免池中的大量消失。 我们强烈建议设置此值,并且应该比任何数据库或基础设施规定的连接时间限制短几秒。 值为0表示没有最大寿命(无限寿命),当然是idleTimeout设定的主题。 默认值:1800000(30分钟)

9、connectionTestQuery
如果您的驱动程序支持JDBC4,我们强烈建议您不要设置此属性。这是针对不支持JDBC4的“传统”驱动程序Connection.isValid() API。这是在连接从池中获得连接以确认与数据库的连接仍然存在之前将要执行的查询。再一次,尝试运行没有此属性的池,如果您的驱动程序不符合JDBC4的要求,HikariCP将记录一个错误以告知您。 默认值:无

10、minimumIdle
该属性控制HikariCP尝试在池中维护的最小空闲连接数。如果空闲连接低于此值并且连接池中的总连接数少于此值maximumPoolSize,则HikariCP将尽最大努力快速高效地添加其他连接。但是,为了获得最佳性能和响应尖峰需求,我们建议不要设置此值,而是允许HikariCP充当固定大小的连接池。 默认值:与maximumPoolSize相同

11、maximumPoolSize
此属性控制池允许达到的最大大小,包括空闲和正在使用的连接。基本上这个值将决定到数据库后端的最大实际连接数。对此的合理价值最好由您的执行环境决定。当池达到此大小并且没有空闲连接可用时,对getConnection()的调用将connectionTimeout在超时前阻塞达几毫秒。请阅读关于游泳池尺寸。 默认值:10

12、metricRegistry
该属性仅通过编程配置或IoC容器可用。该属性允许您指定池使用的Codahale / Dropwizard 实例MetricRegistry来记录各种指标。有关 详细信息,请参阅Metrics维基页面。 默认值:无

13、healthCheckRegistry
该属性仅通过编程配置或IoC容器可用。该属性允许您指定池使用的Codahale / Dropwizard 的实例HealthCheckRegistry来报告当前的健康信息。有关 详细信息,请参阅健康检查 wiki页面。 默认值:无

14、poolName
此属性表示连接池的用户定义名称,主要出现在日志记录和JMX管理控制台中以识别池和池配置。 默认:自动生成

15、 initializationFailTimeout
如果池无法成功初始化连接,则此属性控制池是否将“快速失败”。任何正数都取为尝试获取初始连接的毫秒数; 应用程序线程将在此期间被阻止。如果在超时发生之前无法获取连接,则会引发异常。此超时被应用后的connectionTimeout 期。如果值为零(0),HikariCP将尝试获取并验证连接。如果获得连接但未通过验证,将抛出异常并且池未启动。但是,如果无法获得连接,则会启动该池,但后续获取连接的操作可能会失败。小于零的值将绕过任何初始连接尝试,并且在尝试获取后台连接时,池将立即启动。因此,以后努力获得连接可能会失败。 默认值:1

16、isolateInternalQueries
此属性确定HikariCP是否在其自己的事务中隔离内部池查询,例如连接活动测试。由于这些通常是只读查询,因此很少有必要将它们封装在自己的事务中。该属性仅适用于autoCommit禁用的情况。 默认值:false

17、allowPoolSuspension
该属性控制池是否可以通过JMX暂停和恢复。这对于某些故障转移自动化方案很有用。当池被暂停时,呼叫 getConnection()将不会超时,并将一直保持到池恢复为止。 默认值:false

18、readOnly
此属性控制默认情况下从池中获取的连接是否处于只读模式。注意某些数据库不支持只读模式的概念,而其他数据库则在Connection设置为只读时提供查询优化。无论您是否需要此属性,都将主要取决于您的应用程序和数据库。 默认值:false

19、registerMbeans
该属性控制是否注册JMX管理Bean(“MBeans”)。 默认值:false

20、catalog
该属性设置默认目录为支持目录的概念数据库。如果未指定此属性,则使用由JDBC驱动程序定义的默认目录。 默认:驱动程序默认

21、connectionInitSql
该属性设置一个SQL语句,在将每个新连接创建后,将其添加到池中之前执行该语句。如果这个SQL无效或引发异常,它将被视为连接失败并且将遵循标准重试逻辑。 默认值:无

22、driverClassName
HikariCP将尝试通过DriverManager仅基于驱动程序来解析驱动程序jdbcUrl,但对于一些较旧的驱动程序,driverClassName还必须指定它。除非您收到明显的错误消息,指出找不到驱动程序,否则请忽略此属性。 默认值:无

23、transactionIsolation
此属性控制从池返回的连接的默认事务隔离级别。如果未指定此属性,则使用由JDBC驱动程序定义的默认事务隔离级别。如果您有针对所有查询通用的特定隔离要求,请仅使用此属性。此属性的值是从不断的名称Connection 类,如TRANSACTION_READ_COMMITTED,TRANSACTION_REPEATABLE_READ等 默认值:驱动程序默认

24、 validationTimeout
此属性控制连接测试活动的最长时间。这个值必须小于connectionTimeout。最低可接受的验证超时时间为250 ms。 默认值:5000

25、 leakDetectionThreshold
此属性控制在记录消息之前连接可能离开池的时间量,表明可能存在连接泄漏。值为0意味着泄漏检测被禁用。启用泄漏检测的最低可接受值为2000(2秒)。 默认值:0

26、 dataSource
此属性仅通过编程配置或IoC容器可用。这个属性允许你直接设置DataSource池的实例,而不是让HikariCP通过反射来构造它。这在一些依赖注入框架中可能很有用。当指定此属性时,dataSourceClassName属性和所有DataSource特定的属性将被忽略。 默认值:无

27、schema
该属性设置的默认模式为支持模式的概念数据库。如果未指定此属性,则使用由JDBC驱动程序定义的默认模式。 默认:驱动程序默认

28、 threadFactory
此属性仅通过编程配置或IoC容器可用。该属性允许您设置java.util.concurrent.ThreadFactory将用于创建池使用的所有线程的实例。在一些只能通过ThreadFactory应用程序容器提供的线程创建线程的有限执行环境中需要它。 默认值:无

29、 scheduledExecutor
此属性仅通过编程配置或IoC容器可用。该属性允许您设置java.util.concurrent.ScheduledExecutorService将用于各种内部计划任务的实例。如果为ScheduledThreadPoolExecutor 实例提供HikariCP,建议setRemoveOnCancelPolicy(true)使用它。 默认值:无