JDBC
一、JDBC简介
1、概念:
JDBC就是使用Java语言操作关系型数据库的一套API
全称:(Java DataBase Connectivity)Java数据库连接
2、本质:
为了使得Java代码可以适用于所有关系型数据库,Java提供了一套标准接口JDBC
而对应的关系型数据库提供其具体的实现类(即驱动jar包)
我们就可以使用这套接口(JDBC)编程,真正执行的代码时驱动jar包中的实现类
3、好处:
各数据库厂商使用相同的接口,Java代码不需要针对不同数库分别开发
可以随时替换底层数据库,访问数据库的Java代码基本不变
二、JDBC快速入门
步骤:
0、创建工程,导入驱动jar包
在需要的模块下创建一个目录new -> Directory
将对应的驱动jar包放进去
将jar包设置为库文件 Add as Library...
选择影响范围:
Global Library : 全局有效
Project Library : 项目有效
Module Library : 模块有效
1、注册驱动
2、获得连接
3、定义SQl语句
4、获取执行SQL对象
5、执行SQL
6、处理返回结果
7、释放资源
参考代码:
package com.itheima;
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.Statement;
/*
JDBC快速入门
*/
public class jdbcJDBCDemo {
public static void main(String[] args) throws Exception{
//1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2、获取连接
//IP端口数据库、用户名、密码
String url = "jdbc:mysql://127.0.0.1:3306/db1";
String username = "root";
String password = "123456"; -- 此处为你自己的密码
Connection conn = DriverManager.getConnection(url, username, password);
//3、定义sql语句
String sql = "UPDATE account SET money = 2000 WHERE id = 1;";
//4、获取执行sql的对象Statement
Statement stmt = conn.createStatement();
//5、执行sql
//返回结果为受影响的行数
int count = stmt.executeUpdate(sql); //返回结果为此sql语句影响的行数
//6、处理结果
System.out.println(count);
//7、释放资源
stmt.close();
conn.close();
}
}
三、JDBC API详解
1、DriverManager(类)用于注册驱动与连接数据库:
1、概述:
DriverManager(驱动管理类)作用:
注册驱动
获取数据库连接
DriverManager下的方法:
getConnection() 尝试于数据库建立连接
registerDriver() 注册驱动
2、注册驱动:
但是我们使用的注册驱动语句为:
Class.forName("com.mysql.jdbc.Driver"); //通过此方法将com.mysql.jdbc包下的Driver进行调用
查看Driver类的源代码:
package com.mysql.jdbc;
import java.sql.DriverManager;
import java.sql.SQLException;
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
public Driver() throws SQLException {
}
static {
try { //可以发现会在此处自动运行注册驱动的方法
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
}
注意:在jar驱动包下META-INF -> services -> java.sql.Driver中有"com.mysql.jdbc.Driver"这个字符串可以自动进行调用所以注册驱动语句可以省略
2、获取连接:
getConnection方法:
static Connection getConnection(String url, String user, String password);
参数说明:
url:连接路径
语法:jdbc:mysql://IP地址(域名):端口号/数据库名称?参数键值对1&参数键值对2...
示例:jdbc:mysql://127.0.0.1:3306/db1
细节:如果连接的是本机mysql服务器,并且mysql服务器默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称?参数键值对
配置:useSSL=false 参数,禁用安全连接方式,解决警告提示
参考代码:
注意:添加useSSL=false 去除安全提示,之前一定要先进行有一次安全提示的运行,否则就会报错
package com.itheima;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
/*
JDBC API 详解:DriverManager
*/
public class jdbcJDBCDemo2 {
public static void main(String[] args) throws Exception{
// Class.forName("com.mysql.jdbc.Driver");
//2、获取连接
//如果使用的连接的是本机的mysql并且端口是默认的3306 可以简化 书写
// String url = "jdbc:mysql://127.0.0.1:3306/db1";
String url = "jdbc:mysql:///db1?useSSL=false"; //添加useSSL=false 去除安全提示
String username = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url, username, password);
//3、定义sql语句
String sql = "UPDATE account SET money = 2000 WHERE id = 1;";
//4、获取执行sql的对象Statement
Statement stmt = conn.createStatement();
//5、执行sql
//返回结果为受影响的行数
int count = stmt.executeUpdate(sql);
//6、处理结果
System.out.println(count);
//7、释放资源
stmt.close();
conn.close();
}
}
user:用户名
passwrod:密码
2、Connection(接口)用于执行SQL对象和管理事务:
1、概述:
Connection(数据库连接对象)作用:
获取执行SQL对象
管理事务
2、获取执行SQL的对象(后面会具体提及前两个):
注:接口中的方法默认都有修饰符 abstract public 可以省略
普通执行SQL对象
Statement createStatement();
预编译SQL的执行SQL对象:防止SQL注入
PreparedStatement prepareStatement(sql);
执行存储过程的对象
CallableStatement prepareCall(sql);
3、事务管理:
MySQL事务管理
-- 开启事务
BEGIN; -- 或者使用 START TRANSACTION;
-- 提交事务
COMMIT;
-- 回滚事务
ROLLBACK;
-- MySQL默认自动提交事务
JDBC 事务管理:Connection接口中定义了3个对应的方法
//开启事务
setAutoCommit(boolean autoCommit); //true为自动提交事务;false为手动提交事务,同时开启事务
//提交事务
commit();
//回滚事务
rollback();
参考代码:
package com.itheima;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/*
JDBC快速入门
*/
public class jdbcJDBCDemo3_Connection {
public static void main(String[] args) throws Exception{
// //1、注册驱动
// Class.forName("com.mysql.jdbc.Driver"); //从源码中我们可以得知Driver在前面这个包下
//2、获取连接
String url = "jdbc:mysql:///db1?useSSL=false";
String username = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url, username, password);
//3、定义sql语句
String sql1 = "UPDATE account SET money = 3000 WHERE id = 1;";
String sql2 = "UPDATE account SET money = 3000 WHERE id = 2;";
//4、获取执行sql的对象Statement
Statement stmt = conn.createStatement();
try {
// !!开启事务
conn.setAutoCommit(false);
//执行sql
//返回结果为受影响的行数
int count1 = stmt.executeUpdate(sql1);
//处理结果
System.out.println(count1);
// int i = 3 / 0; 用于制造异常,可以看到只要报错所有操作回滚不执行
//执行sql
//返回结果为受影响的行数
int count2 = stmt.executeUpdate(sql2);
//处理结果
System.out.println(count2);
} catch (Exception e) {
//回滚事务
conn.rollback();
e.printStackTrace();
}
// !!提交事务
conn.commit();
//7、释放资源
stmt.close();
conn.close();
}
}
3、Statement(接口)用于执行SQL语句:
1、概述:
Statement作用:
执行SQL语句
2、执行SQL语句(此处先讲解前一个方法)
注:
DDL:数据定义语言,用来定义数据库对象(操作库、表、字段)
DML:数据操作语言,用来对数据库表中的数据进行增删改
DQL:数据查询语言,用来查询数据库中表的记录
int executeUpdate(sql); //执行DML、DDL语句
//返回值:对DML是这条语句影响的行数(所以可以使用是否为0判断) DDL语句执行后,“执行成功”也可能返回0
ResultSet executeQuery(sql); //执行DQL语句
//返回值:Resultset结果的集合对象
参考代码:
package com.itheima;
import jdk.jfr.StackTrace;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
/*
JDBC API 详解:Statement
*/
public class jdbcJDBCDemo4_Statement {
/**
* 执行DML语句
* @throws Exception
*/
@Test //使用快捷键 Alt + Enter 可以快速添加JUnit4依赖库
public void testDML() throws Exception{
//1、注册驱动
//Class.forName("com.mysql.jdbc.Driver");
//2、获取连接
String url = "jdbc:mysql:///db1?useSSL=false"; //添加useSSL=false 去除安全提示
String username = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url, username, password);
//3、定义sql语句
String sql = "UPDATE account SET money = 3000 WHERE id = 1;";
//4、获取执行sql的对象Statement
Statement stmt = conn.createStatement();
//5、执行sql
//返回结果为受影响的行数
int count = stmt.executeUpdate(sql); //执行完DML语句,受影响的行数
//6、处理结果
// System.out.println(count);
//通过返回值是否影响到了行,来返回给使用者信息
if(count > 0){
System.out.println("修改成功~");
}
else{
System.out.println("修改失败~");
}
//7、释放资源
stmt.close();
conn.close();
}
/**
* 执行DDL语句
* @throws Exception
*/
@Test //使用快捷键 Alt + Enter 可以快速添加JUnit4依赖库
public void testDDL() throws Exception{
//1、注册驱动
//Class.forName("com.mysql.jdbc.Driver");
//2、获取连接
String url = "jdbc:mysql:///db1?useSSL=false"; //添加useSSL=false 去除安全提示
String username = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url, username, password);
//3、定义sql语句
String sql = "drop database if exists db2";
//4、获取执行sql的对象Statement
Statement stmt = conn.createStatement();
//5、执行sql
//返回结果为受影响的行数
int count = stmt.executeUpdate(sql); //执行完DDL语句,有更改也可能返回0
//6、处理结果
System.out.println(count);
//无法再根据是否为0判断是否修改成功,所以不能用这个(基本不报错就ok)
// if(count > 0){
// System.out.println("修改成功~");
// }
// else{
// System.out.println("修改失败~");
// }
//7、释放资源
stmt.close();
conn.close();
}
}
4、ResultSet(接口)用于查询语句的结果:
1、概述:
ResultSet(结果集对象)作用:
封装了DQL查询语句的结果
ResultSet stmt.executeQuery(sql); //执行DQL语句,返回Result对象
2、获取查询结果
boolean next(); //1、将光标(类似于指针)从当前位置向前移动一行 2、判断当前行是否为有效行
/*
返回值
true:有效行,当前行有数据
false:无效行,当前行没有数据
*/
xxx getXxx(参数); //获取数据
/*
xxx:数据类型; 如:int getInt(参数); String getString(参数);
参数:
int:列的编号,从1开始
String:列的名称
*/
3、使用步骤:
游标向下移动一行,并判断改行是否有数据:next()
获取数据:getXxx(参数)
//写法格式
while(rs.next){
//获取数据
rs.getXxx(参数);
}
参考代码:
package com.itheima;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
/*
JDBC API 详解:Statement
*/
public class jdbcJDBCDemo4_ResultSet {
/**
* 执行DQL查询语句
* @throws Exception
*/
@Test //使用快捷键 Alt + Enter 可以快速添加JUnit4依赖库
public void testResult() throws Exception{
//1、注册驱动
//Class.forName("com.mysql.jdbc.Driver");
//2、获取连接
String url = "jdbc:mysql:///db1?useSSL=false"; //添加useSSL=false 去除安全提示
String username = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url, username, password);
//3、定义sql
String sql = "select * from account";
//4、获取Statement对象
Statement stmt = conn.createStatement();
//5、执行sql
ResultSet rs = stmt.executeQuery(sql);
//6、处理结果
/* //6.1 光标向下移动一行,并且判断当前行是否有数据
while(rs.next()){
//6.2 获取数据 getXxx() 此处参数使用列数注意从1开始
int id = rs.getInt(1);
String name = rs.getString(2);
double money = rs.getDouble(3);
System.out.print(id + "\t");
System.out.print(name + "\t");
System.out.println(money);
System.out.println("--------------------");
}
//7、释放资源
rs.close();
stmt.close();
conn.close();
*/
//6.1 光标向下移动一行,并且判断当前行是否有数据
while(rs.next()){
//6.2 获取数据 getXxx() 此处参数使用列名
int id = rs.getInt("id");
String name = rs.getString("name");
double money = rs.getDouble("money");
System.out.print(id + "\t");
System.out.print(name + "\t");
System.out.println(money);
System.out.println("--------------------");
}
//7、释放资源
rs.close();
stmt.close();
conn.close();
}
}
4、ResultSet案例:
需求:查询account账户表数据,封装到Account对象中,并存储到ArrayList集合中
package com.itheima;
public class Account {
private int id;
private String name;
private double money;
public void setId(int id){
this.id = id;
}
public int getId(){
return this.id;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
public void setMoney(double money){
this.money = money;
}
public double getMoney(){
return this.money;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", name='" + name + '\'' +
", money=" + money +
'}';
}
}
/**
* 实现案例
* @throws Exception
*/
@Test //使用快捷键 Alt + Enter 可以快速添加JUnit4依赖库
public void testResult2() throws Exception{
//1、注册驱动
//Class.forName("com.mysql.jdbc.Driver");
//2、获取连接
String url = "jdbc:mysql:///db1?useSSL=false"; //添加useSSL=false 去除安全提示
String username = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url, username, password);
//3、定义sql
String sql = "select * from account";
//4、获取Statement对象
Statement stmt = conn.createStatement();
//5、执行sql
ResultSet rs = stmt.executeQuery(sql);
//6、定义ArrayList对象
ArrayList<Account> arrayList = new ArrayList<Account>();
//7、处理结果
//7.1 光标向下移动一行,并且判断当前行是否有数据
while(rs.next()){
Account account = new Account();
//7.2 获取数据 getXxx() 此处参数使用列名
int id = rs.getInt("id");
String name = rs.getString("name");
double money = rs.getDouble("money");
//7.3 将数据放到类中并添加到集合
account.setId(id);
account.setName(name);
account.setMoney(money);
arrayList.add(account);
}
//8、遍历集合查看数据
for(int i = 0; i < arrayList.size(); i++){
System.out.println(arrayList.get(i)); //重写了toString
}
//9、释放资源
rs.close();
stmt.close();
conn.close();
}
5、PreparedStatement(接口)对sql语句进行预编译,提高执行效率;防止sql注入问题:
1、概述:
PrepareStatement作用:
预编译SQL语句并执行:预防SQL注入问题
2、SQL:
SQL注入是通过操作输入来修改事先定义好的SQL语句,用以达到执行代码对服务器进行攻击的方法。
3、SQL注入演示:
需求:完成用户登录
SELECT * FROM tb_user WHERE username = 'zhangsan' AND PASSWORD = '123';
参考代码:
package com.itheima;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
/*
用户登录
*/
public class jdbcJDBCDemo6_UserLogin {
@Test //使用快捷键 Alt + Enter 可以快速添加JUnit4依赖库
public void testLogin() throws Exception{
//获取连接
String url = "jdbc:mysql:///db1?useSSL=false"; //添加useSSL=false 去除安全提示
String username = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url, username, password);
//接收用户输入用户名和密码
String name = "zhangsan";
String pwd = "shogosgs";
//'+变量+' 写法可以在字符串中嵌套
String sql = "select * from tb_user where username = '"+name+"' and password = '"+pwd+"'";
//获取stmt对象
Statement stmt = conn.createStatement();
//执行sql
ResultSet rs = stmt.executeQuery(sql);
//判断登录是否成功
if(rs.next()){
System.out.println("登录成功~");
}
else{
System.out.println("登录失败~");
}
//释放资源
rs.close();
stmt.close();
conn.close();
}
/**
* 演示SQL注入
* @throws Exception
*/
@Test //使用快捷键 Alt + Enter 可以快速添加JUnit4依赖库
public void testLogin_Inject() throws Exception{
//获取连接
String url = "jdbc:mysql:///db1?useSSL=false"; //添加useSSL=false 去除安全提示
String username = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url, username, password);
//接收用户输入用户名和密码
String name = "sognsng";
String pwd = "' or '1' = '1";
//'+变量+' 写法可以在字符串中嵌套
String sql = "select * from tb_user where username = '"+name+"' and password = '"+pwd+"'";
System.out.println(sql);
//获取stmt对象
Statement stmt = conn.createStatement();
//执行sql
ResultSet rs = stmt.executeQuery(sql);
//判断登录是否成功
if(rs.next()){
System.out.println("登录成功~");
}
else{
System.out.println("登录失败~");
}
//释放资源
rs.close();
stmt.close();
conn.close();
}
}
4、解决SQL注入的问题
PreparedStatement预编译SQL并执行SQL语句
获取PreparedStatement对象:
//SQl语句中的参数值,使用?占位符替代
String sql = "select *from user where usename = ? and password = ?";
//通过Connection对象获取,并传入对应的sql语句
PrepareStatement pstmt = conn.prepareStatement(sql);
设置参数:
PrepareStatement对象:setXxx(参数1, 参数2): 给 ? 赋值
//Xxx:数据类型;如setInt(参数1, 参数2)
/*
参数:
参数1:? 的位置编号,从1开始
参数2:? 的值
*/
执行sql:
executeUpdate(); //或者 executeQuery; 注意:不需要再传递sql
参考代码:
package com.itheima;
import org.junit.Test;
import java.sql.*;
/*
API详解:PreparedStatement
*/
public class jdbcJDBCDemo7_PreparedStatement {
@Test //使用快捷键 Alt + Enter 可以快速添加JUnit4依赖库
public void testPreparedStatement() throws Exception{
//获取连接
String url = "jdbc:mysql:///db1?useSSL=false"; //添加useSSL=false 去除安全提示
String username = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url, username, password);
//接收用户输入用户名和密码
String name = "zhangsan";
String pwd = "' or '1' = '1";
//定义sql
String sql = "select * from tb_user where username = ? and password = ?";
//获取pstmt对象
PreparedStatement pstmt = conn.prepareStatement(sql);
//设置 ? 的值
pstmt.setString(1, name);
pstmt.setString(2, pwd);
//执行sql
ResultSet rs = pstmt.executeQuery();
//判断登录是否成功
if(rs.next()){
System.out.println("登录成功~");
}
else{
System.out.println("登录失败~");
}
//释放资源
rs.close();
pstmt.close();
conn.close();
}
}
5、PreparedStatement原理:
好处:
预编译SQL,性能更高
防止SQL注入:将敏感字符进行转义
预编译开启:
userServerPrepStmts=true
配置MySQL执行日志(重启mysql服务后生效):
注意:
如果在安装路径中找不到my.ini,估计是被隐藏了,先打开文件查看中的显示隐藏文件
再路径搜索中输入:%ProgramData%
然后找到MySQL->MySQL Server
若是无法添加进去,就在文件属性中设置一下文件的安全的编辑权限
-- 找不到mysql的my.ini文件,可能会是隐藏的
log-output=FILE
general-log=1
general_log_file="D:\mysql.log"
slow-query-log=1
slow_query_log_file="D:\mysql_slow.log"
long_query_time=2
-- 添加好后需要重启MySQL 再运行程序就可以在对应盘符目录中看到变化
PreparedStatement原理:
在获取PreparedStatement对象时,将sql语句发送给mysql服务器进行检查,编译(这些步骤很耗时,所以先进行后面执行时就不用在进行了)
执行时就不用再进行这些步骤了,速度更快
如果sql模板一样,则只需要进行一次检查、编译
参考代码:
/**
* PreparedStatement原理
* @throws Exception
*/
@Test //使用快捷键 Alt + Enter 可以快速添加JUnit4依赖库
public void testPreparedStatement2() throws Exception{
//获取连接
//注意重启MySQL后运行报错,可能是useSSL=false不是第二次运行,需要先开启一次再使用
String url = "jdbc:mysql:///db1?useSSL=false&useServerPrepStmts=true"; //添加useSSL=false 去除安全提示
String username = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url, username, password);
//接收用户输入用户名和密码
String name = "zhangsan";
String pwd = "' or '1' = '1";
//定义sql
String sql = "select * from tb_user where username = ? and password = ?";
//获取pstmt对象
PreparedStatement pstmt = conn.prepareStatement(sql);
//设置 ? 的值
pstmt.setString(1, name);
pstmt.setString(2, pwd);
ResultSet rs = null;
//执行sql
rs = pstmt.executeQuery();
//再次设置 ? 的值 看看预编译执行了几次
pstmt.setString(1, name);
pstmt.setString(2, pwd);
//再次执行sql
rs = pstmt.executeQuery();
//判断登录是否成功
if(rs.next()){
System.out.println("登录成功~");
}
else{
System.out.println("登录失败~");
}
//释放资源
rs.close();
pstmt.close();
conn.close();
}
可以看到预编译只执行了一次
2022-11-19T09:28:30.434501Z 22 Prepare select * from tb_user where username = ? and password = ?
2022-11-19T09:28:30.435456Z 22 Execute select * from tb_user where username = 'zhangsan' and password = '\' or \'1\' = \'1'
2022-11-19T09:28:30.436096Z 22 Execute select * from tb_user where username = 'zhangsan' and password = '\' or \'1\' = \'1'
四、数据库连接池
将多个数据库连接放到一个集合中,用户使用就拿出去,不使用就放回来以便下一个用户继续快速使用。
(如果不这样就会使用->释放->再次使用->再次释放...)
1、数据库连接池简介:
数据库连接池是一个容器,负责分配、管理数据库连接(Connection)
它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个
释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗留
好处:
资源重用
提升系统影响速度
避免数据库连接遗漏(会合理分配连接)
2、数据库连接池的实现:
标准接口:DataSource
官方(SUN)提供的数据库连接池标准接口,由第三方组织实现此接口
功能:获取连接
Connection getConnection(); //获取连接池对象
常见的数据库连接池:
DBCP
C3P0
Druid
Druid(德鲁伊):
Druid连接池是阿里巴巴开源的数据库连接池项目
功能强大,性能优秀,是Java语言最好的数据库连接池之一
2、Druid数据库连接池:
使用步骤:
导入jar包
定义配置文件
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///db1?useSSL=false&useServerPrepStmts=true
username=root
password=200241
# 初始化连接数量
initialSize=5
# 最大连接数
maxActive=10
# 最大等待时间
maxWait=3000
加载配置文件
获取数据库连接池对象
获取连接
参考代码:
package com.itheima.druid;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.util.Properties;
/*
Druid数据池连接演示
*/
public class DruidDemo {
public static void main(String[] args) throws Exception {
//1、导入jar包
//2、定义配置文件
//3、加载配置文件
Properties prop = new Properties();
prop.load(new FileInputStream("jdbc-demo/src/druid.properties"));
//4、获取连接池对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
//5、获取对应数据库连接 Connection
Connection connection = dataSource.getConnection();
System.out.println(connection);
// System.out.println(System.getProperty("user.dir")); //获取当前代码路径
}
}
druid配置详解
属性 | 说明 | 建议值 |
---|---|---|
url | 数据库的jdbc连接地址。一般为连接oracle/mysql。示例如下: | |
mysql : jdbc:mysql://ip:port/dbname?option1&option2&… | ||
oracle : jdbc:oracle:thin:@ip:port:oracle_sid | ||
username | 登录数据库的用户名 | |
password | 登录数据库的用户密码 | |
initialSize | 启动程序时,在连接池中初始化多少个连接 | 10-50已足够 |
maxActive | 连接池中最多支持多少个活动会话 | |
maxWait | 程序向连接池中请求连接时,超过maxWait的值后,认为本次请求失败,即连接池 | 100 |
没有可用连接,单位毫秒,设置-1时表示无限等待 | ||
minEvictableIdleTimeMillis | 池中某个连接的空闲时长达到 N 毫秒后, 连接池在下次检查空闲连接时,将 | 见说明部分 |
回收该连接,要小于防火墙超时设置 | ||
net.netfilter.nf_conntrack_tcp_timeout_established的设置 | ||
timeBetweenEvictionRunsMillis | 检查空闲连接的频率,单位毫秒, 非正整数时表示不进行检查 | |
keepAlive | 程序没有close连接且空闲时长超过 minEvictableIdleTimeMillis,则会执 | true |
行validationQuery指定的SQL,以保证该程序连接不会池kill掉,其范围不超 | ||
过minIdle指定的连接个数。 | ||
minIdle | 回收空闲连接时,将保证至少有minIdle个连接. | 与initialSize相同 |
removeAbandoned | 要求程序从池中get到连接后, N 秒后必须close,否则druid 会强制回收该 | false,当发现程序有未 |
连接,不管该连接中是活动还是空闲, 以防止进程不会进行close而霸占连接。 | 正常close连接时设置为true | |
removeAbandonedTimeout | 设置druid 强制回收连接的时限,当程序从池中get到连接开始算起,超过此 | 应大于业务运行最长时间 |
值后,druid将强制回收该连接,单位秒。 | ||
logAbandoned | 当druid强制回收连接后,是否将stack trace 记录到日志中 | true |
testWhileIdle | 当程序请求连接,池在分配连接时,是否先检查该连接是否有效。(高效) | true |
validationQuery | 检查池中的连接是否仍可用的 SQL 语句,drui会连接到数据库执行该SQL, 如果 | |
正常返回,则表示连接可用,否则表示连接不可用 | ||
testOnBorrow | 程序 申请 连接时,进行连接有效性检查(低效,影响性能) | false |
testOnReturn | 程序 返还 连接时,进行连接有效性检查(低效,影响性能) | false |
poolPreparedStatements | 缓存通过以下两个方法发起的SQL: | true |
public PreparedStatement prepareStatement(String sql) | ||
public PreparedStatement prepareStatement(String sql, | ||
int resultSetType, int resultSetConcurrency) | ||
maxPoolPrepareStatementPerConnectionSize | 每个连接最多缓存多少个SQL | 20 |
filters | 这里配置的是插件,常用的插件有: | stat,wall,slf4j |
监控统计: filter:stat | ||
日志监控: filter:log4j 或者 slf4j | ||
防御SQL注入: filter:wall | ||
connectProperties | 连接属性。比如设置一些连接池统计方面的配置。 | |
druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 | ||
比如设置一些数据库连接属性: | ||