1.连接池
jdbc程序每次访问数据库都需要创建一个新的连接,访问完毕之后,还需要释放资源。那么在这样的一个过程中,连接的创建和销毁所消耗的资源是远远大于我们发送sql并执行的时间的。就不需要不停的创建和销毁了。只需要创建一次,放在指定的地方。而我们使用的时候,直接从里面拿就行了。 这就是连接池的来源。
1.2.常用开源连接池:
C3P0 (★★★★★)
Apache DBCP (★★)
2.DBUtils
DBUtils封装了对JDBC的操作,简化了JDBC操作,可以少写代码。
Dbutils三个核心功能:
1.QueryRunner中提供对sql语句操作的API.
2.ResultSetHandler接口,用于定义select操作后,怎样封装结果集.
3.DbUtils类,它就是一个工具类,定义了关闭资源与事务处理的方法
QueryRunner核心类介绍
QueryRunner(DataSource) 创建核心类,并提供数据源,内部自己维护Connection
方法:update(String sql , Object … params) 执行DML语句
query(String sql , ResultSetHandler , Object … params) 执行DQL语句,并将查询结果封装到对象中。
案例c3p0;
1.导入包。
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.0.2</version>
</dependency>
2.C3P0配置文件
src目录下,固定的名字:c3p0-config.xml
c3p0数据库连接池自己去获取配置文件,自己解析配置文件。
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/shop</property>
<property name="user">root</property>
<property name="password">root</property>
<!-- 如果连接池中连接不够时一次性增长多少连接 -->
<property name="acquireIncrement">5</property>
<!-- 初始化连接池时池子中有多少个连接 -->
<property name="initialPoolSize">20</property>
<!-- 池子中最小连接数 -->
<property name="minPoolSize">10</property>
<!-- 池子中最大连接数 -->
<property name="maxPoolSize">40</property>
<!-- 每次最多可以执行多少个批处理语句 -->
<property name="maxStatements">50</property>
<!-- 连接池内单个连接所拥有的最大缓存statements数 -->
<property name="maxStatementsPerConnection">5</property>
</default-config>
</c3p0-config>
3.QueryRunner实现添加、更新、删除操作
@Test
public void add() {
DataSource dataSource = JdbcUtils.getDataSource();
QueryRunner queryRunner = new QueryRunner(dataSource);
String sql = "insert into product values(?,?,?,?)";
try {
queryRunner.update(sql, 14,"空调",2000,"c001");
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
public void update() {
DataSource dataSource = JdbcUtils.getDataSource();
QueryRunner queryRunner = new QueryRunner(dataSource);
String sql = "update product set price = ?";
try {
queryRunner.update(sql, 500);
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
public void delete() {
DataSource dataSource = JdbcUtils.getDataSource();
QueryRunner queryRunner = new QueryRunner(dataSource);
String sql = "delete from product where pid=?";
try {
queryRunner.update(sql, 14);
} catch (SQLException e) {
e.printStackTrace();
}
}
4.QueryRunner实现查询操作(重点)
query(String sql, ResultSetHandler rsh, Object… params) ,用来完成表数据的查询操作
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 表操作。
a.测试BeanHandler
1.提供javabean对象
package com.icbc.study.dutils;
public class Product {
private int pid;
private String pname;
private double price;
private String category_id;
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
public String getPname() {
return pname;
}
public void setPname(String pname) {
this.pname = pname;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getCategory_id() {
return category_id;
}
public void setCategory_id(String category_id) {
this.category_id = category_id;
}
@Override
public String toString() {
return "Product [pid=" + pid + ", pname=" + pname + ", price=" + price + ", category_id=" + category_id + "]";
}
public Product(int pid, String pname, double price, String category_id) {
super();
this.pid = pid;
this.pname = pname;
this.price = price;
this.category_id = category_id;
}
public Product() {
}
}
BeanHandler(重点):结果集处理的一种方式
* 使用格式: new BeanHandler<泛型>(类型)
* 将第一条数据封装到一个javaBean中
*
@Test
public void beanHandlerTest() {
DataSource dataSource = JdbcUtils.getDataSource();
QueryRunner queryRunner = new QueryRunner(dataSource);
String sql = "select * from product where pid=?";
try {
Product product = queryRunner.query(sql, 14,new BeanHandler<>(Product.class));
System.out.println(product);
} catch (SQLException e) {
e.printStackTrace();
}
}
BeanListHandler,将所有数据封装到javabean的集合中。
ScalarHandler(重点):一般用于聚合函数。count(*)是常用的,返回值类型必须是Long。
@Test
public void ScalarHandlerTest() throws SQLException {
DataSource dataSource = JdbcUtils.getDataSource();
QueryRunner queryRunner = new QueryRunner(dataSource);
String sql = "select count(*) from product ";
Long query = queryRunner.query(sql, new ScalarHandler<Long>());
System.out.println(query);
}
.MapHandler
将第一条数据封装成map集合。
key就是列名,value就是列对应的值。
@Test
public void MapHandlerTest() throws SQLException {
DataSource dataSource = JdbcUtils.getDataSource();
QueryRunner queryRunner = new QueryRunner(dataSource);
String sql = "select * from product ";
Map<String, Object> map = queryRunner.query(sql, new MapHandler());
Set<String> keySet = map.keySet();
for (String string : keySet) {
Object value = map.get(string);
System.out.println(string+"="+value);
}
}
数据库值:
结果:
MapListHandler
* 将所有的商品封装成list集合,list集合中每一个都是map集合。
* map集合的key就是列名,值就是列对应的值。
ArrayHandler
* 将第一条数据封装成数组,数组中的每个值都是列中的值。
.ArrayListHandler
* 将所有的数据封装成一个list集合,集合中的每一个对象都是数组。每一个数组对应了一条数据。
KeyedHandler
将所有的结果封装成一个map集合,
* key就是制定的列的值,
* value就是每一条数据被封装成的map集合,key是列名,值就是列 对应的值。
@Test
public void keyedHandlerTest() throws SQLException{
//首先创建一个queryRunner对象
DataSource dataSource = JdbcUtils.getDataSource();
QueryRunner queryRunner = new QueryRunner(dataSource);
String sql ="select * from product";
Map<String, Map<String, Object>> query = queryRunner.query(sql, new KeyedHandler<String>("category_id"));
for (Map.Entry<String, Map<String, Object>> e : query.entrySet()) {
System.out.println(e.getKey());
System.out.println(e.getValue());
}
}
ColumnListHandler
将制定列中的所有值封装成list集合。
@Test
public void columListHandlerTest() throws SQLException{
//首先创建一个queryRunner对象
DataSource dataSource = JdbcUtils.getDataSource();
QueryRunner queryRunner = new QueryRunner(dataSource);
String sql ="select * from product";
List<Double> query = queryRunner.query(sql, new ColumnListHandler<Double>("price"));
for (Double double1 : query) {
System.out.println(double1);
}
}
3.采用注解把Spring和DBUtils进行整合
1.修改spring配置文件。
在配置文件中配置较简单。
<!-- 开启注解扫描 -->
<context:component-scan base-package="com.icbc.study"></context:component-scan>
<!-- 1.创建querRunner对象 ,需要用到dataSource -->
<bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">
<constructor-arg name="ds" ref="dataSource"></constructor-arg>
</bean>
<!-- 2.创建 dataSource-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/shop"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>
测试:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestDbutils {
@Autowired
private QueryRunner queryRunner;
@Test
public void keyedHandlerTest() throws SQLException{
String sql ="select * from product";
Map<String, Map<String, Object>> query = queryRunner.query(sql, new KeyedHandler<String>("category_id"));
for (Map.Entry<String, Map<String, Object>> e : query.entrySet()) {
System.out.println(e.getKey());
System.out.println(e.getValue());
}
}
}