当前位置: 首页 > news >正文

事务(理解)与数据库连接池

一、什么是事务

事务是数据库提供的一个特性。
事务:组成各个数据的执行的单元,要么都成功,要么都不成功。
举例:
  转账的功能,冠希给美美转 1000 元钱。
  使用事务
  先给冠希扣除掉 1000
  再给美美加上 1000
  事务结束了

二、事物的特性

  • 原子性(Atomicity):事务中的操作是一个不可分割的整体,要么全部成功,要么全部失败。例如,在银行转账中,扣款和入账必须同时成功,否则就回滚到初始状态。​
  • 一致性(Consistency):事务执行前后,数据库都必须处于合法的状态。比如,转账前后,双方账户的总金额应该保持不变。​
  • 隔离性(Isolation):多个事务并发执行时,一个事务的执行不能被其他事务干扰,每个事务都感觉像是在独立执行。​
  • 持久性(Durability):一旦事务提交成功,它对数据库的修改就会永久保存,即使系统发生故障也不会丢失。

三、客户端进行事务操作

第一种方式—开启事务

开启事务

执行转账操作,aaa付给bbb100

UPDATE account SET money = money - 100 where name = "aaa";
UPDATE account SET money = money + 100 where name = "bbb";

执行回滚操作

可以看到数据回滚成功

回滚或者提交都代表事务已经结束,所以再次执行相同的操作,回滚不会生效!

第二种方式—设置不默认提交

多次执行转账操作

多次执行回滚操作发现都可以生效

由此可知设置自动提交为off,执行回滚或者提交,事务不会结束

四、使用JDBC进行事务操作

jdbc进行事务操作只有一种方式——设置不默认提交

调用connection的setAutoCommit方法,设置autoCommit为false

import java.sql.*;
public class TransactionExample {public static void main(String[] args) {try (Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/spring_db", "root", "2762089616..")) {// 关闭自动提交connection.setAutoCommit(false);try (Statement statement = connection.createStatement()) {// 执行多个SQL语句statement.executeUpdate("UPDATE account SET money = money - 100 where name = 'aaa'");statement.executeUpdate("UPDATE account SET money = money + 100 where name = 'bbb'");// 提交事务connection.commit();} catch (SQLException e) {// 发生异常时回滚事务connection.rollback();e.printStackTrace();}} catch (SQLException e) {e.printStackTrace();}}
}

五、JDBC操作数据库

JDBC操作数据库的步骤

jdbc操作数据库需要经历以下步骤:

1、加载数据库驱动

在使用 JDBC 操作数据库之前,首先需要加载对应的数据库驱动。不同的数据库厂商提供了各自的驱动程序,例如:​

  • MySQL:com.mysql.cj.jdbc.Driver​
  • Oracle:oracle.jdbc.driver.OracleDriver​
  • SQL Server:com.microsoft.sqlserver.jdbc.SQLServerDriver​

加载驱动的方式有两种:​

1.1 使用Class.forName()方法(反射方式)

try {Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {e.printStackTrace();
}

1.2 直接创建

try {// 直接实例化MySQL驱动(MySQL 8.x及以上版本)new com.mysql.cj.jdbc.Driver();// 或者直接实例化Oracle驱动// new oracle.jdbc.driver.OracleDriver();System.out.println("驱动加载成功!");
} catch (Exception e) {System.err.println("驱动加载失败:" + e.getMessage());
}

2、建立数据库连接

加载驱动后,需要建立与数据库的连接。通过DriverManager.getConnection()方法可以获取一个Connection对象,该对象代表与数据库的连接。连接数据库时需要提供数据库的 URL、用户名和密码等信息。

Connection connection = DriverManager.getConnection(url, username, password));

3、创建Statement对象

建立连接后,需要创建Statement对象(或其子类PreparedStatement、CallableStatement)来执行 SQL 语句。

 PreparedStatement preparedStatement = connection.prepareStatement(sql)) {​preparedStatement.setString(1, "John");​preparedStatement.setInt(2, 30);​}

4、执行sql语句,返回结果集

根据不同的需求,使用Statement对象执行相应的 SQL 语句

 ResultSet resultSet = statement.executeQuery(sql)) ;

5、遍历结果集然后输出

while(resultSet.next()){Account account =new Account(resultSet.getInt("id"), resultSet.getString("name"), resultSet.getString("money"));System.out.println(account);
}

6、关闭资源

在完成数据库操作后,需要关闭相关资源,包括ResultSet、Statement和Connection对象,关闭资源时遵守先开后闭规则

if(rs!=null){try {rs.close();} catch (SQLException e) {e.printStackTrace();}
}
if(stmt!=null) {try {tmt.close();} catch (SQLException e) {e.printStackTrace();}
}
if(conn!=null){try {conn.close();} catch (SQLException e) {e.printStackTrace();}
}

        在执行不同的sql语句时我们发现代码有共同部分重复编写,为了简化代码,提高耦合度,我们不妨把原有代码的共同部分进行提取,写入工具类中

