文章目录
20190801更新:6.4 DBCP;6.5DBUtils
六:数据库连接池
6.1 概念
-
其实就是一个容器(集合),存放数据库连接的容器。
- 当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归还为容器。
-
好处:
- 节约资源
- 用户访问高效
- 实现:
- 标准接口:
DataSource
javax.sql包下- 方法:
- 获取连接:
getConnection()
- 归还连接:如果连接对象
Connection
是从连接池获取的,那么调用Connection.close()
,则不会再关闭连接了,而是归还连接。
- 获取连接:
- 方法:
- 一般我们不去实现它,由数据库厂商来实现。
- c3p0:数据库连接池技术
- Druid:德鲁伊数据路连接池技术,由阿里巴巴提供
- 标准接口:
6.2 c3p0
-
步骤:
-
导入jar包(两个),
c3p0-0.9.5.2.jar
和mchange-commons-java-0.2.12.jar
(mysql的驱动jar包也要导入,不要忘记,mysql-connector-java-5.1.37-bin.jar
),所以一共是3个 -
定义配置文件:
- 名称:
c3p0.properties
orc3p0-config.xml
<c3p0-config> <!-- 使用默认的配置读取连接池对象 --> <default-config> <!-- 连接参数 --> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/db4</property> <property name="user">root</property> <property name="password">root</property> <!-- 连接池参数 --> <!-- 初始化申请的连接数量 --> <property name="initialPoolSize">5</property> <!-- 最大的连接数量 --> <property name="maxPoolSize">10</property> <!-- 超时时间 --> <property name="checkoutTimeout">3000</property> </default-config> <named-config name="otherc3p0"> <!-- 连接参数 --> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/day25</property> <property name="user">root</property> <property name="password">root</property> <!-- 连接池参数 --> <property name="initialPoolSize">5</property> <property name="maxPoolSize">8</property> <property name="checkoutTimeout">1000</property> </named-config> </c3p0-config>
- 路径:直接将文件放在
src
目录下
- 名称:
-
创建核心对象:数据库连接对象
ComboPooledDataSource
-
获取连接:
getConnection()
package day03_JDBC; import com.mchange.v2.c3p0.ComboPooledDataSource; import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException; /** * C3P0演示 */ public class C3P0Demo01 { public static void main(String[] args) throws SQLException { //1. 创建数据库连接池对象 DataSource ds = new ComboPooledDataSource(); //2. 获取连接对象 Connection conn = ds.getConnection(); //3. 打印连接对象 System.out.println(conn); } }
-
6.3 Druid
-
数据库连接池实现技术,由阿里巴巴提供
-
步骤
-
导入jar包:
druid-1.0.9.jar
-
定义配置文件:
- 是
properties
形式
driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://127.0.0.1:3306/db3 username=root password=root # 初始化连接数量 initialSize=5 # 最大连接数 maxActive=10 # 最长等待时间 maxWait=3000
- 可以叫任意名称,可以放在任意的目录下
- 是
-
加载配置文件。
Properties
-
获取数据库连接池对象:通过工厂类来获取
DruidDataSourceFctory
-
获取连接:
getConnection()
package day03_JDBC; import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.io.IOException; import java.io.InputStream; import java.sql.Connection; import java.util.Properties; public class DruidDemo01 { public static void main(String[] args) throws Exception { //1. 导入jar包 //2. 定义配置文件 //3. 加载配置文件 Properties pro = new Properties(); InputStream rs = DruidDemo01.class.getClassLoader().getResourceAsStream("druid.properties"); pro.load(rs); //4. 获取连接池对象 DataSource ds = DruidDataSourceFactory.createDataSource(pro); //5. 获取连接 Connection conn = ds.getConnection(); System.out.println(conn); } }
-
-
定义工具类
- 定义一个类 JDBCUtils
- 提供静态代码块加载配置文件,初始化连接池对象
- 提供方法
- 获取连接方法:通过数据库连接池获取连接
- 释放资源
- 获取连接池的方法
package day03_JDBC.JDBCUtils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class JDBCUtils_Druid {
//1. 定义成员变量
private static DataSource ds;
static{
try {
//1. 加载配置文件
Properties pro = new Properties();
pro.load(JDBCUtils_Druid.class.getClassLoader().getResourceAsStream("druid.properties"));
//2. 获取Datasource
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取连接的方法
*/
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
/**
* 释放资源
*/
public static void close(Statement stmt, Connection conn){
close(null, stmt, conn);
}
public static void close(ResultSet rs, Statement stmt, Connection conn){
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null){
try {
conn.close();//归还连接
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 获取连接池的方法
*/
public static DataSource getDataSource(){
return ds;
}
}
- 练习代码:一个添加操作
package day03_JDBC;
import day03_JDBC.JDBCUtils.JDBCUtils_Druid;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* 使用新的工具类
*/
public class DruidDemo02 {
public static void main(String[] args) {
/*
完成一个添加操作:给accout添加一条记录
*/
Connection conn = null;
PreparedStatement pstmt = null;
try {
//1. 获取连接
conn = JDBCUtils_Druid.getConnection();
//2. 定义sql
String sql = "insert into account values(null,?,?)";
//3. 获取pstmt对象
pstmt = conn.prepareStatement(sql);
//4. 给?赋值
pstmt.setString(1,"王五");
pstmt.setDouble(2, 3000);
//5. 执行sql
int count = pstmt.executeUpdate();//执行成功的返回
System.out.println(count);
} catch (SQLException e) {
e.printStackTrace();
} finally {
//6. 释放资源
JDBCUtils_Druid.close(pstmt, conn);
}
}
}
6.4 DBCP(Apache)
-
需要导入两个
jar
包,分别为:commons-dbcp-1.4.jar
和commons-pool-1.5.6.jar
-
DBCP的连接池
DataSource
的实现类为BasicDataSource
,可以使用此实现类或使用工厂方法BasicDataSourceFactory.createDataSource(pro)
实现,但需要引入配置文件,具体实现方式如下:package day0801; import java.io.FileInputStream; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.Properties; import javax.sql.DataSource; import org.apache.commons.dbcp.BasicDataSource; import org.apache.commons.dbcp.BasicDataSourceFactory; public class DBCPDemo01 { public static void main(String[] args) throws Exception{ Properties pro = new Properties(); pro.load(new FileInputStream(DBCPDemo01.class.getResource("dbcp.properties").getFile())); DataSource ds = BasicDataSourceFactory.createDataSource(pro); Connection conn = ds.getConnection(); String sql = "select * from account"; PreparedStatement pstmt = conn.prepareStatement(sql); ResultSet rs = pstmt.executeQuery(); while(rs.next()) { int id = rs.getInt(1); String name = rs.getString(2); int balance = rs.getInt(3); System.out.println(id + "---" + name + "---" + balance); } } }
6.5 DBUtils(快速创建对象,并以集合形式返回)
-
核心类:
QueryRunner
- 使用:
QueryRunner qr = new QueryRunner(连接池对象ds);
List<Person> list = qr.query(sql, new BeanListHandler<Person>(Person.class));
返回集合
- 使用:
-
核心参数:
ResultSetHandler
(接口),创建对象所必须- 注意事项:
- 实体类构造器必须是无参构造器,且不能省略
- 注意事项:
-
实际操作:
-
配置文件(
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/db2</property> <property name="user">root</property> <property name="password">root</property> <property name="initialPoolSize">5</property> <property name="maxPoolSize">20</property> </default-config> <named-config name="oracle"> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql:///web_07</property> <property name="user">root</property> <property name="password">123</property> </named-config> </c3p0-config>
-
主程序
package day0801; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.BeanListHandler; import com.mchange.v2.c3p0.ComboPooledDataSource; public class DBuUtilsDemo { public static void main(String[] args) throws Exception { List<Person> persons = findAll(); for(Person p : persons) { System.out.println(p); } } //1. 创建查询的方法,返回存Person的List public static List<Person> findAll() throws Exception { ComboPooledDataSource ds = new ComboPooledDataSource(); QueryRunner qr = new QueryRunner(ds); String sql = "select * from emp"; List<Person> list = qr.query(sql, new BeanListHandler<Person>(Person.class)); return list; } }
-
实体类
package day0801; import java.util.Date; public class Person { private int id; private String name; private String gender; private double salary; private Date join_date; private int dept_id; public Person() {//无参构造器十分重要,必须是无参构造器 } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } public Date getJoin_date() { return join_date; } public void setJoin_date(Date join_date) { this.join_date = join_date; } public int getDept_id() { return dept_id; } public void setDept_id(int dept_id) { this.dept_id = dept_id; } @Override public String toString() { return "Person [id=" + id + ", name=" + name + ", gender=" + gender + ", salary=" + salary + ", join_date=" + join_date + ", dept_id=" + dept_id + "]"; } }
-
七、Spring JDBC _ JdbcTemplate
- Spring框架对JDBC的简单封装。提供了
JdbcTemplate
对象,简化JDBC的开发 - 步骤
- 导入jar包(5个),并且依赖数据库连接池的jar包和驱动包。
- 创建JDBCTemplate对象。依赖于数据源
DataSource
JdbcTemplate template = new JdbcTemplate(ds);
- 调用JDBCTemplate的方法来完成CRUD的操作。
update()
:执行DML语句。增删改语句queryForMap()
:查询结果,将结果集封装为map
集合,将列名作为key
,将值作为value
,将这条记录封装为一个Map
集合。- 注意:这个方法查询的结果集长度只能是1
queryForList()
:查询结果封装为list
集合。- 将每一条记录封装为一个
Map
集合,再将Map
集合装在到List
集合
- 将每一条记录封装为一个
query()
:查询结果,将结果封装为JavaBean
对象。query
的参数:RowMapper- 一般使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装
new BeanPropertyRowMapper<Emp>(Emp.class)
queryForObject
:查询结果,将结果封装为对象。- 一般用于聚合函数的查询。
package day03_JDBC;
import day03_JDBC.JDBCUtils.JDBCUtils_Druid;
import org.springframework.jdbc.core.JdbcTemplate;
public class JDBCTemplateDemo01 {
public static void main(String[] args) {
//1. 导入jar包
//2. 创建JDBC
JdbcTemplate template = new JdbcTemplate(JDBCUtils_Druid.getDataSource());
//3. 调用方法
String sql = "update account set balance = 500 where id = ?";
int count = template.update(sql, 3);
System.out.println(count);
}
}
- 练习:
- 需求
- 修改1号数据的salary 为10000
- 添加一条记录
- 删除刚才添加的记录
- 查询id为1的记录,将其封装为
Map
集合 - 查询所有记录,将其封装为
List
- 查询所有记录,将其封装为
Emp
对象的List
- 查询总记录数
- 需求
package day03_JDBC;
import day03_JDBC.JDBCUtils.JDBCUtils_Druid;
import org.junit.Test;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import java.sql.Date;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
public class JdbcTemplateDemo02 {
//Junit单元测试,可以让方法独立执行
/*
修改1号数据的salary 为10000
*/
private JdbcTemplate template = new JdbcTemplate(JDBCUtils_Druid.getDataSource());
@Test
public void test01(){
JdbcTemplate template = new JdbcTemplate(JDBCUtils_Druid.getDataSource());
String sql = "update emp set salary = 10000 where id = ?";
int count = template.update(sql, 1);
System.out.println(count);
}
/*
添加一条记录
*/
@Test
public void test02(){
String sql = "insert into emp(id,name,dept_id) values(?,?,?)";
int count = template.update(sql, 6, "文泽路", 1);
System.out.println(count);
}
/*
删除刚才添加的记录
*/
@Test
public void test03(){
String sql = "delete from emp where id = ?";
int count = template.update(sql, 6);
System.out.println(count);
}
/*
查询id为1的记录,将其封装为`Map`集合
注意:这个方法查询的结果集长度只能是1
*/
@Test
public void test04(){
String sql = "select * from emp where id = ? ";
Map<String, Object> map = template.queryForMap(sql, 1);
System.out.println(map);
}
/*
查询所有记录,将其封装为`List
*/
@Test
public void test05(){
String sql = "select * from emp";
List<Map<String, Object>> list = template.queryForList(sql);
for(Map<String, Object> map : list){
System.out.println(map);
}
}
/*
查询所有记录,将其封装为`Emp`对象的`List`
*/
@Test
public void test06(){
String sql = "select * from emp";
List<Emp> list = template.query(sql, new RowMapper<Emp>() {
@Override
public Emp mapRow(ResultSet resultSet, int i) throws SQLException {
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
String gender = resultSet.getString("gender");
double salary = resultSet.getDouble("salary");
Date join_date = resultSet.getDate("join_date");
int dept_id = resultSet.getInt("dept_id");
Emp emp = new Emp(id, name, gender, salary, join_date, dept_id);
return emp;
}
});
for(Emp emp : list){
System.out.println(emp);
}
}
/*
简化操作!!!
*/
@Test
public void test06_1(){
String sql = "select * from emp";
List<Emp> list = template.query(sql, new BeanPropertyRowMapper<Emp>(Emp.class));
for(Emp emp : list){
System.out.println(emp);
}
}
/*
查询总记录数
*/
@Test
public void test07(){
String sql = "select count(id) from emp";
Long total = template.queryForObject(sql, Long.class);
System.out.println(total);
}
}