JDBC连接池

Posted 编程学习之美

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDBC连接池相关的知识,希望对你有一定的参考价值。

一、认识JDBC连接池

1. 概念其实就是一个容器(集合),存放数据库连接的容器。

当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归还给容器。

2. 实现

1. 标准接口:DataSource   javax.sql包下的方法:

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

2. 通过数据库厂商来实现

1. C3P0:数据库连接池技术

2. Druid:数据库连接池实现技术,这里主要介绍Druid技术,是比较受欢迎的一个技术,也是国内的阿里巴巴开发的。

二、Druid技术

1.入门级实现步骤

1. 导入jar包 druid-1.0.9.jar

2. 定义配置文件:druid.propertise

3. 加载配置文件。Properties

4. 获取数据库连接池对象:通过工厂来来获取  DruidDataSourceFactory

5. 获取连接:getConnection

实例代码:

package jdbc02;import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource;import java.io.IOException;import java.io.InputStream;import java.sql.Connection;import java.util.Properties;/**Dirud演示,数据库连接池实现技术,由阿里巴巴提供的 * 概念:其实就是一个容器(集合),存放数据库连接的容器。 * 当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后, * 会将连接对象归还给容器。 * @author zouguang * @create 2019-07-20 17:41 */public class DirudDemo { public static void main(String[] args) throws Exception { //1.导入Jar包 //2.定义配置文件druid.properties //3.加载配置文件 Properties pro = new Properties(); InputStream is = DirudDemo.class.getClassLoader().getResourceAsStream("druid.properties"); pro.load(is); //4.获取连接池对象        DataSource dataSource = DruidDataSourceFactory.createDataSource(pro); //5.获取连接 Connection connection = dataSource.getConnection(); System.out.println(connection); }}

2.合成一个工具类

通过工具类Jdbcutils来进行JDBC连接,不用再繁琐的进行一些重复的步骤。在工具类中提供方法获取连接。

druid.properties配置文件代码:一般是放在src目录下,需要修改数据库,只需修改配置文件即可,而不需要对代码进行修改。

driverClassName=com.mysql.cj.jdbc.Driverurl=jdbc:mysql://127.0.0.1:3306/db3?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT&useSSL=falseusername=rootpassword=zou131412121# 初始时连接数目initialSize=5# 最大连接数目maxActive=10# 超时等待时间maxWait=3000

Jdbcutils工具类具体实现:

package utils;import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource;import java.io.IOException;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import java.util.Properties;/**Druid连接池的工具类 * @author zouguang * @create 2019-07-20 19:02 */public class JdbcUtils2 { //1.定义成员变量DataSource    private static DataSource ds; static { Properties pro = new Properties(); try { pro.load(JdbcUtils2.class.getClassLoader().getResourceAsStream("druid.properties")); ds = DruidDataSourceFactory.createDataSource(pro); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); }    } /** * 获取链接 */ public static Connection getconnection() throws SQLException { return ds.getConnection();     } /** * 释放资源 */ public static void close(Statement stat,Connection conn){ if (stat != null) { try { stat.close(); } catch (SQLException e) { e.printStackTrace(); }          } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } }
}
public static void close(ResultSet rs,Statement stat, Connection conn){ if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } }        close(stat,conn);    } /** * 获取连接池的方法 */ public static DataSource getDataSource(){ return ds;     }}
释放资源重写了close方法,一个三个参数,一个两个参数,针对不同的查询,传入不同的参数。执行DQL语句返回的是一个ResultSet集合。此时就需要传入三个参数。
ResultSet executeQuery(String sql) :执行DQL(select)语句
同时,可以省去两个参数方法中的代码,直接在两个参数的close方法中调用三个参数的,第一个参数传null即可。也可像上述工具类的代码操作。
close(null,stat,conn)
静态代码块的作用是提前把配置文件加载好,创建好数据库连接对象。

三、Spring JDBC

Spring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发

1、简单的使用步骤:

步骤:

1. 导入jar包,导入jar包如下图:

2. 创建JdbcTemplate对象。依赖于数据源DataSource

JdbcTemplate template = new JdbcTemplate(ds);

3. 调用JdbcTemplate的方法来完成CRUD的操作

update():执行DML语句。增、删、改语句
queryForMap():查询结果将结果集封装为map集合,将列名作为key,将值作为value 将这条记录封装为一个map集合

* 注意:这个方法查询的结果集长度只能是1

