1、 数据库频繁连接的问题
JDBC技术操作数据库,每次和数据库连接成功,执行SQL语句,释放资源。数据库的连接过程比较消耗资源,消耗的是网络资源,和数据库连接都是TCP协议的,Java程序要和数据库进行三次握手才能确定连接成功。
大数据高并发时代,频繁的连接数据库,必然导致我们开发的软件在运行速度上会变慢。用户体验会非常的差。必须解决数据库频繁连接的问题,提供我们软件运行速度。
2 、数据库连接池的原理
数据库连接池:解决频繁连接带来的性能问题和网络资源消耗问题。
数据库连接池,数据库连接对象的缓冲池。实现原理就是将数据库的连接对象存储在一个容器中(池pool),需要操作数据库,就从池中取出连接对象来使用,数据库操作完成,要将连接对象放回到连接池中。连接对象永远不会被销毁,可以反复的使用,达到提供连接效率的问题。
3、Data Source接口
开发中必须要使用连接池,但是我们自己开发连接池很不现实。需要使用第三方的连接池技术。
常见的连接池:德鲁伊连接池,Apache的连接池DBCP,C3P0
连接池产品众多,我们开发人员选择用哪个连接池呢?
如果连接池不统一标准,开发人员将无法切换连接池!!
连接池的技术标准也必须要统一:Sun公司定义了连接池的标准接口:
java
javax.sql包下的接口
/**
是所有连接池标准
连接池就必须实现此接口
接口的名字是数据源,就是连接池
*/
public interface DataSource{
Connection getConnection();// 返回数据库的连接对象
}
任何一个连接池,都必须实现接口:
javax.sql.DataSource
重写方法getConnection()
4、德鲁伊连接池的使用
阿里巴巴的德鲁伊连接池:DruidDataSource类实现了Sun公司的接口DataSource
- 德鲁伊连接池的配置参数
参数配置 | 参数说明 |
---|---|
driverClassName | 数据库的驱动类 |
url | 数据库服务器的连接地址 |
username | 连接数据库的用户名 |
password | 连接数据库的密码 |
initalSize | 连接池中初始化的连接个数 |
maxIdIe | 连接池中最大的连接个数 |
使用德鲁伊连接池,必须要添加jar包!
- 自定义德鲁伊连接池工具类
java
/**
创建静态方法,返回数据库的连接对象
数据库的连接对象,交给德鲁伊连接池管理
从池中取出连接来使用
*/
public static Connection getConnection(){
// 创建连接池接口DataSource的实现类对象
DruidDataSource dataSource=new DruidDataSource();
// 配置数据库的驱动类,dataSource对象的set方法设置
DruidDataSource dataSource=new DruidDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); //数据库驱动类
dataSource.setUrl("jdbc:mysql://localhost:3306/school");
dataSource.setUsername("root"); //连接数据库的用户名
dataSource.setUsername("renyanlei115"); // 连接数据库的密码
dataSource.setInitialSize(10); // 连接池中,初始化的连接个数
dataSource.setMaxActive(20); //连接池中,最大的连接个数
// 调用对象的方法 getConnection()获取数据库连接对象
return dataSource.getConnection();
}
// 测试代码
public static void main(){
Connection con=getConnection();
System.out.println("con="+con);
con.close();
}
- 德鲁伊连接池(properties)
java
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/school
username=root
password=renyanlei115
initialSize=10
maxActive=20
-
配置文件中的键名称不能乱写,因为德鲁伊连接池中的键是固定的。
-
优化后的德鲁伊连接池工具
java
package com.rocky.utils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class DruidJDBCUtils {
static DataSource dataSource;
static {
//1 :加载配置文件
InputStream resourceAsStream =
DruidJDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
Properties properties = new Properties();
try {
properties.load(resourceAsStream);
// druid提供了一个工厂方法来生成dataSource对象
dataSource = DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static DataSource getDataSource(){
return dataSource;
}
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
/**
* 凡是使用了连接池的JDBC技术,执行Connection对象的close()方法,不是关闭连接,而是回收到连接池中
*
*/
public static void close(ResultSet resultSet, Statement statement,Connection connection) throws SQLException {
if(resultSet!=null){
resultSet.close();
}
if(statement!=null){
statement.close();
}
if(connection!=null){
connection.close();
}
}
}
数据库连接池中的资源释放问题(连接对象使用完毕要归还连接池)
连接池中使用动态代理技术(改变方法的功能),close()方法的作用就是归还连接池
5、使用连接池使用数据表的查询功能
java
package com.rocky.view;
import com.rocky.utils.DataSourceUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class DataSourceTest {
public static void main(String[] args) throws SQLException {
Connection connection=null;
PreparedStatement preparedStatement=null;
ResultSet resultSet=null;
try {
//德鲁伊连接池工具类,获得数据库的连接对象
connection= DataSourceUtils.getConnection();
//拼写SQL语句
String sql="select * from userinfo";
//sql语句中,没有问号,没有占位符,不需要设置参数
preparedStatement=connection.prepareStatement(sql);
resultSet=preparedStatement.executeQuery();
while (resultSet.next()){
int id=resultSet.getInt("id");
String name=resultSet.getNString("name");
String password=resultSet.getString("password");
System.out.println("id="+id+"name="+name+"password="+password);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}finally {
DataSourceUtils.close(resultSet,preparedStatement,connection);
}
}
}