JDBCUtil 1.0版本

该工具类将共有的加载驱动、创建Connection连接和关闭资源进行封装

package com.qcby.util;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;public class JdbcUtil {public static void createDriver() throws ClassNotFoundException {Class.forName("com.mysql.jdbc.Driver");}public static Connection getConnection() throws ClassNotFoundException, SQLException {createDriver();Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/spring_db", "root", "2762089616..");return connection;}public static void close(Connection conn, Statement stmt, ResultSet rs){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 void close(Connection conn, Statement stmt){close(conn, stmt, null);}public static void close(Connection conn) {close(conn, null, null);}
}

JDBCUtil 2.0版本

2.0版本中,数据库连接信息(URL、USER、PASSWORD)是代码中固定的。2.0版本将数据库连接信息(URL、USER、PASSWORD)通过静态代码块从jdbc.properties文件中加载得到

package com.qcby.util;import com.alibaba.druid.pool.DruidDataSource;import java.io.IOException;
import java.sql.*;
import java.util.Properties;public class JdbcUtil {private static String URL = null;private static String USER = null;private static String PASSWORD = null;static {Properties properties = new Properties();try {properties.load(JdbcUtil.class.getResourceAsStream("/jdbc.properties"));URL = properties.getProperty("url");USER = properties.getProperty("username");PASSWORD = properties.getProperty("password");} catch (IOException e) {e.printStackTrace();}}public static void createDriver() throws ClassNotFoundException {Class.forName("com.mysql.jdbc.Driver");}public static Connection getConnection() throws ClassNotFoundException, SQLException {createDriver();Connection connection = DriverManager.getConnection(URL, USER, PASSWORD);return connection;}public static void close(Connection conn, Statement stmt, ResultSet rs){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 void close(Connection conn, Statement stmt){close(conn, stmt, null);}public static void close(Connection conn) {close(conn, null, null);}
}

JDBCUtil 3.0版本

2.0版本中,数据库连接信息(URL、USER、PASSWORD)是通过静态代码块从jdbc.properties文件中加载的。3.0版本在此基础上引入了Druid连接池,以提高数据库连接的效率和性能。

package com.qcby.util;import com.alibaba.druid.pool.DruidDataSource;import java.sql.Connection;
import java.sql.SQLException;public class DruidUtil {private static String URL = null;private static String USER = null;private static String PASSWORD = null;private static DruidDataSource druidDataSource = null;private static Connection connection = null;private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();static {druidDataSource = new DruidDataSource();druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");druidDataSource.setUrl("jdbc:mysql://localhost:3306/spring_db");druidDataSource.setUsername("root");druidDataSource.setPassword("2762089616..");druidDataSource.setInitialSize(1);druidDataSource.setMaxActive(10);druidDataSource.setMaxWait(3000);}public static DruidDataSource getDataSource() {return druidDataSource;}public static Connection getConnection() throws SQLException {if(connection == null || connection.isClosed()){connection = getDataSource().getConnection();}threadLocal.set(connection);return connection;}public static void closeConnection() throws SQLException {if(connection!= null){threadLocal.remove();connection.close();}}}

相关文章:

  • 【AI论文】作为评判者的感知代理:评估大型语言模型中的高阶社会认知
  • 【Java学习笔记】instanceof操作符
  • Quantum convolutional nerual network
  • Web开发—Vue工程化
  • stm32实战项目:无刷驱动
  • 期刊 | 《电讯技术》
  • 信息安全管理与评估索引
  • C++中什么是函数指针?
  • 嵌入式STM32学习——振动传感器
  • fast-livo2原理
  • 匈牙利算法
  • all-in-one方式安装kubersphere时报端口连接失败
  • 软件设计师-错题笔记-软件工程基础知识
  • Bash 字符串语法糖详解
  • 产业带数据采集方案:1688 API 接口开发与实时数据解析实践
  • 运算放大器稳定性分析
  • PHP API安全设计四要素:构建坚不可摧的接口防护体系
  • .Net HttpClient 发送Http请求
  • Java SolonMCP 实现 MCP 实践全解析:SSE 与 STDIO 通信模式详解
  • Linux——MySQL内置函数与复合查询
  • 马上评丨未成年人“擦边”短视频岂能成流量密码
  • 石家庄推动城市能级与民生福祉并进
  • 汉斯·季默:不会指挥的声音工程师终成音乐“大神”
  • 雷军:过去一个多月是创办小米以来最艰难的时间
  • 巴基斯坦军方:印度导弹袭击巴首都附近空军基地
  • 上海发布首份直播电商行业自律公约,禁止虚假宣传、商业诋毁