【WEEK8】 【DAY1】【DAY2】JDBC—事务数据库连接池【中文版】

2024-04-16 15:12

本文主要是介绍【WEEK8】 【DAY1】【DAY2】JDBC—事务数据库连接池【中文版】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

接上文【WEEK7】 【DAY5】JDBC—PreparedStatement对象【中文版】

目录

  • 2024.4.15 Monday
  • 10.5.事务
    • 10.5.1.要么都成功,要么都失败
    • 10.5.2.ACID原则(详见6.2.事务的ACID原则)
    • 10.5.3.实例
      • 10.5.3.1.成功的
      • 10.5.3.2.失败的
      • 10.5.3.3.步骤总结
  • 10.6.数据库连接池
    • 10.6.1.“数据库连接——执行完毕——释放”这个“连接+释放”的过程十分浪费资源
    • 10.6.2.池化技术:预先准备一些资源,需要使用资源时就可以直接使用预先准备好的
    • 10.6.3.编写连接池只需要实现一个接口:DataSource
    • 10.6.4.开源数据源实现
    • 10.6.5.DBCP
      • 10.6.5.1.需要用到的jar包
      • 10.6.5.2.新建dbcpconfig.properties文件
      • 10.6.5.3.新建utils文件
  • 2024.4.16 Tuesday
      • 10.6.5.4.新建TestDBCP文件
    • 10.6.6.C3P0
      • 10.6.6.1.需要用到的jar包
      • 10.6.6.2.新建c3p0-config.xml文件
      • 10.6.6.3.新建utils文件
      • 10.6.6.4.新建TestC3P0文件
      • 10.6.6.5.结论:无论使用什么数据源,本质相同,DataSource接口不会变,方法就不会变
    • 10.6.7.下载jar包网址备份

2024.4.15 Monday

10.5.事务

10.5.1.要么都成功,要么都失败

10.5.2.ACID原则(详见6.2.事务的ACID原则)

10.5.2.1.原子性:要么全部完成,要么都不完成
10.5.2.2.一致性:总数不变
10.5.2.3.隔离性:多个进程互不干扰
10.5.2.4.持久性:一旦提交不可逆,持久化到数据库
10.5.2.5.隔离性的问题:

  • 脏读:一个事物读取了另一个没有提交的事物
  • 不可重复读:在同一个事务内,重复读取表中的数据,表数据发生了改变
  • 虚读(幻读):在一个事务内,读取到了别人插入的数据,导致前后读出来结果不一致

10.5.3.实例

10.5.3.1.成功的