queryForList():查询结果将结果集封装为list集合

* 注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中

query():查询结果,将结果封装为JavaBean对象query的参数:RowMapper

* 一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装,这个方法用得比较多,直接封装成对象,方便。

new BeanPropertyRowMapper<类型>(类型.class)
* queryForObject:查询结果,将结果封装为对象

* 这个一般用于聚合函数的查询

2、简单使用:

package JdbcTemplate;import Bean.Emp;import org.junit.Test;import org.springframework.jdbc.core.BeanPropertyRowMapper;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.jdbc.core.RowMapper;import utils.JdbcUtils2;import java.sql.Date;import java.sql.ResultSet;import java.sql.SQLException;import java.util.List;import java.util.Map;/*** 需求: 1. 修改1号数据的 salary 为 10000 2. 添加一条记录 3. 删除刚才添加的记录 4. 查询id为1的记录,将其封装为Map集合 5. 查询所有记录,将其封装为List 6. 查询所有记录,将其封装为Emp对象的List集合 7. 查询总记录数 * @author zouguang * @create 2019-07-20 23:02 */public class demo2 { //1. 修改1号数据的 salary 为 10000 JdbcTemplate template = new JdbcTemplate(JdbcUtils2.getDataSource()); @Test public void test1(){
String sql = "update emp set salary = 10000 where id = 1001"; int count = template.update(sql); System.out.println(count);    } //2. 添加一条记录 @Test public void test2(){
String sql = "insert into emp(id,ename,dept_id) values (?,?,?)"; int count = template.update(sql,1015,"郭靖",10); System.out.println(count); } //3. 删除刚才添加的记录 @Test public void test3(){
String sql = "delete from emp where id = ?"; int count = template.update(sql,1015); System.out.println(count); } //4. 查询id为1001的记录,将其封装为Map集合 // 这个方法查询的结果集长度只能为1 @Test public void test4(){ String sql = "select * from emp where id = ?"; Map<String, Object> map = template.queryForMap(sql, 1001); System.out.println(map); //{id=1001, ename=孙悟空, job_id=4, mgr=1004, joindate=2000-12-17, salary=10000.00, bonus=null, dept_id=20}    } //5. 查询所有记录,将其封装为List @Test public void test5(){ String sql = "select * from emp"; List<Map<String, Object>> list = template.queryForList(sql); for (Map<String, Object> map : list) { System.out.println(map); }    } //6. 查询所有记录,将其封装为Emp对象的List集合 @Test public void test6(){ String sql = "select * from emp"; List<Emp> list = template.query(sql, new RowMapper<Emp>() { @Override public Emp mapRow(ResultSet resultSet, int i) throws SQLException { Emp emp = new Emp(); int id = resultSet.getInt("id"); String ename = resultSet.getString("ename"); int job_id = resultSet.getInt("job_id"); int mgr = resultSet.getInt("mgr"); Date joindate = resultSet.getDate("joindate"); double salary = resultSet.getDouble("salary"); double bonus = resultSet.getDouble("bonus"); int dept_id = resultSet.getInt("dept_id");
emp.setId(id); emp.setEname(ename); emp.setJob_id(job_id); emp.setMgr(mgr); emp.setJoindate(joindate); emp.setSalary(salary); emp.setBonus(bonus); emp.setDept_id(dept_id);

return emp; } });
for (Emp emp : list) { System.out.println(emp); } } //6. 查询所有记录,将其封装为Emp对象的List集合 @Test public void test6_2(){ String sql = "select * from emp"; List<Emp> list = template.query(sql, new BeanPropertyRowMapper<Emp>(Emp.class)); for (Emp emp : list) { System.out.println(emp); }    } // 7. 查询总记录数 @Test public void test7(){ String sql = "select count(id) from emp"; Long total = template.queryForObject(sql, Long.class); //因为这个count聚合函数返回的是一个Long型 // 第二个参数需要返回结果的class对象 System.out.println(total);    }}

以上数据基于db3数据库的emp表。使用这个JdbcTemplate大大简化了对数据库的操作。









以上是关于JDBC连接池的主要内容,如果未能解决你的问题,请参考以下文章

JDBC自定义连接池

数据库连接池的Java连接池

JDBC 连接池错误

MySQL 和 JDBC 连接池:未关闭的语句

用Java手动封装JDBC连接池

哪个更好:JDBC 连接池,还是使用 SIngleton 类进行 JDBC 连接?