2021年9月1日
1.c3p0连接池
2.druid连接池
3.JDBC事务处理
4.DBUtil这个Dao层框架
1.连接池
1.1为什么要使用连接池
数据库的连接池
现在使用的db.properties这个文件,读取这个文件中的各个属性值,进行数据库的连接,Drivermanager.getConnection()获取数据库的连接对象。
每一次执行业务(增删改查)的时候,重新申请资源(Connection对象)。运行结束以后。直接关闭资源。不好,会导致数据库压力过大。好比咱们磁盘,每一次读取,写入。
磁盘会老化的。新的磁盘。随便读随便写。不会坏,为什么咱们用了八年的话会坏。是因为在这八年内你来回读,来回写。磁盘扛不住的。
希望采用一种共享单车的一种模式:
1.投放一定数据量车
2.用户使用,使用完毕以后,归还
3.市场需求大的话,再次投放
数据库连接池:池,游泳池,盛放很多的水
在这个池子中存放很多的连接对象。不用每次都重新连接数据库。
先连数据库,获取数据库的连接对象以后,执行sql语句。执行完sql语句以后要关闭连接对象。但是不是真正的关闭,而是把这个连接对象放到这个池子中,下次再进行sql的操作的时候,直接从池子中取连接对象。而不是重新去连接数据库了。这个池子起到一个缓存的作用!!!连接池的目的保存咱们数据库的。
1.2连接池需要考虑哪些问题【代码的角度】
数据库连接池是用来管理数据库连接资源,属性等
数据库连接必要的参数:1.url 2.user 3.assword 4.数据库的驱动
好比咱们写过一个db.properties这个文件
连接池对于数据库对象的管理:
1.初始化的容量,连接对象的容量
2.容量的最大值,连接对象的最大值
3.等待时间
数据库连接对象是需要归还的,依然是用最原始的close方法,
常见的数据库池:
1.C3P0 2.DBCP 3.Druid(德鲁伊) 阿里的连接池(2020以后也不用了)
1.3C3P0连接池的使用【重点】day32_wb1项目中
使用流程:
1.导包:需要三个包
c3p0-0.9.5.jar
mchage-common-java-0.2.19.jar
mysql-connector-java-5.1.47.jar
2.书写连接池的配置文件 c3p0-config.xml文件(你只需要复制黏贴就可以了,不需要写),这个文件放在src(有些同学偏偏就不放在src文件夹下面,你就等着报错去把!!!)
3.创建核心的类
package com.qfedu.a_Connection;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Demo1 {
public static void main(String[] args) throws SQLException {
//之前获取数据库的连接对象connection 封装了一个JdbcUtil 使用的Properties对象
//读取src下面的db.properties这个文件 把url,user,password,driver 读取出来
//然后获取connection
//现在c3p0获取connection对象
//如果实例化了 ComboPooledDataSource以后,就立马读取了xml文件
//底层是一个dom4j的文档操作方式,专门出来xml文件的
//将xml文件读取到了pool对象中了,就这么尿性!!!
//configName 就是配置文件中咱们没有使用默认的,使用的测试的一个数据连接
//ComboPooledDataSource pool = new ComboPooledDataSource("test1"); <named-config name="test1">
ComboPooledDataSource pool = new ComboPooledDataSource();//不传参就代表默认的 <default-config>
Connection connection = pool.getConnection();
//接受不了,我没有发现url,password,user,咋就加载了?咋就获取了connection
//有对象接下来就是执行sql语句
System.out.println(connection);
String sql = "insert into work(name, age, info) values(?,?,?)";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setObject(1, "翠翠");
preparedStatement.setObject(2, 34);
preparedStatement.setObject(3,"和计算机技能");
int i = preparedStatement.executeUpdate();
System.out.println(i);
preparedStatement.close();
connection.close();//j将对象放到池子中
}
}
思考:
我之前封装JdbcUtil这个类。不用db.properties了,开始使用连接池。能不能修改?
下节课修改一下。
重新使用连接池进行JdbcUtil的封装。连接池就是获取Connection对象的
1.4使用连接池获取Connection对象day32_wb2这个项目
1.导包
c3p0-0.9.5.jar
mchage-common-java-0.2.19.jar
mysql-connector-java-5.1.47.jar
commons-beanutils-1.9.3.jar
commons-logging-1.2.jar
2.在src下面黏贴一个c3p0-config.xml文件(之前db.properties这个文件不用了)
3.修改JdbcUtil这个类,这个类之前是用db.properties,现在用的是连接池
package com.qfedu.util;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
/**
* 1.完成驱动的自动加载
* 2.完成必要的数据处理 url user password
* 3.完成connection这个方法
* 4.完成统一的close方法
*/
public class JdbcUtil {
//为什么呢么是static修饰的?是因为getConnection是静态方法,
//静态方法中不能使用非静态的后成员属性
private static ComboPooledDataSource pool = new ComboPooledDataSource();
//简化getConnection方法的写法
//封装一个静态的方法,获取connetion对象
public static Connection getConnection() {
Connection connection = null;
try {
connection = pool.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
//现在封装的时候,我不知道需要关闭哪个资源
//有的需要关闭一个,有的需要关闭两个,有的需要关闭三个
//关闭一个资源 connection
public static void close(Connection connection) {
close(connection, null, null);
}
//关闭两个资源 connection statement
public static void close(Connection connection, Statement statement) {
close(connection, statement, null);
}
//关闭三个资源的 connection statement resultSet
public static void close(Connection connection, Statement statement, ResultSet resultSet) {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
1.5druid连接池day32_wb3
德鲁伊连接池是阿里巴巴在用的一个连接池
使用流程
1.导包
druid-1.0.9.jar
2.书写配置文件 druid.properties,在src文件夹下面新建一个druid.properties
3.创建核心类
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/java2109?useSSL=false
username=root
password=123456
initialSize=5
maxActive=20
maxWait=2000
package com.qfedu.a_druid;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.Properties;
public class Demo1 {
public static void main(String[] args) throws Exception {
//和db.properties非常相似
Properties properties = new Properties();
properties.load(new FileInputStream("./src/druid.properties"));
//druid里面有一个核心类,创建数据资源核心类
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
//可以拿这个dataSource获取数据库连接对象
Connection connection = dataSource.getConnection();
System.out.println(connection);
String sql = "insert into work(name, age, info) values(?,?,?)";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setObject(1, "花花");
preparedStatement.setObject(2, 23);
preparedStatement.setObject(3,"你就是你近几年");
int i = preparedStatement.executeUpdate();
System.out.println(i);
preparedStatement.close();
connection.close();//j将对象放到池子中
}
}
1.6之前讲过使用c3p0对JdbcUtil进行封装day32_wb3
接下来将一下druid连接池在封装的JdbcUtil类下面咋写的
自己尝试一下
package com.qfedu.util;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
/**
* 1.完成驱动的自动加载
* 2.完成必要的数据处理 url user password
* 3.完成connection这个方法
* 4.完成统一的close方法
*/
public class JdbcUtil {
private static DataSource ds;
static {
Properties properties = new Properties();
try {
properties.load(new FileInputStream("./src/druid.properties"));
ds = DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
//简化getConnection方法的写法
//简化getConnection方法的写法
//封装一个静态的方法,获取connetion对象
public static Connection getConnection() {
Connection connection = null;
try {
connection = ds.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
//现在封装的时候,我不知道需要关闭哪个资源
//有的需要关闭一个,有的需要关闭两个,有的需要关闭三个
//关闭一个资源 connection
public static void close(Connection connection) {
close(connection, null, null);
}
//关闭两个资源 connection statement
public static void close(Connection connection, Statement statement) {
close(connection, statement, null);
}
//关闭三个资源的 connection statement resultSet
public static void close(Connection connection, Statement statement, ResultSet resultSet) {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
2.JDBC的事务操作
2.1事务的四大特性【ssm框架的时候会重新讲事务】
原子性 隔离性 一致性 持久性
2.2在JDBC里面事务怎么执行
要在JDBC李阿敏执行事务,本质是将多个sql语句包裹在一个事务上面
语法格式:
try{
Connection conn = Drivermanager.getConnetcion();
conn.setAutoCommit(false);//关闭自动提交
//才去写sql语句
insert(),delete().update();
//如果没有错误的话,直接提交
conn.commit();
}catch(Exception e) {
//如果走异常这一步,怎么办?回滚,回到原来的状态就可以了
conn.rollback();
}finally{
conn.setAutoCommit(true);//一个事务结束以后,开启自动提交。默认的
conn.close();
}
模拟转账
张三给李四转200块钱。
至少得两个sql语句
张三这个账户减钱
package com.qfedu.a_druid;
import com.qfedu.util.JdbcUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
//事务操作的讲解
public class Demo3 {
public static void main(String[] args) throws SQLException {
Connection connection = JdbcUtil.getConnection();
try {
//1.开启事务
connection.setAutoCommit(false);//把自动提交关闭
//2.编写sql语句
//money=money+? 等号右边的money是数据库原有的值
String sql = "update bank_sys set money=money+? where name=?";
//减钱 张三的账户减钱 200
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setObject(1, -200);
preparedStatement.setObject(2, "张三");
int i = preparedStatement.executeUpdate();
//突然这个地方有异常了
int i2 = 1/0;//这个是异常代码
//整体的所有sql语句都是在一个事务当中。这两个sql语句都在一个事务中
//y一荣俱荣,一损俱损。只有你有哪一个sql语句没有执成功。那么其他sql语句也就不会成功。
//一致性 加上事务以后要么同时成功,要么同时失败!!!事务更加安全些!!!
//ssm 使用AOP进行事务的操作,是因为在配置文件中直接写事务,让咱们的代码更加健壮些!!!
//增钱 李四的账户增加钱200
preparedStatement.setObject(1, 200);
preparedStatement.setObject(2, "李四");
int i1 = preparedStatement.executeUpdate();
//如果没有错误的话,就提交上面的执行的两次sql语句
connection.commit();//事务的提交
}catch (Exception e){
//回滚
connection.rollback();
}finally {
connection.setAutoCommit(true);
connection.close();
}
}
}
和小黑屏上面的命令差不多,关键字都是一样的
3.JDBCUtil
3.1JDBCUtils是什么?
主要封装了JDBC的代码,简化dao层的操作。换句话说就是官方给咱们封装的
BaseDao,咱们自己封装了一个BaseDao。不更新了官方封装的是JDBCUtil这个。
你感觉我封装好?还是官方封装的好?
只要是官方封装的都好!!!,但是现在咱们这个JDBCUtils不用了,老程序员(2011年)我们用这个东西,现在不用了,因为apache组织不再对它进行维护了。不更新
咱们以后会学习 mybatis,mybatis-plus,hibernate, JPA 等这些框架所以淘汰了。
让大家多学习点!!!,看看底层。
不会也没有关系,后期不用,但是他可以扩展眼界!!!
只要学会BaseDao就可以了,功能是一模一样的额,都是对数据库的数据进行增删改查的
3.2入门案例
1.新建项目
2.导包
mysql-connector-java
druid
beanutils
3.工具类JdbcUtil
获取connetion对象的
https://commons.apache.org/proper/commons-dbutils/apidocs/index.html
以上官方手册,不再维护更新了
核心类叫QueryRunner
package com.qfedu.a_dbutils;
import com.qfedu.util.JdbcUtil;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.*;
import org.junit.Test;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public class TestDBUtils {