本专栏将从基础开始,循序渐进,讲解数据库的基本概念以及使用,希望大家都能够从中有所收获,也请大家多多支持。
专栏地址: 数据库必知必会
相关软件地址:软件地址
如果文章知识点有错误的地方,请指正!大家一起学习,一起进步。
文章目录
1 自定义连接池
1.1 连接池概念
1.1.1 为什么要使用连接池
Connection对象在JDBC使用的时候就会去创建一个对象,使用结束以后就会将这个对象给销毁了(close),每次创建和销毁对象都是耗时操作,需要使用连接池对其进行优化.
程序初始化的时候,初始化多个连接,将多个连接放入到池(集合)中,每次获取的时候,都可以直接从连接池中进行获取,使用结束以后,将连接归还到池中。
1.1.2 生活里面的连接池例子
- 老方式: 下了地铁需要骑车, 跑去生产一个, 然后骑完之后,直接把车销毁了。
- 连接池方式 摩拜单车: 骑之前, 有一个公司生产了很多的自行车, 下了地铁需要骑车, 直接扫码使用就好了, 然后骑完之后, 还回去。
1.1.3 连接池原理
- 程序一开始就创建一定数量的连接,放在一个容器(集合)中,这个容器称为连接池。
- 使用的时候直接从连接池中取一个已经创建好的连接对象, 使用完成之后 归还到池子
- 如果池子里面的连接使用完了, 还有程序需要使用连接, 先等待一段时间(eg: 3s), 如果在这段时间之内有连接归还, 就拿去使用; 如果还没有连接归还, 新创建一个, 但是新创建的这一个不会归还了(销毁)
- 集合选择LinkedList - 增删比较快- LinkedList里面的removeFirst()和addLast()方法和连接池的原理吻合
使用连接池的目的: 可以让连接得到复用, 避免浪费
1.2 自定义连接池-初级版本
目标
根据连接池的原理, 使用LinkedList自定义连接池
分析
- 创建一个类MyDataSource, 定义一个集合LinkedList
- 程序初始化的时候, 创建5个连接 存到LinkedList
- 定义getConnection() 从LinkedList取出Connection返回
- 定义addBack()方法归还Connection到LinkedList
实现
- JDBCUtils.java
packagecom.hashnode.utils;importjava.io.FileInputStream;importjava.io.InputStream;importjava.sql.*;importjava.util.Properties;publicclassJDBCUtils{privatestaticString driver;privatestaticString url;privatestaticString user;privatestaticString password;static{try{// 使用Properties对象加载配置文件// 创建Properties对象Properties pro =newProperties();// 读取配置文件中的数据//pro.load(new FileInputStream("my-code\\src\\db.properties"));// 返回的输入流的路径默认到src路径InputStream is =JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
pro.load(is);// 通过pro对象给属性赋值
url = pro.getProperty("url");
user = pro.getProperty("username");
password = pro.getProperty("password");
driver = pro.getProperty("driver");// 1.加载驱动Class.forName(driver);}catch(Exception e){
e.printStackTrace();}}/**
* 获得连接
*
* @return 连接
* @throws Exception
*/publicstaticConnectiongetConnection()throwsException{// 2.获得连接Connection connection =DriverManager.getConnection(url, user, password);return connection;}/**
* 释放资源
*
* @param resultSet
* @param statement
* @param connection
*/publicstaticvoidrelease(ResultSet resultSet,Statement statement,Connection connection){if(resultSet !=null){try{
resultSet.close();}catch(SQLException e){
e.printStackTrace();}}if(statement !=null){try{
statement.close();}catch(SQLException e){
e.printStackTrace();}}if(connection !=null){try{
connection.close();}catch(SQLException e){
e.printStackTrace();}}}}
- MyDataSource1.java
packagecom.hashnode.datapool;importcom.hashnode.utils.JDBCUtils;importjava.sql.Connection;importjava.util.LinkedList;publicclassMyDataSource1{// 1.定义一个LinkedList集合,用来存储初始化的连接privatestaticLinkedList<Connection> list =newLinkedList<>();// 2.初始化5个连接,并存储到集合中static{for(int i =0; i <5; i++){try{// 获得连接Connection connection =JDBCUtils.getConnection();// 添加到集合中
list.add(connection);}catch(Exception e){
e.printStackTrace();}}}// 3.定义getAbc方法,用来获得连接publicConnectiongetAbc(){Connection connection = list.removeFirst();return connection;}// 4.定义addBack方法,用来归还连接publicvoidaddBack(Connection connection){
list.addLast(connection);}// 5.定义getCount方法,返回连接池中连接数量publicstaticintgetCount(){return list.size();}}
- CRUDTest1.java
packagecom.hashnode.datapool;importcom.hashnode.pojo.User;importcom.hashnode.utils.JDBCUtils;importorg.junit.Test;importjava.sql.Connection;importjava.sql.PreparedStatement;importjava.sql.ResultSet;// 测试publicclassCRUDTest1{// 查询记录@Testpublicvoidselect()throwsException{// 1.创建连接池对象MyDataSource1 dataSource =newMyDataSource1();System.out.println("获得连接之前,连接池中连接的数量:"+MyDataSource1.getCount());// 5// 2.获得连接Connection connection = dataSource.getAbc();// 2.书写sql语句,预编译sql语句,得到预编译对象String sql ="select * from user where id = ?";PreparedStatement ps = connection.prepareStatement(sql);// 3.设置参数
ps.setInt(1,3);// 4.执行sql语句ResultSet resultSet = ps.executeQuery();// 封装,处理数据User user =null;while(resultSet.next()){
user =newUser();
user.setId(resultSet.getInt("id"));
user.setUsername(resultSet.getString("username"));
user.setPassword(resultSet.getString("password"));
user.setNickname(resultSet.getString("nickname"));}System.out.println("获得连接之后,连接池中连接的数量:"+MyDataSource1.getCount());// 4System.out.println(user);// 5.释放资源// 归还连接
dataSource.addBack(connection);JDBCUtils.release(resultSet,ps,null);System.out.println("归还连接之后,连接池中连接的数量:"+MyDataSource1.getCount());// 5}}
小结
- 创建一个类MyDataSource, 定义一个集合LinkedList
- 程序初始化(静态代码块)里面 创建5个连接存到LinkedList
- 定义提供Connection的方法
- 定义归还Connection的方法
1.3 自定义连接池-进阶版本
目标
实现datasource完成自定义连接池
分析
在初级版本版本中, 我们定义的方法是getAbc(),因为是自定义的,如果改用李四的自定义的连接池,李四定义的方法是getCon(), 那么我们的源码就需要修改, 这样不方便维护,所以sun公司定义了一个接口DataSource,让自定义连接池有了规范。
1.3.1 datasource接口概述
Java为数据库连接池提供了公共的接口:javax.sql.DataSource,各个厂商(用户)需要让自己的连接池实现这个接口。这样应用程序可以方便的切换不同厂商的连接池!
1.3.2 代码实现
publicclassMyDataSource2implementsDataSource{// 1.定义一个LinkedList集合,用来存储初始化的连接privatestaticLinkedList<Connection> list =newLinkedList<>();// 2.初始化5个连接,并存储到集合中static{for(int i =0; i <5; i++){try{// 获得连接Connection connection =JDBCUtils.getConnection();// 添加到集合中
list.add(connection);}catch(Exception e){
e.printStackTrace();}}}/*// 3.定义getAbc方法,用来获得连接
public Connection getAbc(){
Connection connection = list.removeFirst();
return connection;
}*/// 4.定义addBack方法,用来归还连接publicvoidaddBack(Connection connection){
list.addLast(connection);}// 5.定义getCount方法,返回连接池中连接数量publicstaticintgetCount(){return list.size();}@OverridepublicConnectiongetConnection()throwsSQLException{Connection connection = list.removeFirst();return connection;}@OverridepublicConnectiongetConnection(String username,String password)throwsSQLException{returnnull;}@OverridepublicPrintWritergetLogWriter()throwsSQLException{returnnull;}@OverridepublicvoidsetLogWriter(PrintWriter out)throwsSQLException{}@OverridepublicvoidsetLoginTimeout(int seconds)throwsSQLException{}@OverridepublicintgetLoginTimeout()throwsSQLException{return0;}@OverridepublicLoggergetParentLogger()throwsSQLFeatureNotSupportedException{returnnull;}@Overridepublic<T>Tunwrap(Class<T> iface)throwsSQLException{returnnull;}@OverridepublicbooleanisWrapperFor(Class<?> iface)throwsSQLException{returnfalse;}}// 测试publicclassCRUDTest2{// 查询记录@Testpublicvoidselect()throwsException{// 1.创建连接池对象DataSource dataSource =newMyDataSource2();System.out.println("获得连接之前,连接池中连接的数量:"+MyDataSource2.getCount());// 5// 2.获得连接Connection connection = dataSource.getConnection();// 2.书写sql语句,预编译sql语句,得到预编译对象String sql ="select * from user where id = ?";PreparedStatement ps = connection.prepareStatement(sql);// 3.设置参数
ps.setInt(1,3);// 4.执行sql语句ResultSet resultSet = ps.executeQuery();// 封装,处理数据User user =null;while(resultSet.next()){
user =newUser();
user.setId(resultSet.getInt("id"));
user.setUsername(resultSet.getString("username"));
user.setPassword(resultSet.getString("password"));
user.setNickname(resultSet.getString("nickname"));}System.out.println("获得连接之后,连接池中连接的数量:"+MyDataSource2.getCount());// 4System.out.println(user);// 5.释放资源// 归还连接// 解决办法: 1.向下转型 2.增强Connection的close方法(默认是销毁连接,增强后变成归还连接)((MyDataSource2)dataSource).addBack(connection);JDBCUtils.release(resultSet,ps,null);System.out.println("归还连接之后,连接池中连接的数量:"+MyDataSource2.getCount());// 5}}
1.3.2 编写连接池遇到的问题
- 实现DataSource接口后,addBack()不能调用了。
- 能不能不引入新的api,直接调用之前的connection.close(),但是这个close不是关闭,是归还
解决办法
- 继承- 条件:可以控制父类, 最起码知道父类的名字
- 装饰者模式- 作用:改写已存在的类的某个方法或某些方法- 条件: - 增强类和被增强类实现的是同一个接口- 增强类里面要拿到被增强类的引用
- 动态代理
1.4 自定义连接池-终极版本
目标
使用装饰者模式改写connection的close()方法, 让connection归还
1.4.1 装饰者模式
1.4.1.1 概述
- 什么是装饰者模式 装饰者模式,是 23种常用的面向对象软件的设计模式之一, 动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更加有弹性的替代方案。 装饰者的作用:改写已存在的类的某个方法或某些方法, 增强方法的逻辑
- 使用装饰者模式需要满足的条件- 增强类和被增强类实现的是同一个接口- 增强类里面要拿到被增强类的引用
1.4.1.2 装饰者模式的使用
实现步骤:
- 增强类和被增强类需要实现同一个接口
- 增强类里面需要得到被增强类的引用,
- 对于不需要改写的方法,调用被增强类原有的方法。
- 对于需要改写的方法写自己的代码
- 接口:
publicinterfaceStar{publicvoidsing();publicvoiddance();}
- 被增强的类:
publicclassAAAimplementsStar{@Overridepublicvoidsing(){System.out.println("AAA is sing...");}@Overridepublicvoiddance(){System.out.println("AAA is dancing...");}}
- 增强的类:
publicclassAAAWrapperimplementsStar{// 增强类中获得被增强类的引用LiuDeHua ldh;publicLiuDeHuaWrapper(LiuDeHua ldh){this.ldh = ldh;}@Overridepublicvoidsing(){System.out.println("AAA is sing...");
ldh.sing();System.out.println("AAA is practicing...");}@Overridepublicvoiddance(){// 不增强
ldh.dance();}}
- 测试
publicclassTest{publicstaticvoidmain(String[] args){// 没有使用装饰者LiuDeHua ldh =newLiuDeHua();//ldh.sing();//ldh.dance();// 使用装饰者AAAWrapper ldhw =newLiuDeHuaWrapper(ldh); ldhw.sing(); ldhw.dance();}}
1.4.2 自定义连接池终极版本
1.4.2.1 分析
增强connection的close()方法, 其它的方法逻辑不改
- 创建MyConnection实现Connection
- 在MyConnection里面需要得到被增强的connection对象(通过构造方法传进去)
- 改写close()的逻辑, 变成归还
- 其它方法的逻辑, 还是调用被增强connection对象之前的逻辑
1.4.2.2 实现
- MyConnection
publicclassMyConnectionimplementsConnection{// 获得被增强的连接对象的引用Connection con;// 获得连接池LinkedList<Connection> list;publicMyConnection(Connection con,LinkedList<Connection> list){this.con = con;this.list = list;}@Overridepublicvoidclose()throwsSQLException{// 归还连接
list.addLast(con);}@OverridepublicStatementcreateStatement()throwsSQLException{return con.createStatement();}// 必须写@OverridepublicPreparedStatementprepareStatement(String sql)throwsSQLException{return con.prepareStatement(sql);}// 剩余的重写方法,使用被增强的连接对象调用原有方法...// ...}
- MyDataSource03
publicclassMyDataSource3implementsDataSource{// 1.定义一个LinkedList集合,用来存储初始化的连接privatestaticLinkedList<Connection> list =newLinkedList<>();// 2.初始化5个连接,并存储到集合中static{for(int i =0; i <5; i++){try{// 获得连接Connection connection =JDBCUtils.getConnection();// 添加到集合中
list.add(connection);}catch(Exception e){
e.printStackTrace();}}}/*// 3.定义getAbc方法,用来获得连接
public Connection getAbc(){
Connection connection = list.removeFirst();
return connection;
}*//*// 4.定义addBack方法,用来归还连接
public void addBack(Connection connection){
list.addLast(connection);
}*/// 5.定义getCount方法,返回连接池中连接数量publicstaticintgetCount(){return list.size();}@OverridepublicConnectiongetConnection()throwsSQLException{Connection connection = list.removeFirst();// 返回的是被增强的连接对象// 增强MyConnection myConnection =newMyConnection(connection,list);return myConnection;}@OverridepublicConnectiongetConnection(String username,String password)throwsSQLException{returnnull;}@OverridepublicPrintWritergetLogWriter()throwsSQLException{returnnull;}@OverridepublicvoidsetLogWriter(PrintWriter out)throwsSQLException{}@OverridepublicvoidsetLoginTimeout(int seconds)throwsSQLException{}@OverridepublicintgetLoginTimeout()throwsSQLException{return0;}@OverridepublicLoggergetParentLogger()throwsSQLFeatureNotSupportedException{returnnull;}@Overridepublic<T>Tunwrap(Class<T> iface)throwsSQLException{returnnull;}@OverridepublicbooleanisWrapperFor(Class<?> iface)throwsSQLException{returnfalse;}}
- JDBCUtils.java
packagecom.hashnode.utils;importjava.io.FileInputStream;importjava.io.InputStream;importjava.sql.*;importjava.util.Properties;publicclassJDBCUtils{privatestaticString driver;privatestaticString url;privatestaticString user;privatestaticString password;static{try{// 使用Properties对象加载配置文件// 创建Properties对象Properties pro =newProperties();// 读取配置文件中的数据//pro.load(new FileInputStream("my-code\\src\\db.properties"));// 返回的输入流的路径默认到src路径InputStream is =JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
pro.load(is);// 通过pro对象给属性赋值
url = pro.getProperty("url");
user = pro.getProperty("username");
password = pro.getProperty("password");
driver = pro.getProperty("driver");// 1.加载驱动Class.forName(driver);}catch(Exception e){
e.printStackTrace();}}/**
* 获得连接
*
* @return 连接
* @throws Exception
*/publicstaticConnectiongetConnection()throwsException{// 2.获得连接Connection connection =DriverManager.getConnection(url, user, password);return connection;}/**
* 释放资源
*
* @param resultSet
* @param statement
* @param connection
*/publicstaticvoidrelease(ResultSet resultSet,Statement statement,Connection connection){if(resultSet !=null){try{
resultSet.close();}catch(SQLException e){
e.printStackTrace();}}if(statement !=null){try{
statement.close();}catch(SQLException e){
e.printStackTrace();}}if(connection !=null){try{
connection.close();}catch(SQLException e){
e.printStackTrace();}}}}
- 测试类
publicclassCRUDTest3{// 查询记录@Testpublicvoidselect()throwsException{// 1.创建连接池对象DataSource dataSource =newMyDataSource3();System.out.println("获得连接之前,连接池中连接的数量:"+MyDataSource3.getCount());// 5// 2.获得连接Connection connection = dataSource.getConnection();// 返回的是增强的连接对象 MyConnection// 2.书写sql语句,预编译sql语句,得到预编译对象String sql ="select * from user where id = ?";PreparedStatement ps = connection.prepareStatement(sql);// 3.设置参数 ps.setInt(1,3);// 4.执行sql语句ResultSet resultSet = ps.executeQuery();// 封装,处理数据User user =null;while(resultSet.next()){ user =newUser(); user.setId(resultSet.getInt("id")); user.setUsername(resultSet.getString("username")); user.setPassword(resultSet.getString("password")); user.setNickname(resultSet.getString("nickname"));}System.out.println("获得连接之后,连接池中连接的数量:"+MyDataSource3.getCount());// 4System.out.println(user);// 5.释放资源// 归还连接//connection.close();// 归还连接JDBCUtils.release(resultSet,ps,connection);System.out.println("归还连接之后,连接池中连接的数量:"+MyDataSource3.getCount());// 5}}
小结
- 创建一个MyConnection实现Connection
- 在MyConnection得到被增强的connection对象
- 改写MyConnection里面的close()方法的逻辑为归还
- MyConnection里面的其它方法 调用被增强的connection对象之前的逻辑
- 在MyDataSource03的getConnection()方法里面返回了myConnection(增强的连接对象)(此时调用的是多态,即MyConnection中重写的close方法)
2 第三方连接池
2.1 常用连接池
通过前面的学习,我们已经能够使用所学的基础知识构建自定义的连接池了。其目的是锻炼大家的基本功,帮助大家更好的理解连接池的原理, 但现实是残酷的,我们所定义的 连接池 和第三方的连接池相比,还是显得渺小. 工作里面都会用第三方连接池.
常见的第三方连接池如下:
- C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。C3P0是异步操作的,所以一些操作时间过长的JDBC通过其它的辅助线程完成。目前使用它的开源项目有Hibernate,Spring等。C3P0有自动回收空闲连接功能
- 阿里巴巴-德鲁伊druid连接池:Druid是阿里巴巴开源平台上的一个项目,整个项目由数据库连接池、插件框架和SQL解析器组成。该项目主要是为了扩展JDBC的一些限制,可以让程序员实现一些特殊的需求。
- DBCP(DataBase Connection Pool)数据库连接池,是Apache上的一个Java连接池项目,也是Tomcat使用的连接池组件。dbcp没有自动回收空闲连接的功能。
我们工作里面用的比较多的是:
- C3P0
- druid
- 光连接池
2.2 C3P0
2.2.1 c3p0介绍
- C3P0是开源免费的连接池,目前使用它的开源项目有:Spring、Hibernate等。使用第三方工具需要导入jar包,c3p0使用时还需要添加配置文件c3p0-config.xml.
- 使用C3P0需要添加c3p0-0.9.1.2.jar
2.2.2 c3p0的使用
2.2.2.1 通过硬编码来编写
步骤
- 拷贝jar
- 创建C3P0连接池对象
- 从C3P0连接池对象里面获得connection
实现:
packagecom.hashnode.test;importcom.hashnode.pojo.User;importcom.hashnode.utils.JDBCUtils;importcom.mchange.v2.c3p0.ComboPooledDataSource;importjava.sql.Connection;importjava.sql.PreparedStatement;importjava.sql.ResultSet;publicclassC3P0Test1{publicstaticvoidmain(String[] args)throwsException{// 1.拷贝c3p0jar包到模块下,并添加到classpath路径中// 2.创建连接池对象ComboPooledDataSource dataSource =newComboPooledDataSource();// 连接池设置参数
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/hashnode");
dataSource.setUser("root");
dataSource.setPassword("root");// 设置初始化连接数量
dataSource.setInitialPoolSize(5);// 3.获得连接Connection connection = dataSource.getConnection();// 4.书写sql语句,预编译sql语句,得到预编译对象String sql ="select * from user where id = ?";PreparedStatement ps = connection.prepareStatement(sql);// 5.设置参数
ps.setInt(1,3);// 6.执行sql语句ResultSet resultSet = ps.executeQuery();// 封装,处理数据User user =null;while(resultSet.next()){
user =newUser();
user.setId(resultSet.getInt("id"));
user.setUsername(resultSet.getString("username"));
user.setPassword(resultSet.getString("password"));
user.setNickname(resultSet.getString("nickname"));}System.out.println(user);// 7.释放资源---连接归还JDBCUtils.release(resultSet,ps,connection);}}
2.2.2.2 通过配置文件来编写
步骤:
- 拷贝jar
- 拷贝配置文件(c3p0-config.xml)到src目录【名字不要改】
- 创建C3P0连接池对象【自动的读取】
- 从池子里面获得连接
实现:
- 编写配置文件c3p0-config.xml,放在src目录下(注:文件名一定不要改)
<c3p0-config><default-config><propertyname="driverClass">com.mysql.jdbc.Driver</property><propertyname="jdbcUrl">jdbc:mysql://localhost:3306/hashnode</property><propertyname="user">root</property><propertyname="password">root</property><propertyname="initialPoolSize">5</property></default-config></c3p0-config>
- 编写Java代码 (会自动读取src目录下的c3p0-config.xml,所以不需要我们解析配置文件)
publicclassTest2_通过配置文件来编写 {publicstaticvoidmain(String[] args)throwsException{// 1.拷贝c3p0jar包到模块下,并添加到classpath路径中// 2.创建连接池对象ComboPooledDataSource dataSource =newComboPooledDataSource();// 3.获得连接Connection connection = dataSource.getConnection();// 4.书写sql语句,预编译sql语句,得到预编译对象String sql ="select * from user where id = ?";PreparedStatement ps = connection.prepareStatement(sql);// 5.设置参数
ps.setInt(1,3);// 6.执行sql语句ResultSet resultSet = ps.executeQuery();// 封装,处理数据User user =null;while(resultSet.next()){
user =newUser();
user.setId(resultSet.getInt("id"));
user.setUsername(resultSet.getString("username"));
user.setPassword(resultSet.getString("password"));
user.setNickname(resultSet.getString("nickname"));}System.out.println(user);// 7.释放资源---连接归还JDBCUtils.release(resultSet,ps,connection);}}
2.2.2.3 使用c3p0改写工具类
我们之前写的工具类(JdbcUtils)每次都会创建一个新的连接, 使用完成之后, 都给销毁了; 所以现在我们要使用c3p0来改写工具类. 也就意味着,我们从此告别了JdbcUtils. 后面会使用c3p0写的工具类
思路:
- 创建C3P0Utils这个类
- 定义DataSource, 保证DataSource全局只有一个
- 定义getConnection()方法从DataSource获得连接
- 定义closeAll()方法 释放资源
packagecom.hashnode.utils;importcom.mchange.v2.c3p0.ComboPooledDataSource;importjavax.sql.DataSource;importjava.sql.Connection;importjava.sql.ResultSet;importjava.sql.SQLException;importjava.sql.Statement;publicclassC3P0Utils{// 创建c3p0连接池对象privatestaticfinalComboPooledDataSource DATA_SOURCE =newComboPooledDataSource();/**
* 获得连接的方法
* @return 连接
* @throws Exception
*/publicstaticConnectiongetConnection()throwsException{Connection connection = DATA_SOURCE.getConnection();return connection;}/**
* 获得连接池的方法
* @return
*/publicstaticDataSourcegetDataSource(){return DATA_SOURCE;}/**
* 释放资源
*
* @param resultSet
* @param statement
* @param connection
*/publicstaticvoidrelease(ResultSet resultSet,Statement statement,Connection connection){if(resultSet !=null){try{
resultSet.close();}catch(SQLException e){
e.printStackTrace();}}if(statement !=null){try{
statement.close();}catch(SQLException e){
e.printStackTrace();}}if(connection !=null){try{
connection.close();}catch(SQLException e){
e.printStackTrace();}}}}
- 使用
packagecom.hashnode.test;importcom.hashnode.pojo.User;importcom.hashnode.utils.JDBCUtils;importcom.mchange.v2.c3p0.ComboPooledDataSource;importjava.sql.Connection;importjava.sql.PreparedStatement;importjava.sql.ResultSet;publicclassC3P0Test2{publicstaticvoidmain(String[] args)throwsException{// 1.拷贝c3p0jar包到模块下,并添加到classpath路径中// 2.创建连接池对象ComboPooledDataSource dataSource =newComboPooledDataSource();// 3.获得连接Connection connection = dataSource.getConnection();// 4.书写sql语句,预编译sql语句,得到预编译对象String sql ="select * from user where id = ?";PreparedStatement ps = connection.prepareStatement(sql);// 5.设置参数
ps.setInt(1,3);// 6.执行sql语句ResultSet resultSet = ps.executeQuery();// 封装,处理数据User user =null;while(resultSet.next()){
user =newUser();
user.setId(resultSet.getInt("id"));
user.setUsername(resultSet.getString("username"));
user.setPassword(resultSet.getString("password"));
user.setNickname(resultSet.getString("nickname"));}System.out.println(user);// 7.释放资源---连接归还JDBCUtils.release(resultSet,ps,connection);}}
小结
- C3P0 配置文件方式使用- 拷贝jar- 拷贝配置文件到src【配置文件的名字不要改】- 创建C3P0连接池对象
- C3P0工具类- 保证DataSource连接池只有一个【static】- 提供connection- 释放资源
2.3 DRUID
2.3.1 DRUID介绍
Druid是阿里巴巴开发的号称为监控而生的数据库连接池,Druid是国内目前最好的数据库连接池。在功能、性能、扩展性方面,都超过其他数据库连接池。Druid已经在阿里巴巴部署了超过600个应用,经过一年多生产环境大规模部署的严苛考验。如:一年一度的双十一活动,每年春运的抢火车票。
Druid的下载地址:https://github.com/alibaba/druid
DRUID连接池使用的jar包:druid-1.0.9.jar
2.3.2 DRUID的使用
2.3.3 通过硬编码方式
步骤:
- 导入DRUID jar 包
- 创建Druid连接池对象, 配置4个基本参数
- 从Druid连接池对象获得Connection
实现:
packagecom.hashnode.test;importcom.alibaba.druid.pool.DruidDataSource;importcom.alibaba.druid.pool.DruidPooledConnection;importcom.hashnode.pojo.User;importcom.hashnode.utils.JDBCUtils;importorg.junit.Test;importjava.sql.PreparedStatement;importjava.sql.ResultSet;publicclassDruidTest1{@Testpublicvoidselect()throwsException{// 1.拷贝jar包,添加classpath路径// 2.创建Druid连接池对象DruidDataSource dataSource =newDruidDataSource();// 设置参数
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/hashnode");
dataSource.setUsername("root");
dataSource.setPassword("root");
dataSource.setInitialSize(5);// 3.获得连接DruidPooledConnection connection = dataSource.getConnection();// 4.书写sql语句,预编译sql语句,得到预编译对象String sql ="select * from user where id = ?";PreparedStatement ps = connection.prepareStatement(sql);// 5.设置参数
ps.setInt(1,3);// 6.执行sql语句ResultSet resultSet = ps.executeQuery();// 封装,处理数据User user =null;while(resultSet.next()){
user =newUser();
user.setId(resultSet.getInt("id"));
user.setUsername(resultSet.getString("username"));
user.setPassword(resultSet.getString("password"));
user.setNickname(resultSet.getString("nickname"));}System.out.println(user);// 7.释放资源---连接归还JDBCUtils.release(resultSet,ps,connection);}}
2.3.4 通过配置文件方式
步骤:
- 导入DRUID jar 包
- 拷贝配置文件到src目录
- 根据配置文件创建Druid连接池对象
- 从Druid连接池对象获得Connection
实现:
- 创建druid.properties, 放在src目录下
url=jdbc:mysql://localhost:3306/day21_1
username=root
password=root
driverClassName=com.mysql.jdbc.Driver
- 编写Java代码
packagecom.hashnode.test;importcom.alibaba.druid.pool.DruidDataSourceFactory;importcom.hashnode.pojo.User;importcom.hashnode.utils.JDBCUtils;importorg.junit.Test;importjavax.sql.DataSource;importjava.io.InputStream;importjava.sql.Connection;importjava.sql.PreparedStatement;importjava.sql.ResultSet;importjava.util.Properties;publicclassDruidTest2{@Testpublicvoidselect()throwsException{// 1.拷贝jar包,添加classpath路径// 2.创建Druid连接池对象Properties prop =newProperties();// 加载配置文件InputStream is =DruidTest2.class.getClassLoader().getResourceAsStream("druid.properties");
prop.load(is);// 创建Druid连接池对象DataSource dataSource =DruidDataSourceFactory.createDataSource(prop);// 3.获得连接Connection connection = dataSource.getConnection();// 4.书写sql语句,预编译sql语句,得到预编译对象String sql ="select * from user where id = ?";PreparedStatement ps = connection.prepareStatement(sql);// 5.设置参数
ps.setInt(1,3);// 6.执行sql语句ResultSet resultSet = ps.executeQuery();// 封装,处理数据User user =null;while(resultSet.next()){
user =newUser();
user.setId(resultSet.getInt("id"));
user.setUsername(resultSet.getString("username"));
user.setPassword(resultSet.getString("password"));
user.setNickname(resultSet.getString("nickname"));}System.out.println(user);// 7.释放资源---连接归还JDBCUtils.release(resultSet,ps,connection);}}
2.3.5 使用DruidUtils改写工具类
思路:
- 创建DruidUtils这个类
- 定义DruidDataSource, 保证DruidDataSource全局只有一个
- 定义getConnection()方法从DataSource获得连接
- 定义release()方法 释放资源
packagecom.hashnode.utils;importcom.alibaba.druid.pool.DruidDataSource;importjava.sql.Connection;importjava.sql.ResultSet;importjava.sql.SQLException;importjava.sql.Statement;publicclassDruidUtils{// 创建c3p0连接池对象privatestaticfinalDruidDataSource DATA_SOURCE =newDruidDataSource();static{// 设置参数
DATA_SOURCE.setDriverClassName("com.mysql.jdbc.Driver");
DATA_SOURCE.setUrl("jdbc:mysql://localhost:3306/hashnode");
DATA_SOURCE.setUsername("root");
DATA_SOURCE.setPassword("root");
DATA_SOURCE.setInitialSize(5);}/**
* 获得连接的方法
* @return 连接
* @throws Exception
*/publicstaticConnectiongetConnection()throwsException{Connection connection = DATA_SOURCE.getConnection();return connection;}/**
* 获得连接池的方法
* @return
*/publicstaticDruidDataSourcegetDataSource(){return DATA_SOURCE;}/**
* 释放资源
*
* @param resultSet
* @param statement
* @param connection
*/publicstaticvoidrelease(ResultSet resultSet,Statement statement,Connection connection){if(resultSet !=null){try{
resultSet.close();}catch(SQLException e){
e.printStackTrace();}}if(statement !=null){try{
statement.close();}catch(SQLException e){
e.printStackTrace();}}if(connection !=null){try{
connection.close();}catch(SQLException e){
e.printStackTrace();}}}}
- 使用
packagecom.hashnode.test;importcom.alibaba.druid.pool.DruidDataSourceFactory;importcom.hashnode.pojo.User;importcom.hashnode.utils.DruidUtils;importcom.hashnode.utils.JDBCUtils;importorg.junit.Test;importjavax.sql.DataSource;importjava.io.InputStream;importjava.sql.Connection;importjava.sql.PreparedStatement;importjava.sql.ResultSet;importjava.util.Properties;publicclassDruidTest3{@Testpublicvoidselect()throwsException{// 3.获得连接Connection connection =DruidUtils.getConnection();// 4.书写sql语句,预编译sql语句,得到预编译对象String sql ="select * from user where id = ?";PreparedStatement ps = connection.prepareStatement(sql);// 5.设置参数
ps.setInt(1,3);// 6.执行sql语句ResultSet resultSet = ps.executeQuery();// 封装,处理数据User user =null;while(resultSet.next()){
user =newUser();
user.setId(resultSet.getInt("id"));
user.setUsername(resultSet.getString("username"));
user.setPassword(resultSet.getString("password"));
user.setNickname(resultSet.getString("nickname"));}System.out.println(user);// 7.释放资源---连接归还DruidUtils.release(resultSet,ps,connection);}}
小结
- Druid配置文件使用 - 拷贝jar- 拷贝配置文件到src- 读取配置文件成properties对象- 使用工厂根据properties创建DataSource- 从DataSource获得Connection
版权归原作者 每天都要努力的小颓废呀 所有, 如有侵权,请联系我们删除。