数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用现有的N个(自定义)数据库连接,不用每次都再重新建立一个新的连接,以提高对数据库操作的性能。
常用开源的数据库连接池
C3P0
:是一个开放源代码的JDBC连接池,它在lib目录中与Hibernate [2] 一起发布,包括了实现jdbc3和jdbc2扩展规范说明的Connection 和Statement 池的DataSources 对象。Proxool
:是一个Java SQDriver驱动程序,提供了对选择的其它类型的驱动程序的连接池封装。可以非常简单的移植到现存的代码中,完全可配置,快速、成熟、健壮。可以透明地为现存的JDBC驱动程序增加连接池功能。Jakarta DBCP
:DBCP是一个依赖Jakartacommons-pool对象池机制的数据库连接池。DBCP可以直接的在应用程序中使用。DBPool
:是一个高效、易配置的数据库连接池。它除了支持连接池应有的功能之外,还包括了一个对象池,使用户能够开发一个满足自己需求的数据库连接池。SmartPool
:是一个连接池组件,它模仿应用服务器对象池的特性。SmartPool能够解决一些临界问题如连接泄漏(connection leaks)、连接阻塞、打开的JDBC对象(如Statements、PreparedStatements)等。Druid
连接池是阿里巴巴开源的数据库连接池项目。Druid连接池为监控而生,内置强大的监控功能,监控特性不影响性能。功能强大,能防SQL注入,内置Loging能诊断Hack应用行为。简单来说,数据库连接池就是在一开始先创建N多个数据库连接connection对象,存储在一个集合内,每次使用一个就从集合内取出一个,用完之后又添加到集合内,一直反复使用。
创建带有是否使用标记的Connection对象。自定义一个带有是否使用标记的Connection对象。
package com.pool;
import java.sql.Connection;
public class PooledConnection {
// 数据库连接
private Connection conn;
// 用于标识当前数据库连接的状态 true:执行 false:空闲
private boolean busy;
public PooledConnection(Connection conn) {
this.conn = conn;
}
public Connection getConn() {
return conn;
}
public void setConn(Connection conn) {
this.conn = conn;
}
public boolean isBusy() {
return busy;
}
public void setBusy(boolean busy) {
this.busy = busy;
}
}
创建数据库线程池对象
数据库线程池对象包含默认连接数、最大连接数、每次新增个数、超时时间和连接对象集合。
package com.star;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.*;
/**
* 连接池
*/
public class Poo{
// 初始化连接数
private static int initSize = 2;
// 池中最大连接数
private static int maxSize = 10;
// 每次创建的连接数
private static int stepSize = 2;
// 超时时间
private static int timeout = 2000;
// 用来保存创建的数据库连接
private static List<PoolCollection> poo= Collections.synchronizedList(new ArrayList<>());
//单例对象
private static Pooinstance;
/**
* 单利模式:无论什么时候只会有一个Pool对象
*/
private Pool() {
resizePool(initSize);
}
/**
* 单利模式:无论什么时候只会有一个Pool对象
*/
private Pool() {
resizePool(initSize);
}
/**
* 获取单例对象
*
* @return
*/
public static synchronized PoogetInstance() {
if (instance == null) {
instance = new Pool();
}
return instance;
}
/**
* 初始化连接池,循环使用池子里的连接对象,如果不够再创建num个,不超过最大数maxSize
*
* @param size 初始时按照initSize给池中添加连接,其他时候按照stepSize给池中加
*/
private void resizePool(int size) {
int current = pool.size();
if (current + size > maxSize) {
size = maxSize - current;
}
for (int i = 0; i < size; i++) {
pool.add(new PoolCollection(createConnection()));
}
}
}
获取连接
/**
* 创建连接
*
* @return
*/
public Connection createConnection() {
try {
//加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//加载配置文件
Properties p = new Properties();
p.load(new FileInputStream("jdbc.properties"));
return DriverManager.getConnection(p.getProperty("url"), p.getProperty("user"), p.getProperty("password"));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 获取连接
*
* @return
*/
public Connection getConnection() {
Connection connection = getAddConnection();
while (connection == null) {
System.out.println(Thread.currentThread().getName() + "开始等待获取连接");
try {
Thread.sleep(timeout);
connection = getAddConnection();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "拿到连接");
return connection;
}
/**
* 可以实现递增获取的机制
*
* @return
*/
private Connection getAddConnection() {
Connection connection = getUsableConnection();
if (connection == null) {
resizePool(stepSize);
connection = getUsableConnection();
}
return connection;
}
/**
* 获取可用的连接
*
* @return
*/
private Connection getUsableConnection() {
Connection connection = null;
if (pool.size() > 0) {
for (PoolCollection poolCollection : pool) {
if (poolCollection.isUsed() == false) {
poolCollection.setUsed(true);
connection = poolCollection.getConnection();
//connection有课能在上次使用过程中产生异常被中断
try {
// connection.isValid如果连接未关闭且有效,则返回true
if (connection.isValid(2000) == false) {
connection = createConnection();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
break;
}
}
}
return connection;
}
归还
/**
* 关闭
* @param connection
*/
public void close(Connection connection){
for (PoolCollection poolCollection : pool) {
if(connection == poolCollection.getConnection()){
poolCollection.setUsed(false);
}
}
}
测试
package com.star;
import java.sql.Connection;
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 20; i++) {
new Thread(){
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "获取连接");
Poopool1 = Pool.getInstance();
Connection connection = pool1.getConnection();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
pool1.close(connection);
System.out.println(Thread.currentThread().getName() + "释放连接");
}
}.start();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
下载DBCP地址:
下载pool地址
下载Logging地址
参数 | 默认值 | 说明 |
---|---|---|
username |
传递给JDBC驱动的用于建立连接的用户名 | |
password |
传递给JDBC驱动的用于建立连接的密码 | |
url |
传递给JDBC驱动的用于建立连接的URL | |
driverClassName |
使用的JDBC驱动的完整有效的Java 类名 | |
initialSize |
0 | 初始化连接:连接池启动时创建的初始化连接数量,1.2版本后支持 |
maxActive | 8 | 最大活动连接:连接池在同一时间能够分配的最大活动连接的数量, 如果设置为非正数则表示不限制 |
maxIdle | 8 | 最大空闲连接:连接池中容许保持空闲状态的最大连接数量,超过的空闲连接将被释放, 如果设置为负数表示不限制 |
minIdle | 0 | 最小空闲连接:连接池中容许保持空闲状态的最小连接数量,低于这个数量将创建新的连接, 如果设置为0则不创建 |
maxWait | 无限 | 最大等待时间:当没有可用连接时,连接池等待连接被归还的最大时间(以毫秒计数)超过时间则抛出异常,如果设置为-1表示无限等待 |
testOnReturn | false | 是否在归还到池中前进行检验 |
testWhileIdle | false | 连接是否被空闲连接回收器(如果有)进行检验.如果检测失败, 则连接将被从池中去除.设置为true后如果要生效,validationQuery参数必须设置为非空字符串 |
minEvictableIdleTimeMillis | 1000 * 60 * 30 |
连接在池中保持空闲而不被空闲连接回收器线程 (如果有)回收的最小时间值,单位毫秒 |
numTestsPerEvictionRun | 3 | 在每次空闲连接回收器线程(如果有)运行时检查的连接数量 |
timeBetweenEvictionRunsMillis | -1 | 在空闲连接回收器线程运行期间休眠的时间值,以毫秒为单位. 如果设置为非正数,则不运行空闲连接回收器线程 |
validationQuery | null | SQL查询,用来验证从连接池取出的连接,在将连接返回给调用者之前.如果指定, 则查询必须是一个SQSELECT并且必须返回至少一行记录 |
testOnBorrow | true | 是否在从池中取出连接前进行检验,如果检验失败, 则从池中去除连接并尝试取出另一个. |
package com.dbcp;
import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;
public class DBCPUtils {
private String driver = "com.mysql.cj.jdbc.Driver";
private String ur= "jdbc:mysql://localhost/mydbcp?serverTimezone=GMT";
private String username = "root";
private String password = "";
private static BasicDataSource basicDataSource = new BasicDataSource();
public DBCPUtils() {
basicDataSource.setUrl(url);
basicDataSource.setDriverClassName(driver);
basicDataSource.setUsername(username);
basicDataSource.setPassword(password);
basicDataSource.setInitialSize(10);// 初始化时创建10个链接
basicDataSource.setMaxIdle(8);// 设置最大连接数
basicDataSource.setMaxIdle(5);// 这只最大的空闲连接数
basicDataSource.setMinIdle(1);// 设置最小空闲连接数字
}
/**
* 返回一个数据源DataSource应该是在javax.sql.DataSource包下
*
* @return
*/
public static DataSource getDataSource() {
return basicDataSource;
}
}
测试
package com.dbcp;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import javax.sql.DataSource;
public class DBCPTest {
public static void main(String[] args) {
DBCPUtils uti= new DBCPUtils();
DataSource ds = util.getDataSource();
Connection conn;
try {
conn = ds.getConnection();
String sq= "insert into user values(null,?,?,?,?)";
PreparedStatement st = conn.prepareStatement(sql);
st.setString(1, "王麻子");
st.setInt(2, 1);
st.setDate(3, new Date(new SimpleDateFormat("yyyy-MM-dd").parse("2019-06-08").getTime()));
st.setInt(4, 1);
int i = st.executeUpdate();
if (i == 1) {
System.out.println("success");
} else {
System.out.println("fail");
}
} catch (SQLException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
}
}
配置文件dbcp.properties
#驱动名
driverClassName=com.mysql.cj.jdbc.Driver
#数据库
database=mydbcp
#url
url=jdbc:mysql://localhost/${database}?serverTimezone=Asia/Shanghai&characterEncoding=UTF-8
#用户名
username=root
#密码
password=
#初试连接数
initialSize=30
#最大活跃数
maxTotal=30
#最大idle数
maxIdle=10
#最小idle数
minIdle=5
#最长等待时间(毫秒)
maxWaitMillis=1000
#程序中的连接不使用后是否被连接池回收(该版本要使用removeAbandonedOnMaintenance和removeAbandonedOnBorrow)
#removeAbandoned=true
removeAbandonedOnMaintenance=true
removeAbandonedOnBorrow=true
#连接在所指定的秒数内未使用才会被删除(秒)(为配合测试程序才配置为1秒)
removeAbandonedTimeout=1
使用
package com.dbcp;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.commons.dbcp2.BasicDataSourceFactory;
public class DBCPUtils2 {
private static BasicDataSource basicDataSource = new BasicDataSource();
public DBCPUtils2() {
Properties prop = new Properties();
try {
prop.load(new FileInputStream("src/dbcp.properties"));
basicDataSource = new BasicDataSourceFactory().createDataSource(prop);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 返回一个数据源DataSource应该是在javax.sql.DataSource包下
*
* @return
*/
public static DataSource getDataSource() {
return basicDataSource;
}
}
测试
package com.dbcp;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import javax.sql.DataSource;
public class DBCPTest2 {
public static void main(String[] args) {
DBCPUtils2 uti= new DBCPUtils2();
DataSource ds = util.getDataSource();
Connection conn;
try {
conn = ds.getConnection();
String sq= "insert into user values(null,?,?,?,?)";
PreparedStatement st = conn.prepareStatement(sql);
st.setString(1, "王麻子");
st.setInt(2, 1);
st.setDate(3, new Date(new SimpleDateFormat("yyyy-MM-dd").parse("2019-06-08").getTime()));
st.setInt(4, 1);
int i = st.executeUpdate();
if (i == 1) {
System.out.println("success");
} else {
System.out.println("fail");
}
} catch (SQLException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
}
}
下载C3P0地址:
package com.c3p0;
import java.beans.PropertyVetoException;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class C3P0Utils {
private static ComboPooledDataSource cpds = null;
/**
* 初始化
*/
public C3P0Utils() {
cpds = new ComboPooledDataSource();
try {
cpds.setDriverClass("com.mysql.cj.jdbc.Driver");
cpds.setJdbcUrl("jdbc:mysql://localhost/mydbcp?serverTimezone=GMT");
cpds.setUser("root");
cpds.setPassword("");
cpds.setMinPoolSize(5);
cpds.setMaxPoolSize(20);
cpds.setAcquireIncrement(5);
cpds.setInitialPoolSize(5);
cpds.setMaxStatements(50);
cpds.setMaxIdleTime(60);
} catch (PropertyVetoException e) {
e.printStackTrace();
}
}
/**
* 获取 Connection 连接
*
* @return
*/
public static ComboPooledDataSource getDataSource() {
return cpds;
}
}
测试
package com.c3p0;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import javax.sql.DataSource;
public class C3P0Test {
public static void main(String[] args) {
C3P0Utils uti= new C3P0Utils();
DataSource ds = util.getDataSource();
Connection conn;
try {
conn = ds.getConnection();
String sq= "insert into user values(null,?,?,?,?)";
PreparedStatement st = conn.prepareStatement(sql);
st.setString(1, "王麻子");
st.setInt(2, 1);
st.setDate(3, new Date(new SimpleDateFormat("yyyy-MM-dd").parse("2019-06-08").getTime()));
st.setInt(4, 1);
int i = st.executeUpdate();
if (i == 1) {
System.out.println("success");
} else {
System.out.println("fail");
}
} catch (SQLException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
}
}
配置文件夹,通过 c3p0-config.xml
文件进行配置,文件名不能改
<c3p0-config>
<default-config>
<property name="user">rootproperty>
<property name="password">rootproperty>
<property name="jdbcUrl">jdbc:mysql://localhost/mydbcp? serverTimezone=Asia/Shanghai&characterEncoding=UTF-8&useSSL=false
property>
<property name="driverClass">com.mysql.cj.jdbc.Driverproperty>
<property name="checkoutTimeout">30000property>
<property name="idleConnectionTestPeriod">30property>
<property name="initialPoolSize">5property>
<property name="maxIdleTime">60property>
<property name="maxPoolSize">20property>
<property name="minPoolSize">5property>
<property name="maxStatements">50property>
<property name="acquireIncrement">5property>
default-config>
<named-config name="test">
<property name="user">Xiaopengweiproperty>
<property name="password">123456property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/Xiaopengwei
property>
<property name="driverClass">com.mysql.jdbc.Driverproperty>
<property name="acquireIncrement">5property>
<property name="initialPoolSize">20property>
<property name="maxPoolSize">25property>
<property name="minPoolSize">5property>
named-config>
c3p0-config>
使用
package com.c3p0;
import java.beans.PropertyVetoException;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class C3P0Utils2 {
private static ComboPooledDataSource cpds = null;
/**
* 初始化
*/
public C3P0Utils2() {
cpds = new ComboPooledDataSource();
}
/**
* 获取 Connection 连接
* @return
*/
public static ComboPooledDataSource getDataSource() {
return cpds;
}
}
测试
package com.c3p0;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import javax.sql.DataSource;
public class C3P0Test2 {
public static void main(String[] args) {
C3P0Utils2 uti= new C3P0Utils2();
DataSource ds = util.getDataSource();
Connection conn;
try {
conn = ds.getConnection();
String sq= "insert into user values(null,?,?,?,?)";
PreparedStatement st = conn.prepareStatement(sql);
st.setString(1, "王麻子");
st.setInt(2, 1);
st.setDate(3, new Date(new SimpleDateFormat("yyyy-MM-dd").parse("2019-06-08").getTime()));
st.setInt(4, 1);
int i = st.executeUpdate();
if (i == 1) {
System.out.println("success");
} else {
System.out.println("fail");
}
} catch (SQLException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
}
}
DbUtils是在数据库连接池基础上建立起来的快速操作数据库的工具类。
后面会用到spring JdbcTemplate、Mybatis、hibernate
等框架
下载地址:
DBUtils三个核心功能介绍
-QueryRunner
中提供对sql语句操作的API
ResultSetHandler
接口,用于定义select操作后,怎样封装结果集DBUtils
类,它就是一个工具类,定义了关闭资源与事务处理的方法QueryRunner(DataSource ds)
,传入连接池,并且底层自动维护连接connection
-update(String sql,Obj...params)
,执行更新数据
query(String sql,ResultSetHandler rsh,Object...panrams)
,执行查询-ArrayHandler
:适合取1条记录,把结果集中的第一行数据转成对象数组。
ArrayListHandler
:适合取多条记录,把结果集中的每一行数据都转成一个对象数组,再存放到List中。BeanHandler
:将结果集中的第一行数据封装到一个对应的JavaBean实例中(把每条记录封装成对象,适合取一条记录)BeanListHandler
:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。MapHandler
:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。MapListHandler
:将结果集中的每一行数据都封装到一个Map里,然后再存放到ListKeyedHandler(name)
:将结果集中的每一行数据都封装到一个Map里(Map
),再把这些map再存到一个map里,其key为指定的列。ColumnListHandler
:将结果集中某一列的数据存放到List
中。ScalarHandler
:将结果集第一行的某一列放到某个对象Object中。实体类
package com.dbutils.entity;
import java.sql.Date;
public class User {
private Long id;
private String name;
private Boolean sex;
private Date birthday;
private Integer status;
public User() {
super();
}
public User(Long id, String name, Boolean sex, Date birthday, Integer status) {
super();
this.id = id;
this.name = name;
this.sex = sex;
this.birthday = birthday;
this.status = status;
}
public User(String name, Boolean sex, Date birthday) {
super();
this.name = name;
this.sex = sex;
this.birthday = birthday;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Boolean getSex() {
return sex;
}
public void setSex(Boolean sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
}
package com.dbutils;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ArrayHandler;
import org.apache.commons.dbutils.handlers.ArrayListHandler;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ColumnListHandler;
import org.apache.commons.dbutils.handlers.KeyedHandler;
import org.apache.commons.dbutils.handlers.MapHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.junit.jupiter.api.Test;
import com.dbutils.entity.User;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class MyDbUtils {
// --1.ArrayHandler:将查询的结果的第一行放到一个数组中
@Test
public void query1() throws SQLException {
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
Object[] array = runner.query("select * from user", new ArrayHandler());
System.out.println(array[0] + "," + array[1]);
}
// --2.ArrayListHandler:将查询的结果的每一行放到一个数组中,然后再将数组放到集合中;
@Test
public void query2() throws SQLException {
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
List<Object[]> list = runner.query("select * from user", new ArrayListHandler());
for (Object[] objects : list) {
System.out.println(objects[0] + "," + objects[1]);
}
}
// --3.BeanHandler:将查询的结果的第一行封装到一份javabean对象中;
@Test
public void query3() throws SQLException {
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
User user = runner.query("select * from user", new BeanHandler<User>(User.class));
System.out.println(user.getId() + "," + user.getName());
}
// --4.BeanListHandler:将查询的结果的每一行封装到一个javabean对象中,然后再将这些对象存入list中;
@Test
public void query4() throws SQLException {
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
List<User> list = runner.query("select * from user", new BeanListHandler<User>(User.class));
for (User user : list) {
System.out.println(user.getId() + "," + user.getName());
}
}
// --5.MapHandler:将查询的结果的第一行存入到一个map中,键为列名,值为各列值;
@Test
public void query5() throws SQLException {
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
Map<String, Object> map = runner.query("select * from user", new MapHandler());
for (Entry<String, Object> entry : map.entrySet()) {
String mapKey = entry.getKey();
Object mapValue = entry.getValue();
System.out.println(mapKey + ":" + mapValue);
}
}
// --6.MapListHandler:将查询的结果的每一行存入到一个map中,键为列名,值为各列值;然后再将map存入list中;
@Test
public void query6() throws SQLException {
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
List<Map<String, Object>> map = runner.query("select * from user", new MapListHandler());
for (Map<String, Object> map2 : map) {
for (Entry<String, Object> entry : map2.entrySet()) {
String mapKey = entry.getKey();
Object mapValue = entry.getValue();
System.out.println(mapKey + ":" + mapValue);
}
System.out.println("------------------------------------------------");
}
}
// --7.KeyedHandler:将查询的结果集中某一列的数据存放到List中;
@Test
public void query7() {
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
try {
// ScalarHandler 的参数可以是列的索引(从1开始)或列名
Map<Object, Map<String, Object>> map = (Map<Object, Map<String, Object>>) runner.query("select * from user",new KeyedHandler("id"));
for (Object key : map.keySet()) {
System.out.println(key + " " + map.get(key));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
// --8.ColumnListHandler:将查询的结果集中某一列的数据存放到List中;
@Test
public void query8() {
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
try {
// ScalarHandler 的参数可以是列的索引(从1开始)或列名
List<Object> list = runner.query("select * from user", new ColumnListHandler<Object>(1));
for (Object string : list) {
System.out.println(string);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
// --9.ScalarHandler:将查询的结果的第一行的某一列放到一个对象中;精确定位到某个值;
@Test
public void query9() {
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
try {
// ScalarHandler 的参数可以是列的索引(从1开始)或列名
Object name = runner.query("select * from user", new ScalarHandler<Object>(2));
System.out.println(name);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
close(
):
CloseQuietly
:CloseQuietly
这一方法不仅能在连接、声明或者结果集(ResultSet)为NULL情况下避免关闭,还能隐藏一些在程序中抛出的SQLEeception。closeQuietly(Connection conn,Statement stmt,ResultSet rs)
,这是因为在大多数情况下,连接、声明和结果集(ResultSet)是你要用的三样东西,而且在最后的块你必须关闭它们。CommitAndCloseQuietly(Connection conn)
:
LoadDriver(String driveClassName)
:这一方法装载并注册JDBC驱动程序,如果成功就返回TRUE。package utility;
/*
*@author Liu
*@Description DBPC连接池的工具类
*@data 2021/12/28
*/
import Entity.User;
import MapperEntity.UserMapperEntity;
import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.commons.dbcp2.BasicDataSourceFactory;
import java.io.FileInputStream;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
public class DBCPUtility {
private static BasicDataSource basicDataSource;
//加载配置文件
static {
Properties properties = new Properties();
try (
FileInputStream fis = new FileInputStream("dbpc.properties");
) {
properties.load(fis);
basicDataSource = BasicDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
public static List<User> executeQuery(String sql,Object ... params) {
Connection connection = getConnection();
PreparedStatement statement=null;
List<User> list = new ArrayList<>();
if (connection==null) {
return null;
}
try {
connection.setAutoCommit(false);
statement=connection.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
statement.setObject(i+1,params[i]);
}
ResultSet resultSet = statement.executeQuery();
list = UserMapperEntity.getUser(resultSet);
connection.commit();
} catch (SQLException throwables) {
throwables.printStackTrace();
try {
connection.rollback();
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
Close(connection,statement);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return list;
}
/**
* 修改
* @param sql
* @param params
* @return
*/
public static int executeUpdate(String sql,Object ... params) {
Connection connection = getConnection();
PreparedStatement statement=null;
int rows=0;
List<User> list = new ArrayList<>();
if (connection==null) {
return rows;
}
try {
connection.setAutoCommit(false);
statement=connection.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
statement.setObject(i+1,params[i]);
}
rows = statement.executeUpdate();
connection.commit();
} catch (SQLException throwables) {
throwables.printStackTrace();
try {
connection.rollback();
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
Close(connection,statement);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return rows;
}
/**
* 获取数据库的连接
*
* @return 连接
*/
public static Connection getConnection(){
try {
return basicDataSource.getConnection();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return null;
}
/**
* 关闭Connection
*
* @param connection 连接
* @throws SQLException
*/
public static void Close(Connection connection) throws SQLException {
if (connection != null) {
connection.close();
}
}
/**
* 关闭statement
*
* @param statement 连接
* @throws SQLException
*/
public static void Close(Statement statement) throws SQLException {
if (statement != null) {
statement.close();
}
}
/**
* 关闭connection 和 statement
* @param connection 连接
* @param statement statement
* @throws SQLException
*/
public static void Close(Connection connection,Statement statement) throws SQLException {
connection.close();
statement.close();
}
}
package utility;
/*
*@author Liu
*@Description
*@data 2021/12/28
*/
import Entity.User;
import MapperEntity.UserMapperEntity;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class C3P0Utility {
private static final ComboPooledDataSource dataSource;
static{
dataSource=new ComboPooledDataSource();
}
/**
* 获取连接
* @return
*/
public static Connection getConnection(){
try {
return dataSource.getConnection();
} catch (SQLException throwables)
{
throwables.printStackTrace();
}
return null;
}
/**
* 查询
* @param sql
* @param params
* @return
*/
public static List<User> executeQuery(String sql,Object ... params){
Connection connection = getConnection();
PreparedStatement statement=null;
List<User> list = new ArrayList<>();
if (connection==null) {
return null;
}
try {
connection.setAutoCommit(false);
statement=connection.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
statement.setObject(i+1,params[i]);
}
ResultSet resultSet = statement.executeQuery();
list = UserMapperEntity.getUser(resultSet);
connection.commit();
} catch (SQLException throwables) {
throwables.printStackTrace();
try {
connection.rollback();
} catch (SQLException e) {
e.printStackTrace();
}finally {
Close(connection,statement);
}
}
return list;
}
/**
* 修改
* @param sql
* @param params
* @return
*/
public static int executeUpdate(String sql,Object ... params){
Connection connection = getConnection();
PreparedStatement statement=null;
int rows=0;
if (connection==null) {
return rows;
}
try {
connection.setAutoCommit(false);
statement=connection.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
statement.setObject(i+1,params[i]);
}
rows = statement.executeUpdate();
connection.commit();
} catch (SQLException throwables) {
throwables.printStackTrace();
try {
connection.rollback();
} catch (SQLException e) {
e.printStackTrace();
}finally {
Close(connection,statement);
}
}
return rows;
}
/**
* 关闭连接
* @param connection
* @return
*/
public static void Close(Connection connection){
if (connection!=null) {
try {
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
public static void Close(Statement statement){
if(Objects.nonNull(statement)){
try {
statement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
public static void Close(Connection connection,Statement statement){
Close(connection);
Close(statement);
}
}