JDBC 编程之事务处理

数据库是一个多用户使用的共享资源,当多个用户并发的存取数据时,数据库

中就会可能发生多个用户同时存取同一数据的情况

若对并发操作不加控制,就可能会产生和读取不正确的数据,破坏数据的一致性

而事务正是并发控制的基本单位。所谓事务,是一个操作序列,这些操作要么都

执行,要么都不执行,是一个不可分割的工作单位

事务也是数据库维护数据一致性的单位,在每个事务结束时,都能保持数据的一致性

在编程中,可以把数据库事务看做是一组 SQL 语句,这组 SQL 语句是一个逻辑工作

单元,它们是不可分割的,其执行结果应该作为一个整体,永久性的修改数据库内容,

或 作为一个整体,取消对数据库的修改

事务的四个基本特征

(1)原子性

事务中包含的操作,看做是一个逻辑单元,这个逻辑单元中的操作

要么全部成功,要么全部失败

这也意味着事务中的所有元素,作为一个整体 提交 或 回滚

「事务的所有元素是不可分割的,是一个完整的操作」

(2)一致性

事务开始之前,和事务结束以后,数据库都处于一致性状态,数据库

的完整性约束,没有被破坏

(3)隔离性

对数据库进行修改的多个事务,是彼此隔离的

即 事务必须是独立的,不应该以任何形式影响其他事务

(4)持久性

事务完成之后,对于系统的影响是永久的,该修改真实的修改了

数据库,即使系统出现故障,也会一直保留

与事务相关的 SQL 语句:

开始事务:BEGIN TRANSACTION

提交事务:COMMIT TRANSACTION

回滚事务:ROLLBACK TRANSACTION

程序示例:

首先下载 MySQL 的 JDBC 驱动,下载链接:

https://dev.mysql.com/downloads/connector/j/

mysql-connector-java-5.1.41.zip 解压后一览:

工程名:JDBCTest

包名:com.siwuxie095.jdbc

类名:TransactionTest.java、TransactionTestX.java

打开资源管理器,在工程 JDBCTest 文件夹下,创建一个文件夹:lib,

在其中放入:mysql-connector-java-5.1.41-bin.jar

工程结构目录如下:

选择 mysql-connector-java-5.1.41-bin.jar,右键->Build Path->Add to Build Path

此时,工程结构目录一览:

TransactionTest.java:

package com.siwuxie095.jdbc;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.Statement;

//实际上将数据库信息硬编码到java代码中,不可取

public class TransactionTest {

public static Connection getConnection() {

Connection conn=null;

try {

Class.forName(“com.mysql.jdbc.Driver”);

conn=DriverManager.getConnection(“jdbc:mysql://localhost:3306/sims_db”,“root”,“8888”);

} catch (Exception e) {

e.printStackTrace();

System.err.println(“加载数据库失败…”);

}

return conn;

}

public static void insertStuPassword() {

Connection conn=getConnection();

try {

String sql=“insert into stu_password(stu_id,stu_pwd)”+

“values(‘005’,‘005’)”;

Statement st=conn.createStatement();

int count=st.executeUpdate(sql);

System.out.println(“向stu_password表中插入了 “+count+” 条记录”);

} catch (Exception e) {

e.printStackTrace();

}

}

public static void insertStuInfo() {

Connection conn=getConnection();

try {

/**

  • stu_id是主键,出现异常:

  • 即stu_password和stu_info两张表不一致,本来小黄的stu_id是005

  • 其中 insertStuPassword() 中已经插入了小黄的stu_id 和 stu_pwd

  • 而 insertStuInfo(),却因为输错了已经存在的 stu_id:004 而无法插入

  • (即 一个插进去了,一个没有插进去,导致数据不一致)

*/

String sql=“insert into stu_info(stuid,stu_name,stu_sex,stu_scademic,stu_major)”+

“values(‘004’,‘小黄’,‘男’,‘工程学院’,‘土木工程’)”;

Statement st=conn.createStatement();

int count=st.executeUpdate(sql);

System.out.println(“向stu_info表中插入了 “+count+” 条记录”);

} catch (Exception e) {

e.printStackTrace();

}

}

public static void main(String[] args) {

insertStuPassword();

insertStuInfo();

}

}

TransactionTestX.java:

package com.siwuxie095.jdbc;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

import java.sql.Statement;

//实际上将数据库信息硬编码到java代码中,不可取

public class TransactionTestX {

public static Connection getConnection() {

Connection conn=null;

try {

Class.forName(“com.mysql.jdbc.Driver”);

conn=DriverManager.getConnection(“jdbc:mysql://localhost:3306/sims_db”,“root”,“8888”);

} catch (Exception e) {

e.printStackTrace();

System.err.println(“加载数据库失败…”);

}

return conn;

}

//将SQLException抛给上层调用方法进行处理

public static void insertStuPassword(Connection conn) throws SQLException {

String sql = “insert into stu_password(stu_id,stu_pwd)” + “values(‘005’,‘005’)”;

Statement st = conn.createStatement();

int count = st.executeUpdate(sql);

System.out.println(“向stu_password表中插入了 " + count + " 条记录”);

}

public static void insertStuInfo(Connection conn) throws SQLException {

/**

  • stu_id是主键,出现异常:

  • 即stu_password和stu_info两张表不一致,本来小黄的stu_id是005

  • 其中 insertStuPassword() 中已经插入了小黄的stu_id 和 stu_pwd

  • 而 insertStuInfo(),却因为输错了已经存在的 stu_id:004 而无法插入

  • (即 一个插进去了,一个没有插进去,此时,可使事务回滚,使之都不插入,保持一致性)

*/

String sql = “insert into stu_info(stu_id,stu_name,stu_sex,stu_academic,stu_major)”

  • “values(‘004’,‘小黄’,‘男’,‘工程学院’,‘土木工程’)”;

Statement st = conn.createStatement();

int count = st.executeUpdate(sql);

System.out.println(“向stu_info表中插入了 " + count + " 条记录”);

}

//在main方法中进行事务回滚

public static void main(String[] args) {

Connection conn=null;

try {

conn=getConnection();

conn.setAutoCommit(false);//禁止事务自动提交

insertStuPassword(conn);

insertStuInfo(conn);

conn.commit();//提交事务

} catch (SQLException e) {

System.out.println(“=捕获到 SQL 异常=”);

e.printStackTrace();

try {

conn.rollback();//回滚事务

System.out.println(“=事务回滚成功”);

} catch (Exception e2) {

e2.printStackTrace();

}

}finally {

try {

if (conn!=null) {

conn.close();

}

} catch (Exception e3) {

e3.printStackTrace();

}

}

}

}

对比 TransactionTest.java 和 TransactionTestX.java:

「事务处理使数据库的一致性没有被破坏」

注意:高版本的 JDBC 驱动需要指明是否进行 SSL 连接

即 加上:?characterEncoding=utf8&useSSL=false

或:

即 加上:?useUnicode=true&characterEncoding=utf-8&useSSL=false

总结 JDBC 编程流程:

(1)加载驱动:加载 JDBC 驱动程序

(2)打开连接:打开一个数据库连接

(3)执行查询:创建一个会话对象,执行增删改查等操作

(4)处理结果:处理查询的结果

(5)清理环境:关闭会话,关闭连接等操作,完成资源的清理工作

转载:https://www.cnblogs.com/siwuxie095/p/6696300.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值