连接池&DBUtils
1.连接池
1.1连接池原理
存放多个连接的集合
目的:解决建立数据库连接耗费资源和时间很多的问题,提高性能。
1.2编写标准的数据源(规范)
Java为数据库连接池提供了公共的接口:javax.sql.DataSource,各个厂商需要让自己的连接池实现这个接口。这样应用程序可以方便的切换不同厂商的连接池!
常见的连接池:DBCP、C3P0。
1.2.1DBCP连接池
DBCP:Apache推出的Database Connection Pool
使用步骤:
-
添加jar包 commons-dbcp-1.4.jar、 commons-pool-1.5.6.jar (数据库驱动mysql-connector-java-5.1.17-bin.jar)
-
添加属性资源文件
2.1 配置文件名称:*.properties
2.2 配置文件位置:任意,建议src(classpath/类路径)
2.3 配置文件内容:properties不能编写中文
#连接设置 driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://ip:port/数据库 username=**** password=**** #<!-- 初始化连接 --> initialSize=10 #最大连接数量 maxActive=50 #<!-- 最大空闲连接 --> maxIdle=20 #<!-- 最小空闲连接 --> minIdle=5 #<!-- 超时等待时间以毫秒为单位 60000毫秒/1000等于60秒 --> maxWait=60000 #JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;] #注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。 connectionProperties=useUnicode=true;characterEncoding=utf8 #指定由连接池所创建的连接的自动提交(auto-commit)状态。 defaultAutoCommit=true #driver default 指定由连接池所创建的连接的只读(read-only)状态。 #如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix) defaultReadOnly= #driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。 #可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE defaultTransactionIsolation=REPEATABLE_READ
-
编写DBCP数据源工具类
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import javax.sound.midi.VoiceStatus;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
/**
*
* @author 焦大宝
* 创建DBCP 连接池
*
*/
public class DBCPUtils {
private static DataSource ds;
/**
加载配置文件 *.properties
BasicDataSourceFactory.createDataSource(p) 创建连接池
*/
static {
Properties p = new Properties();
try {
p.load(DBCPUtils.class.getClassLoader().getResourceAsStream("dbcpconfig.properties"));
ds = BasicDataSourceFactory.createDataSource(p);
} catch (Exception e) {
// TODO: handle exception
throw new RuntimeException("创建DBCP连接池失败!");
}
}
/**
获取连接池
*/
public static DataSource getDataSource() throws Exception {
try {
return ds;
} catch (SQLException e) {
throw new RuntimeException("获取DBCP连接池失败!");
}
}
/**
获取连接
*/
public static Connection getConnection() throws SQLException {
try {
return ds.getConnection();
} catch (SQLException e) {
throw new RuntimeException("获取DBCP连接失败!");
}
}
/**
关闭资源
*/
public static void release(Statement st,Connection conn,ResultSet rs) {
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
}
}
if(st != null){
try {
st.close();
} catch (SQLException e) {
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
}
}
}
}
4.测试Demo
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.jar.Attributes.Name;
import com.itheima.cn.DBCP.DBCPUtils;
public class DBCPDemo {
@Test
public static void method01() throws SQLException {
//注册驱动
//获取连接
Connection connection = DBCPUtils.getConnection();
String sqlString = "select * from category ";
PreparedStatement prepareStatement = connection.prepareStatement(sqlString);
boolean execute = prepareStatement.execute();
ResultSet resultSet = prepareStatement.getResultSet();
while (resultSet.next()) {
String cid = resultSet.getString("cid");
String cname = resultSet.getString("cname");
System.out.println("限额信息:cid:" + cid +", name:"+cname);
}
DBCPUtils.release(prepareStatement, connection, null);
}
}
1.2.2C3P0连接池
C3P0开源免费的连接池!目前使用它的开源项目有:Spring、Hibernate等。使用第三方工具需要导入jar包,c3p0使用时还需要添加配置文件 c3p0-config.xml
使用步骤:
1.添加jar包 c3p0-0.9.1.2.jar (注意版本)、(数据库驱动mysql-connector-java-5.1.17-bin.jar)
2.编写配置文件 **c3p0-config.xml,**放在src中(注:文件名一定不要写错)
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://*ip*:3306/*</property>
<property name="user">****</property>
<property name="password">****</property>
<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">100</property>
<property name="minPoolSize">10</property>
</default-config>
<!-- DataSource ds = new ComboPooledDataSource(" mySource ");
//参数对应使用哪个config,如果不写,表示使用默认的config,即default-config里的配置,否则使用参数指定的named-config里的配置-->
<named-config name="mySource">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://*ip*:3306/*</property>
<property name="user">****</property>
<property name="password">****</property>
<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">100</property>
<property name="minPoolSize">10</property>
</named-config>
</c3p0-config>
3.创建C3P0连接池工具类
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import com.mchange.v2.c3p0.ComboPooledDataSource;
/**
*
* @author 焦大宝
* 创建C3P0 连接池
*
*/
public class C3P0Utils {
/**
* 创建C3P0连接池
* 默认查找c3p0-config.xml 并解析
*/
static ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
/**
* 获取连接
* @return Connection
*/
public static Connection getConnection() {
Connection connection = null;
try {
connection = comboPooledDataSource.getConnection();
return connection;
} catch (Exception e) {
// TODO: handle exception
throw new RuntimeException("C3P0获取连接失败!");
}
}
/**
* 获取连接池对象
* @return ComboPooledDataSource
*/
public static ComboPooledDataSource getDataSource() {
try {
return comboPooledDataSource;
} catch (Exception e) {
// TODO: handle exception
throw new RuntimeException("C3P0获取连接池失败!");
}
}
/**
* 刷新资源
* @param Statement st
* @param Connection conn
* @param ResultSet rs
*/
public static void release(Statement st,Connection conn,ResultSet rs) {
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
}
}
if(st != null){
try {
st.close();
} catch (SQLException e) {
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
}
}
}
}
4.测试Demo
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.jar.Attributes.Name;
import com.itheima.cn.C3P0.C3P0Utils;
import com.itheima.cn.DBCP.DBCPUtils;
public class C3P0Demo {
@Test
public static void method01() throws SQLException {
Connection connection = C3P0Utils.getConnection();
PreparedStatement prepareStatement = connection.prepareStatement("select * from category");
boolean execute = prepareStatement.execute();
if (execute) {
ResultSet resultSet = prepareStatement.getResultSet();
if (resultSet.next()) {
String cid = resultSet.getString("cid");
String cname = resultSet.getString("cname");
System.out.println("限额信息:cid:" + cid +", name:"+cname);
}
}
C3P0Utils.release(prepareStatement, connection, null);
}
}
2.DBUtils工具类执行增删改查的操作
2.1 概述
简化JDBC代码开发,本案例我们将采用apache commons组件一个成员:DBUtils。
DBUtils就是JDBC的简化开发工具包。需要使用技术:连接池(获得连接),SQL语句都没有少。
2.2 JavaBean组件
JavaBean就是一个类,在开发中常用于封装数据。具有如下特性
1.需要实现接口:java.io.Serializable ,通常偷懒省略了。
2.提供私有字段:private 类型 字段名;
3.提供getter/setter方法:
4.提供无参构造
2.3 DBUtils
2.3.1概述
DBUtils是java编程中的数据库操作实用工具,小巧简单实用。
DBUtils封装了对JDBC的操作,简化了JDBC操作,可以少写代码。DbUtils类,它就是一个工具类,定义了关闭资源与事务处理的方法。
Dbutils三个核心功能介绍
QueryRunner中提供对sql语句操作的API.(核心类)
1.QueryRunner(DataSource ds) ,提供数据源(连接池),DBUtils底层自动维护连接connection
2.update(String sql, Object... params) ,执行更新数据 insert update delete
3.query(String sql, ResultSetHandler<T> rsh, Object... params) ,执行查询 select
**ResultSetHandler接口,结果集处理类,用于定义select操作后,怎样封装结果集.**
结果集 | |
---|---|
ArrayHandler | 将结果集中的第一条记录封装到一个Object[]数组中,数组中的每一个元素就是这条记录中的每一个字段的值 |
ArrayListHandler | 将结果集中的每一条记录都封装到一个Object[]数组中,将这些数组在封装到List集合中。 |
BeanHandler | 将结果集中第一条记录封装到一个指定的javaBean中。 |
BeanListHandler | 将结果集中每一条记录封装到指定的javaBean中,将这些javaBean在封装到List集合中 |
ColumnListHandler | 将结果集中指定的列的字段值,封装到一个List集合中 |
KeyedHandler | 将结果集中每一条记录封装到Map<String,Object>,在将这个map集合做为另一个Map的value,另一个Map集合的key是指定的字段的值。 |
MapHandler | 将结果集中第一条记录封装到了Map<String,Object>集合中,key就是字段名称,value就是字段值 |
MapListHandler | 将结果集中每一条记录封装到了Map<String,Object>集合中,key就是字段名称,value就是字段值,在将这些Map封装到List集合中。 |
ScalarHandler | 它是用于单个数据。例如select count(*) from 表操作。 |
2.4 DBUtils开发步骤:
1、创建项目,并导入jar包 commons-dbutils-1.4.jar
2、创建连接池 (C3P0、DBCP连接池)
3、编写测试类
import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import com.itheima.bean.Category;
import com.itheima.cn.C3P0.C3P0Utils;
import com.mchange.v2.c3p0.impl.NewPooledConnection;
/**
* @author 焦大宝
*/
public class DButilsDemo{
@Test
public static void method01() throws Exception {
QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
String sql = "insert into category(cid,cname) values(?,?)";
//3 参数
Object[] params = {"c007","汽车"};
int update = queryRunner.update(sql,params);
if (update > 0) {
System.out.println("添加成功");
}else {
System.out.println("添加失败");
}
}
/**
* ArrayHandler 将结果集中的第一条记录封装到一个Object[]数组中,数组中的每一个元素就是这条记录中的每一个字段的值
ArrayListHandler 将结果集中的每一条记录都封装到一个Object[]数组中,将这些数组在封装到List集合中。
BeanHandler 将结果集中第一条记录封装到一个指定的javaBean中。
BeanListHandler 将结果集中每一条记录封装到指定的javaBean中,将这些javaBean在封装到List集合中
ColumnListHandler 将结果集中指定的列的字段值,封装到一个List集合中
KeyedHandler 将结果集中每一条记录封装到Map<String,Object>,在将这个map集合做为另一个Map的value,另一个Map集合的key是指定的字段的值。
MapHandler 将结果集中第一条记录封装到了Map<String,Object>集合中,key就是字段名称,value就是字段值
MapListHandler 将结果集中每一条记录封装到了Map<String,Object>集合中,key就是字段名称,value就是字段值,在将这些Map封装到List集合中。
ScalarHandler 它是用于单个数据。例如select count(*) from 表操作。
*/
/**
* new BeanListHandler
* @throws Exception
*/
@Test
public static void method02() throws Exception {
QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
String sql = "select * from category";
List<Category> query = queryRunner.query(sql, new BeanListHandler<Category>(Category.class));
for (Category category : query) {
System.out.println(category);
}
}
/**聚合函数
* new ScalarHandler
* @throws Exception
*/
@Test
public static void method03() throws Exception {
QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
String sql = "select count(*) from category";
Object query = queryRunner.query(sql, new ScalarHandler());
System.out.println(query);
}
}