package lesson.four;import lesson.two.utils.JdbcUtils;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class TestTransaction1 {public static void main(String[] args) {Connection conn = null;PreparedStatement st = null;ResultSet rs = null;try {conn = JdbcUtils.getConnection();//关闭数据库的自动提交功能,此时会自动开启事务。即:关闭自动提交=开启事务conn.setAutoCommit(false);String sql1 = "UPDATE account SET money = money - 100 WHERE `NAME` = 'A'";st = conn.prepareStatement(sql1);st.executeUpdate();String sql2 = "UPDATE account SET money = money + 100 WHERE `NAME` = 'B'";st = conn.prepareStatement(sql2);st.executeUpdate();//业务完毕,提交事务conn.commit();;System.out.println("成功");} catch (SQLException e) {try {conn.rollback();} catch (SQLException ex) {throw new RuntimeException(ex);}throw new RuntimeException(e);} finally {{JdbcUtils.release(conn,st,rs);}}}
}
  • 结果
    在这里插入图片描述
    在这里插入图片描述->在这里插入图片描述

10.5.3.2.失败的

package lesson.four;import lesson.two.utils.JdbcUtils;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class TestTransaction2 {public static void main(String[] args) {Connection conn = null;PreparedStatement st = null;ResultSet rs = null;try {conn = JdbcUtils.getConnection();//关闭数据库的自动提交功能,此时会自动开启事务。即:关闭自动提交=开启事务conn.setAutoCommit(false);String sql1 = "UPDATE account SET money = money - 100 WHERE `NAME` = 'A'";st = conn.prepareStatement(sql1);st.executeUpdate();int x = 1/0;    //一定会出现异常(为了使该事务不能完全执行成功写的错误行)用于测试回滚String sql2 = "UPDATE account SET money = money + 100 WHERE `NAME` = 'B'";st = conn.prepareStatement(sql2);st.executeUpdate();//业务完毕,提交事务conn.commit();;System.out.println("成功");} catch (SQLException e) {try {conn.rollback();    //如果失败则默认回滚事务(这行不一定要写)} catch (SQLException ex) {throw new RuntimeException(ex);}throw new RuntimeException(e);} finally {{JdbcUtils.release(conn,st,rs);}}}
}
  • 结果
    在这里插入图片描述

执行conn.rollback(); //如果失败则默认回滚事务(这行不一定要写)
即使sql1对应的语句部分修改曾经执行成功过,但是由于回滚导致表中的最终结果不变
在这里插入图片描述

10.5.3.3.步骤总结

  • 开启事务conn.setAutoCommit(false);
  • 一组业务执行完毕,提交事务
  • 可以在catch语句中显示地定义‘回滚语句’,但即使不写,默认情况就会回滚

10.6.数据库连接池

10.6.1.“数据库连接——执行完毕——释放”这个“连接+释放”的过程十分浪费资源

10.6.2.池化技术:预先准备一些资源,需要使用资源时就可以直接使用预先准备好的

10.6.2.1.相当于:“开门——业务员:等待——服务”
10.6.2.2.最小连接数 根据 常用连接数 决定。e.g.常用10个连接->最小连接数是10
10.6.2.3.最大连接数:业务最高承载上限。e.g.承载上限是15则最大连接数是15。超出部分需要排队等待,如果排队等待的时间超过某个阈值(如:100ms’),则称为 超时等待

10.6.3.编写连接池只需要实现一个接口:DataSource

10.6.4.开源数据源实现

10.6.4.1.DBCP(DataBase connection pool)
10.6.4.2.C3P0
10.6.4.3.Druid:阿里巴巴的
10.6.4.4.使用了这些数据库连接池之后,个人在项目开发中就不需要编写连接数据库的代码了

10.6.5.DBCP

10.6.5.1.需要用到的jar包

下载地址都是官网,可参考这篇博客,导入方式和connector相同:https://blog.csdn.net/qq_45523411/article/details/121517140
在进行到新TestDBCP文件运行时发现报错:问题是2.0以上版本的dbcp需要再导入logging包,教程(内附有下载链接)如下:https://blog.csdn.net/qq_41115379/article/details/108947898
在这里插入图片描述
在这里插入图片描述

10.6.5.2.新建dbcpconfig.properties文件

在这里插入图片描述

#连接设置:这里的名字是DBCP数据源中定义好的
driverClassName = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://localhost:3306/p37jdbc?useUnicode=true & characterEncoding=utf8 & useSSL=true
username = root
password = 123456#以下所有内容都可以不手动设置
#<!-- 初始化连接 -->
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=READ_COMMITTED

10.6.5.3.新建utils文件

和JdbcUtils几乎一样,仅更换了输入流的来源
在这里插入图片描述

package lesson.five.utils;import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.commons.dbcp2.BasicDataSourceFactory;import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;public class JdbcUtils_DBCP {private static  DataSource dataSource = null;static {try{//获得类加载器.获取资源,获取的资源的名字:是src文件夹下的文件名,会返回一个输入流InputStream in = JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");//把流读到properties类里Properties properties = new Properties();properties.load(in);//创建数据源 工厂模式(用于创建对象)//点开BasicDataSourceFactory查看可见封装完毕的各种类,和lesson.two.utils中相比,个人所需书写的代码量减少了dataSource = BasicDataSourceFactory.createDataSource(properties);} catch (Exception e) {throw new RuntimeException(e);  //这是默认生成的
//            e.printStackTrace();  //这两行任选一行亦可}}//获取连接public static Connection getConnection() throws SQLException {return dataSource.getConnection();  //只需要在这里修改直接(从数据源中)获取连接即可}// 释放连接资源public static void release(Connection conn, Statement st, ResultSet rs){if(rs != null){try {rs.close();} catch (SQLException e) {throw new RuntimeException(e);}}if(st != null){try {st.close();} catch (SQLException e) {throw new RuntimeException(e);}}if(conn != null){try {conn.close();} catch (SQLException e) {throw new RuntimeException(e);}}}}

2024.4.16 Tuesday

10.6.5.4.新建TestDBCP文件

参考lesson.TestInsert,只修改部分的代码

package lesson.five;import lesson.five.utils.JdbcUtils_DBCP;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;public class TestDBCP {public static void main(String[] args) {Connection conn = null;PreparedStatement st = null;try {//本质是更换了数据源(在获取连接和关闭连接时代码有所区别),和lesson.three的TestInsert其他部分没有任何区别conn = JdbcUtils_DBCP.getConnection();//和一般的statement区别:使作为用问号作为占位符String sql = "INSERT INTO users(id,`NAME`,`PASSWORD`,`email`,`birthday`) VALUES (?,?,?,?,?)";st = conn.prepareStatement(sql);   //预编译SQL:先生成SQL但不执行//手动给参数赋值st.setInt(1,4); //idst.setString(2,"lqf");st.setString(3,"987654");st.setString(4,"27046873@qq.com");st.setDate(5,new java.sql.Date(new java.util.Date().getTime()));//执行int i = st.executeUpdate();if(i > 0){System.out.println("插入成功");}} catch (SQLException e) {e.printStackTrace();} finally {JdbcUtils_DBCP.release(conn,st,null);}}
  • 结果
    在这里插入图片描述
    在这里插入图片描述

10.6.6.C3P0

10.6.6.1.需要用到的jar包

参考教程:
打开压缩包后注意使用的jar包的名称不含有source,是lib文件夹下的文件
https://blog.csdn.net/YyjYsj/article/details/108854804
在这里插入图片描述

10.6.6.2.新建c3p0-config.xml文件

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config><!--
c3p0的缺省(默认)配置
如果在代码中"ComboPooledDataSource ds=new ComboPooledDataSource();"这样写就表示使用的是c3p0的缺省(默认)-->
<default-config><property name="driverClass">com.mysql.cj.jdbc.Driver</property><property name="jdbcUrl">jdbc:mysql://localhost:3306/p37jdbc?useUnicode=true &amp; characterEncoding=utf8 &amp; useSSL=true &amp; serverTimezone=UTC</property><property name="user">root</property><property name="password">123456</property><property name="acquiredIncrement">5</property><property name="initialPoolSize">10</property><property name="minPoolSize">5</property><property name="maxPoolSize">20</property>
</default-config><!--
c3p0的命名配置
如果在代码中"ComboPooledDataSource ds=new ComboPooledDataSource("MySQL");"这样写就表示使用的是name是mysql
&ndash;&gt;
--><named-config name="MySQL"><property name="driverClass">com.mysql.jdbc.Driver</property><property name="jdbcUrl">jdbc:mysql://localhost:3306/p37jdbc?useUnicode=true &amp; characterEncoding=utf8 &amp; useSSL=true</property><property name="user">root</property><property name="password">123456</property><property name="acquiredIncrement">5</property><property name="initialPoolSize">10</property><property name="minPoolSize">5</property><property name="maxPoolSize">20</property></named-config></c3p0-config>
<!--        这里人话说就是可以创建多个不同的数据库连接池~~-->

10.6.6.3.新建utils文件

在这里插入图片描述

package lesson.five.utils;import com.mchange.v2.c3p0.ComboPooledDataSource;import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;public class JdbcUtils_C3P0 {private static  ComboPooledDataSource dataSource = null;static {try {//代码版配置(但是一般不使用)
//            dataSource = new ComboPooledDataSource();
//            dataSource.setDriverClass();
//            dataSource.setUser();
//            dataSource.setPassword();
//            dataSource.setJdbcUrl();
//
//            dataSource.setMaxPoolSize();
//            dataSource.setMinPoolSize();//创建数据源 工厂模式(用于创建对象)dataSource = new ComboPooledDataSource("MySQL");   //配置文件写法。也可在()内添加已完成的“命名配置”} catch (Exception e) {throw new RuntimeException(e);  //这是默认生成的
//            e.printStackTrace();  //这两行任选一行亦可}}//获取连接public static Connection getConnection() throws SQLException {return dataSource.getConnection();  //只需要在这里修改直接(从数据源中)获取连接即可}// 释放连接资源public static void release(Connection conn, Statement st, ResultSet rs){if(rs != null){try {rs.close();} catch (SQLException e) {throw new RuntimeException(e);}}if(st != null){try {st.close();} catch (SQLException e) {throw new RuntimeException(e);}}if(conn != null){try {conn.close();} catch (SQLException e) {throw new RuntimeException(e);}}}}

10.6.6.4.新建TestC3P0文件

package lesson.five;import lesson.five.utils.JdbcUtils_C3P0;
import lesson.five.utils.JdbcUtils_DBCP;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;public class TestC3P0 {public static void main(String[] args) {Connection conn = null;PreparedStatement st = null;try {//本质是更换了数据源(在获取连接和关闭连接时代码有所区别),和lesson.three的TestInsert其他部分没有任何区别conn = JdbcUtils_C3P0.getConnection();  //和lesson.five.TestDBCP相比的区别就是修改了这(使用外部包)//和一般的statement区别:使作为用问号作为占位符String sql = "INSERT INTO users(id,`NAME`,`PASSWORD`,`email`,`birthday`) VALUES (?,?,?,?,?)";st = conn.prepareStatement(sql);   //预编译SQL:先生成SQL但不执行//手动给参数赋值//set...的语法对应了传入函数参数每个位置以及希望设置成的参数st.setInt(1,5); //idst.setString(2,"wlj");st.setString(3,"456789");st.setString(4,"27046873@qq.com");st.setDate(5,new java.sql.Date(new java.util.Date().getTime()));//new Date().getTime()即:外层括号内是计算机的时间,需要转化成mysql的时间//sql.Date是数据库时间,util.Date是Java的//因为setDate的源码中时间的参数是数据库类型的:void setDate(int parameterIndex, java.sql.Date x)//所以要另外用new Date().getTime()获得时间戳(这个版本里需要使用“new java.util.Date().getTime()”才不报错)//执行int i = st.executeUpdate();if(i > 0){System.out.println("插入成功");}} catch (SQLException e) {e.printStackTrace();} finally {JdbcUtils_C3P0.release(conn,st,null);}}
}
  • 结果
    在这里插入图片描述
    在这里插入图片描述

10.6.6.5.结论:无论使用什么数据源,本质相同,DataSource接口不会变,方法就不会变

10.6.7.下载jar包网址备份

https://mvnrepository.com/

这篇关于【WEEK8】 【DAY1】【DAY2】JDBC—事务数据库连接池【中文版】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/909144

相关文章

MySQL的JDBC编程详解

《MySQL的JDBC编程详解》:本文主要介绍MySQL的JDBC编程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言一、前置知识1. 引入依赖2. 认识 url二、JDBC 操作流程1. JDBC 的写操作2. JDBC 的读操作总结前言本文介绍了mysq

Linux下MySQL数据库定时备份脚本与Crontab配置教学

《Linux下MySQL数据库定时备份脚本与Crontab配置教学》在生产环境中,数据库是核心资产之一,定期备份数据库可以有效防止意外数据丢失,本文将分享一份MySQL定时备份脚本,并讲解如何通过cr... 目录备份脚本详解脚本功能说明授权与可执行权限使用 Crontab 定时执行编辑 Crontab添加定

Spring 中的切面与事务结合使用完整示例

《Spring中的切面与事务结合使用完整示例》本文给大家介绍Spring中的切面与事务结合使用完整示例,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考... 目录 一、前置知识:Spring AOP 与 事务的关系 事务本质上就是一个“切面”二、核心组件三、完

如何通过try-catch判断数据库唯一键字段是否重复

《如何通过try-catch判断数据库唯一键字段是否重复》在MyBatis+MySQL中,通过try-catch捕获唯一约束异常可避免重复数据查询,优点是减少数据库交互、提升并发安全,缺点是异常处理开... 目录1、原理2、怎么理解“异常走的是数据库错误路径,开销比普通逻辑分支稍高”?1. 普通逻辑分支 v

Python与MySQL实现数据库实时同步的详细步骤

《Python与MySQL实现数据库实时同步的详细步骤》在日常开发中,数据同步是一项常见的需求,本篇文章将使用Python和MySQL来实现数据库实时同步,我们将围绕数据变更捕获、数据处理和数据写入这... 目录前言摘要概述:数据同步方案1. 基本思路2. mysql Binlog 简介实现步骤与代码示例1

使用shardingsphere实现mysql数据库分片方式

《使用shardingsphere实现mysql数据库分片方式》本文介绍如何使用ShardingSphere-JDBC在SpringBoot中实现MySQL水平分库,涵盖分片策略、路由算法及零侵入配置... 目录一、ShardingSphere 简介1.1 对比1.2 核心概念1.3 Sharding-Sp

Go语言连接MySQL数据库执行基本的增删改查

《Go语言连接MySQL数据库执行基本的增删改查》在后端开发中,MySQL是最常用的关系型数据库之一,本文主要为大家详细介绍了如何使用Go连接MySQL数据库并执行基本的增删改查吧... 目录Go语言连接mysql数据库准备工作安装 MySQL 驱动代码实现运行结果注意事项Go语言执行基本的增删改查准备工作

MySQL 数据库表操作完全指南:创建、读取、更新与删除实战

《MySQL数据库表操作完全指南:创建、读取、更新与删除实战》本文系统讲解MySQL表的增删查改(CURD)操作,涵盖创建、更新、查询、删除及插入查询结果,也是贯穿各类项目开发全流程的基础数据交互原... 目录mysql系列前言一、Create(创建)并插入数据1.1 单行数据 + 全列插入1.2 多行数据

MySQL 数据库表与查询操作实战案例

《MySQL数据库表与查询操作实战案例》本文将通过实际案例,详细介绍MySQL中数据库表的设计、数据插入以及常用的查询操作,帮助初学者快速上手,感兴趣的朋友跟随小编一起看看吧... 目录mysql 数据库表操作与查询实战案例项目一:产品相关数据库设计与创建一、数据库及表结构设计二、数据库与表的创建项目二:员

MybatisPlus中removeById删除数据库未变解决方案

《MybatisPlus中removeById删除数据库未变解决方案》MyBatisPlus中,removeById需实体类标注@TableId注解以识别数据库主键,若字段名不一致,应通过value属... 目录MyBATisPlus中removeBypythonId删除数据库未变removeById(Se