通过代码示例跟我学JDBC对数据库的事务操作实例

合集下载

jdbc实操题

jdbc实操题

jdbc实操题好的,以下是一个简单的 JDBC 实操题:题目:使用 JDBC 连接 MySQL 数据库,查询 "students" 表中的所有数据。

要求:编写 Java 代码实现连接 MySQL 数据库,并查询 "students" 表中的所有数据。

输出查询结果。

示例代码:javaimport java.sql.*;public class JdbcExample {public static void main(String[] args) {String url = "jdbc:mysql://localhost:3306/mydatabase";String username = "root";String password = "password";try (Connection conn = DriverManager.getConnection(url, username, password);Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery("SELECT * FROM students")) {while (rs.next()) {int id = rs.getInt("id");String name = rs.getString("name");int age = rs.getInt("age");System.out.println("ID: " + id + ", Name: " + name + ", Age: " + age);}} catch (SQLException e) {e.printStackTrace();}}}解释:首先,我们定义了数据库连接的 URL、用户名和密码。

JDBC连接数据库代码示例

JDBC连接数据库代码示例

一:获取连接数据库对象的类:package com.JDBC;/**加载mysql驱动:*1:在工程下面新建文件夹lib;*2:把mysql的驱动文件拷贝到此文件夹下面*3:右击工程名,选择最下面的“首选项”,选择“Java Builde Path”;Libraries----Add JARs---"选择mysql的驱动文件"进行加载*//**数据库的连接操作,主要是通过包含在Java API包下的Class类中*的forName()进行。

通过Class.forName()来加载驱动程序*/示例1:import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.Statement;public class Tmp0{public static void main(String[]args)throws Exception{Class.forName("com.mysql.jdbc.Driver");Connectionconn=DriverManager.getConnection("jdbc:mysql://localhost:3306/db","root","");Statement st=conn.createStatement();st.execute("set names'utf8'");st.executeUpdate("insert into hh values('王英','67892')");ResultSet rs=st.executeQuery("select*from student");while(rs.next()){System.out.println(rs.getString("name"));System.out.println(rs.getString("pass"));}}}2import java.io.UnsupportedEncodingException;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import com.mysql.jdbc.Connection;public class DataBase{Connection con=null;Statement stat;ResultSet rs;int count;public DataBase()throws Exception{Class.forName("com.mysql.jdbc.Driver");con=(Connection)DriverManager.getConnection("jdbc:mysql://localhost:3306/db","root","");stat=con.createStatement();}public void selectDb(String sql)throws Exception{rs=stat.executeQuery(sql);System.out.println("姓名密码");while(rs.next()){System.out.print(rs.getString("name"));System.out.print(""+rs.getString("pass"));System.out.println();}}public void updateDb(String sql)throws Exception{sql=new String(sql.getBytes(),"utf-8");stat.executeUpdate(sql);System.out.println("成功了!!!!");}public void dbClose(){try{con.close();}catch(SQLException e){//TODO Auto-generated catch blocke.printStackTrace();}}}//主类public class DataBaseDemo{public static void main(String[]args)throws Exception{ DataBase t0=new DataBase();String sql="insert into student values('刘能','123321')";t0.updateDb(sql);String sql1="select*from student";t0.selectDb(sql1);t0.dbClose();}}。

JDBC连接MySQL数据库代码

JDBC连接MySQL数据库代码

JDBC连接MySQL数据库代码******************************************************1**********************************************************1import java.sql.DriverManager;2import java.sql.ResultSet;3import java.sql.SQLException;4import java.sql.Connection;5import java.sql.Statement;678public class MysqlDemo {9public static void main(String[] args) throws Exception {10 Connection conn = null;11 String sql;12// MySQL的JDBC URL编写⽅式:jdbc:mysql://主机名称:连接端⼝/数据库的名称?参数=值13// 避免中⽂乱码要指定useUnicode和characterEncoding14// 执⾏数据库操作之前要在数据库管理系统上创建⼀个数据库,名字⾃⼰定,15// 下⾯语句之前就要先创建javademo数据库16 String url = "jdbc:mysql://localhost:3306/javademo?"17 + "user=root&password=root&useUnicode=true&characterEncoding=UTF8";1819try {20// 之所以要使⽤下⾯这条语句,是因为要使⽤MySQL的驱动,所以我们要把它驱动起来,21// 可以通过Class.forName把它加载进去,也可以通过初始化来驱动起来,下⾯三种形式都可以22 Class.forName("com.mysql.jdbc.Driver");// 动态加载mysql驱动23// or:24// com.mysql.jdbc.Driver driver = new com.mysql.jdbc.Driver();25// or:26// new com.mysql.jdbc.Driver();2728 System.out.println("成功加载MySQL驱动程序");29// ⼀个Connection代表⼀个数据库连接30 conn = DriverManager.getConnection(url);31// Statement⾥⾯带有很多⽅法,⽐如executeUpdate可以实现插⼊,更新和删除等32 Statement stmt = conn.createStatement();33 sql = "create table student(NO char(20),name varchar(20),primary key(NO))";34int result = stmt.executeUpdate(sql);// executeUpdate语句会返回⼀个受影响的⾏数,如果返回-1就没有成功35if (result != -1) {36 System.out.println("创建数据表成功");37 sql = "insert into student(NO,name) values('2012001','陶伟基')";38 result = stmt.executeUpdate(sql);39 sql = "insert into student(NO,name) values('2012002','周⼩俊')";40 result = stmt.executeUpdate(sql);41 sql = "select * from student";42 ResultSet rs = stmt.executeQuery(sql);// executeQuery会返回结果的集合,否则返回空值43 System.out.println("学号\t姓名");44while (rs.next()) {45 System.out46 .println(rs.getString(1) + "\t" + rs.getString(2));// ⼊如果返回的是int类型可以⽤getInt()47 }48 }49 } catch (SQLException e) {50 System.out.println("MySQL操作错误");51 e.printStackTrace();52 } catch (Exception e) {53 e.printStackTrace();54 } finally {55 conn.close();56 }5758 }5960 }******************************************2*****************************************1 DBHelper.java2package com.hu.demo;34import java.sql.Connection;5import java.sql.DriverManager;6import java.sql.PreparedStatement;7import java.sql.SQLException;89public class DBHelper {10public static final String url = "jdbc:mysql://127.0.0.1/student";11public static final String name = "com.mysql.jdbc.Driver";12public static final String user = "root";13public static final String password = "root";1415public Connection conn = null;16public PreparedStatement pst = null;1718public DBHelper(String sql) {19try {20 Class.forName(name);//指定连接类型21 conn = DriverManager.getConnection(url, user, password);//获取连接22 pst = conn.prepareStatement(sql);//准备执⾏语句23 } catch (Exception e) {24 e.printStackTrace();25 }26 }2728public void close() {29try {30this.conn.close();31this.pst.close();32 } catch (SQLException e) {33 e.printStackTrace();34 }35 }36 }1 Demo.java2package com.hu.demo;34import java.sql.ResultSet;5import java.sql.SQLException;67public class Demo {89static String sql = null;10static DBHelper db1 = null;11static ResultSet ret = null;1213public static void main(String[] args) {14 sql = "select *from stuinfo";//SQL语句15 db1 = new DBHelper(sql);//创建DBHelper对象1617try {18 ret = db1.pst.executeQuery();//执⾏语句,得到结果集19while (ret.next()) {20 String uid = ret.getString(1);21 String ufname = ret.getString(2);22 String ulname = ret.getString(3);23 String udate = ret.getString(4);24 System.out.println(uid + "\t" + ufname + "\t" + ulname + "\t" + udate );25 }//显⽰数据26 ret.close();27 db1.close();//关闭连接28 } catch (SQLException e) {29 e.printStackTrace();30 }31 }3233 }*********************************************3********************************************************1/*JDBC231. 在Java中,软件功能都是由类来完成的。

通过代码示例跟我学JDBC对数据库的事务操作实例

通过代码示例跟我学JDBC对数据库的事务操作实例
Connection conn = DriverManager.getConnection("URL","userName","userPassWord");
insertUserInfoSql="insert
into
userInfo
insertUserContactInfoSql="insert
into
2 杨教授工作室,版权所有,盗版必究, 2/25 页
杨教授工作室 精心创作的优秀程序员 职业提升必读系列资料
(2)怎么解决这个问题呢? 我们可以把存款、提款、转账这三个商业对象注册到一个事务中去,当某个对象无法完 成操作的时候,其它的对象自动恢复成原来的状态。 这个关系可以用下面的图来表示。
因此,事务机制对于一些关键事务是很重要的,例如 ATM 机提款,提款有多个动作:修 改数据库以及数钱等,如果这其中有任何一个环节出错,那么其它已经实现的操作必须还原, 否则,就会出现,提款人没有拿到钱,但是卡上已经扣款等不可思议的事情发生。 6、事务处理的应用场合 这些应用在下列条件下应该维护数据的完整性(由应用的商务规则来定义): (1) 分布式访问一个单独的数据资源,以及 (2)从一个单独的应用构件访问分布式资源。 在这种情况,可能要求在(分布式)资源上的一组操作被当作一个工作单元 (unit)。在一 个工作单元中, 操作的所有部分一起成功或失败并恢复。 7、事务划分的基本原则 (1)原则一:使事务尽可能短小。 通过使事务尽量短小,您可以把阻碍其它事务的时间缩到最短,从而提高应用程序的可 伸缩性。保持事务尽可能短小的最好方法当然是不在事务中间做任何不必要耗费时间的事, 特别是不要在事务中间等待用户输入。 因为事务提供并发控制,这通常意味着资源管理器将代表您获得您在事务期间访问的数 据项的锁, 并且它必须一直持有这些锁, 直到事务结束 (前面所讨论的 ACID 特性, 其中 “ACID”

jdbc事务的基本使用方法

jdbc事务的基本使用方法

jdbc事务的基本使用方法JDBC事务是一组SQL语句指令,这些指令都需要以原子性的方式执行。

如果任何一条指令在事务执行期间发生错误,所有之前执行的指令都将被回滚到初始状态,如果所有指令都执行成功,它们将会同时被提交到数据库。

在Java编程语言中,可以通过使用JDBC事务来实现这个功能。

下面我们就来学习一下JDBC事务的基本使用方法。

1.获取连接:使用JDBC连接数据库需要连接到JDBC连接的数据库。

可以通过使用java.sql包中的DriverManaget类提供的getConnection方法来获取数据库连接。

2. 关闭自动提交:在进行JDBC事务处理时,需要手动提交或撤销所有事务处理。

在开启一个JDBC连接时,默认情况下会自动提交所有事务处理,这会使得事务处理的逻辑更加复杂,所以我们需要在开启连接之后,通过调用setAutoCommit(false)来关闭自动提交功能。

3.执行SQL语句: 在JDBC事务中,我们需要执行一系列的SQL语句来完成我们的业务逻辑。

通常我们使用Statement或PreparedStatement执行SQL语句,需要注意的是,这些语句都必须在已经关闭了自动提交的连接中执行。

4.提交事务:在所有的SQL语句都执行完毕之后,我们需要调用connection对象的commit()方法来提交所有的事务。

如果在提交事务时发生错误,也可以通过调用rollback()方法来回滚所有已经执行的操作。

5.释放资源:在事务处理结束之后,需要释放资源,包括关闭数据库连接、释放Statement和ResultSet对象等。

具体代码示例:```Connection conn = null;PreparedStatement pstmt = null;try {// 获取连接conn = DriverManager.getConnection(url, user, password);// 关闭自动提交conn.setAutoCommit(false);// 创建PreparedStatement对象pstmt = conn.prepareStatement("insert into user(name, age) values(?,?)");pstmt.setString(1, "张三");pstmt.setInt(2, 20);// 执行INSERT语句pstmt.executeUpdate();pstmt.setString(1, "李四");pstmt.setInt(2, 22);// 执行INSERT语句pstmt.executeUpdate();// 提交事务mit();} catch (SQLException e) {// 发生错误,回滚事务conn.rollback();} finally {// 释放资源if (pstmt != null) {pstmt.close();}if (conn != null) {conn.close();}}```以上是JDBC事务的基本使用方法,通过学习和实践,我们可以更好地理解和掌握JDBC事务的应用和实现。

跟我学Java JDBC数据库访问操作技术——JDBC事务管理技术在项目中的应用实例

跟我学Java JDBC数据库访问操作技术——JDBC事务管理技术在项目中的应用实例
杨教授工作室 精心创作的优秀程序员 职业提升必读系列资料
1.1
JDBC应用 JDBC 的事务控制技术 1、事务控制技术在银行账户系统中的应用示例 (1)假设有这样一个简单的编程任务 编写一段程序,将钱从一个银行账户转移到另一个账户。为了简化起见,两个账户都是 存放在内存里面的--也就是说你不用考虑跟数据库的交互。 但要求你的代码在并发环境中也必须能够正确执行,这里所谓的并发环境也就是指可能 存在多个线程同时调用你的转账函数,而所谓能够正确执行则是指任何线程都不能“看到” 系统处于不一致的状态(比如看到其中一个账户显示已被取出了一笔钱然而同时另一个账户 却显示还没有收到这笔钱)。 (2)加锁的银行账户 目前,用于协调并发程序的主导技术仍是锁和条件变量。在 Java 面向对象的语言中,每 个对象上都带有一个隐式的锁,而加锁则由 synchronized 方法来完成,但原理与经典的加锁 解锁是一样的。 因此,在 Java 程序中可以将银行账户类定义成下面这样: class Account { int balance; synchronized void withdraw( int n ) { balance = balance - n; } void deposit( int n ) { withdraw( -n ); } } 其中的 withdraw 方法必须是 synchronized 的,这样两个线程同时调用它的时候才不会 把 balance 减错了。synchronized 关键字的效果就等同于先对当前账户对象加锁,然后运行
2 杨教授工作室,版权所有,盗版必究, 2/11 页
杨教授工作室 精心创作的优秀程序员 职业提升必读系列资料
(1)标准的解决方案是规定一个全局统一的锁顺序,并按照递增顺序来进行加锁 采用这种做法的代码如下: if(from < to){ from.lock(); to.lock(); } else{ to.lock(); from.lock(); } 这个方法是可行的,但前提是必须事先知道要对哪些锁进行加锁,而后面这个条件并不 是总能满足的。例如,假设 from.withdraw 的实现当账户余额不足时就会从 from2 上提款。 遇到这种情况除非等到我们从 from 中提了钱否则是无法知道是否该对 from2 加锁的, 而另一 方面,一旦已经从 from 中提了钱,再想按“正确”顺序加锁便不可能了。 更何况 from2 这个账户可能根本就只应对 from 可见,而不应被 transfer 知道。而且退 一步说,就算 transfer 知道 from2 的存在,现在需要加的锁也已经由两个变成了三个(事先 还要记得将这些锁正确排序)。 (2)还有更糟的 如果我们需要在某些情况下阻塞(block),情况就会更加复杂。例如,要求 transfer 在 from 账户内余额不足的时候阻塞。这类问题通常的解决办法是在一个条件变量上等待,并 同时释放 from 的锁。 但更进一步, 如果要求当 from 和 from2 中的总余额不够的时候阻塞呢? 3、体验事务控制技术——了解取消 JDBC 中的默认提交 (1)常规的数据访问的编程实现的代码——使用 JDBC 中的默认的提交 public boolean insertOneUserInfo(UserInfoBasePO oneRegisterUserInfo) throws WebBankException { PreparedStatement pstmt=null; int returnResult=0; oneConnection=oneConnectDBBean.getConnection();

Java程序设计中的JDBC数据库访问与事务处理案例

Java程序设计中的JDBC数据库访问与事务处理案例JDBC(Java Database Connectivity)是在Java程序设计中用于访问数据库的一种标准接口。

通过JDBC,我们可以方便地连接、查询和操作各种类型的数据库。

除了基本的数据库访问功能外,JDBC还提供了事务处理的支持,使得我们可以在数据库操作中保持数据的一致性和完整性。

下面将介绍一个使用JDBC进行数据库访问与事务处理的案例。

案例背景:假设我们正在开发一个在线图书商城系统,其中涉及到对图书、用户和订单等数据的管理和操作。

我们需要设计一个Java程序,使用JDBC实现对数据库中图书、用户和订单的增删改查,并且能够保持相关操作的事务一致性。

案例步骤:1. 准备工作:a. 安装并配置数据库:在本案例中,我们以MySQL数据库为例,需安装并配置好MySQL数据库环境。

b. 创建数据库和表:根据系统需求,在MySQL中创建名为bookstore的数据库,并在此数据库中创建用于存储图书、用户和订单数据的表。

c. 导入JDBC驱动:为了使用JDBC连接数据库,需先导入相应的数据库驱动。

在本案例中,我们将使用MySQL的JDBC驱动。

将相关的JDBC驱动jar包导入到项目中。

2. 建立数据库连接:a. 加载JDBC驱动:在Java程序中,通过Class.forName()方法加载JDBC驱动类。

对于MySQL,加载驱动的代码如下:```javaClass.forName("com.mysql.cj.jdbc.Driver");```b. 建立数据库连接:通过指定数据库的URL、用户名和密码,调用DriverManager.getConnection()方法建立数据库连接:```javaString url = "jdbc:mysql://localhost:3306/bookstore";Connection connection = DriverManager.getConnection(url, "username", "password");```3. 执行数据库操作:a. 查询数据:通过创建Statement或PreparedStatement对象,使用SQL语句进行查询操作。

JAVA使用JDBC技术操作SqlServer数据库实例代码

JAVA使⽤JDBC技术操作SqlServer数据库实例代码JDBC(Java Data Base Connectivity,Java数据库连接)是⼀种⽤于执⾏SQL语句的Java API,可以为多种关系数据库提供统⼀访问,它由⼀组⽤Java语⾔编写的类和接⼝组成。

JDBC提供了⼀种基准,据此可以构建更⾼级的⼯具和接⼝,使数据库开发⼈员能够编写数据库应⽤程序。

JDBC并不能直接访问数据库,需要借助于数据库⼚商提供的JDBC驱动程序。

数据库连接如果要在Java访问数据库,⾸先要加载⼀个数据库驱动,数据库驱动只需要在第⼀次访问时加载⼀次。

然后再每次访问数据库时创建⼀个Connection实例,获取数据库连接,这样就可以执⾏操作数据库的SQL语句。

最后⽤完后释放掉数据库的连接。

数据库驱动类下完后在新建的java_project导⼊驱动包右击选中项⽬>>Build Path >>Add External Archives... 选中下载解压的⽂件导⼊成功后的项⽬:package com.Project_DataBase01;import java.sql.Connection;import java.sql.DriverManager;public class SelectQuery {private Connection conn;/** 创建⼀个返回Connection的⽅法*/public Connection getConnection(){try {Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");System.out.println("数据库驱动加载成功");conn=DriverManager.getConnection("jdbc:sqlserver://localhost:1433;DatabaseName=java_conn_test","sa","123456");if(conn==null){System.out.println("数据库连接失败");System.out.println("-----------------------");}else {System.out.println("数据库连接成功");System.out.println("-----------------------");}} catch (Exception e) {// TODO: handle exceptione.printStackTrace();}return conn;}}进⾏SqlServe数据库java_conn_test中的tb_User进⾏数据的增删改查。

Java基于jdbc连接mysql数据库操作示例

Java基于jdbc连接mysql数据库操作⽰例本⽂实例讲述了Java基于jdbc连接mysql数据库操作。

分享给⼤家供⼤家参考,具体如下:import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;public class MySQLDemo {private Connection conn = null;private Statement stmt = null;private ResultSet rs = null;private String driverclass = "com.mysql.jdbc.Driver";private String url = "jdbc:mysql://localhost:3306/mydb";private String user = "root";private String password = "111111";public MySQLDemo() {try {Class.forName(driverclass).newInstance(); // 加载驱动程序} catch (InstantiationException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (ClassNotFoundException e1) {// TODO Auto-generated catch blockSystem.out.println("class not found");}try {conn = DriverManager.getConnection(url, user, password); // 获得Connection对象} catch (Exception e) {System.out.println("Connect failed!");}}public void selectMethod(String sql) {System.out.println("id title");try {stmt = conn.createStatement(); // 获得Statement对象rs = stmt.executeQuery(sql); // 执⾏SQL语句,并返回ResultSet类型的结果while (rs.next()) {String title = rs.getString("id");String name = rs.getString("name");System.out.println(title + " " + name);}} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public void closeDB() throws SQLException {if (rs != null)rs.close();if (stmt != null)stmt.close(); // 关闭Statement对象if (conn != null) // 关闭Connection对象conn.close();}public static void main(String args[]) {MySQLDemo demo = new MySQLDemo();demo.selectMethod("select * from test");}}⽤JDBC来连接数据库,基本步骤都⼤同⼩异,只不过不同的数据库之间的URL有些不同。

java中JDBC连接数据库代码和步骤详解及实例代码

java中JDBC连接数据库代码和步骤详解及实例代码java 中JDBC连接数据库代码和步骤详解JDBC连接数据库•创建⼀个以JDBC连接数据库的程序,包含7个步骤:1、加载JDBC驱动程序:在连接数据库之前,⾸先要加载想要连接的数据库的驱动到JVM(Java虚拟机),这通过ng.Class类的静态⽅法forName(String className)实现。

例如:try{//加载MySql的驱动类Class.forName("com.mysql.jdbc.Driver") ;}catch(ClassNotFoundException e){System.out.println("找不到驱动程序类,加载驱动失败!");e.printStackTrace() ;}成功加载后,会将Driver类的实例注册到DriverManager类中。

2、提供JDBC连接的URL•连接URL定义了连接数据库时的协议、⼦协议、数据源标识。

•书写形式:协议:⼦协议:数据源标识协议:在JDBC中总是以jdbc开始⼦协议:是桥连接的驱动程序或是数据库管理系统名称。

数据源标识:标记找到数据库来源的地址与连接端⼝。

例如:(MySql的连接URL)jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=gbk ;useUnicode=true:表⽰使⽤Unicode字符集。

如果characterEncoding设置为gb2312或GBK,本参数必须设置为true 。

characterEncoding=gbk:字符编码⽅式。

3、创建数据库的连接•要连接数据库,需要向java.sql.DriverManager请求并获得Connection对象,该对象就代表⼀个数据库的连接。

•使⽤DriverManager的getConnectin(String url , String username , String password )⽅法传⼊指定的欲连接的数据库的路径、数据库的⽤户名和密码来获得。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
3 杨教授工作室,版权所有,盗版必究, 3/25 页
杨教授工作室 精心创作的优秀程序员 职业提升必读系列资料
的“I”代表“隔离”---Isolation,也就是说,一个事务的结果影响不到与该事务并发执行 的其它事务)。 当您拥有锁时,任何需要访问您锁定的数据项的其它事务将不得不一直等待,直到您释 放锁。如果您的事务很长,那些其它的所有事务都将被锁定,您的应用程序吞吐量将大幅度 下降。 (2)原则二:在事务期间不要等待用户输入 (3)原则三:把相关操作归到单个事务中,但把不相关的操作放到单独的事务中 根据前面的原则一中所要求的事务应尽可能短小,我们必须把一些操作归到一个事务中来维 护一致性。 8、数据库操作过程中可能出现的三种不确定情况: (1)脏读取(Dirty Reads) 一个事务读取了另一个并行事务未提交的数据。 (2)不可重复读取(Non-repeatable Reads) 一个事务再次读取之前的数据时,得到的数据不一致,被另一个已提交的事务修改。 (3)虚读(Phantom Reads) 一个事务重新执行一个查询,返回的记录中包含了因为其他最近提交的事务而产生的新 记录。 9、标准 SQL 规范中,为了避免上面 3 种情况的出现,定义了四个事务隔离等级 (1)Read Uncommitted 最低等级的事务隔离,仅仅保证了读取过程中不会读取到非法数据。上诉 3 种不确定情 况均有可能发生。 (2)Read Committed 大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已修改但 未提交的数据,避免了“脏读取”。该级别适用于大多数系统。 (3)Repeatable Read 保证了一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据。避免了“脏 读取”和“不可重复读取”的情况,但是带来了更多的性能损失。 (4)Serializable
2 杨教授工作室,版权所有,盗版必究, 2/25 页
杨教授工作室 精心创作的优秀程序员 职业提升必读系列资料
(2)怎么解决这个问题呢? 我们可以把存款、提款、转账这三个商业对象注册到一个事务中去,当某个对象无法完 成操作的时候,其它的对象自动恢复成原来的状态。 这个关系可以用下面的图来表示。
因此,事务机制对于一些关键事务是很重要的,例如 ATM 机提款,提款有多个动作:修 改数据库以及数钱等,如果这其中有任何一个环节出错,那么其它已经实现的操作必须还原, 否则,就会出现,提款人没有拿到钱,但是卡上已经扣款等不可思议的事情发生。 6、事务处理的应用场合 这些应用在下列条件下应该维护数据的完整性(由应用的商务规则来定义): (1) 分布式访问一个单独的数据资源,以及 (2)从一个单独的应用构件访问分布式资源。 在这种情况,可能要求在(分布式)资源上的一组操作被当作一个工作单元 (unit)。在一 个工作单元中, 操作的所有部分一起成功或失败并恢复。 7、事务划分的基本原则 (1)原则一:使事务尽可能短小。 通过使事务尽量短小,您可以把阻碍其它事务的时间缩到最短,从而提高应用程序的可 伸缩性。保持事务尽可能短小的最好方法当然是不在事务中间做任何不必要耗费时间的事, 特别是不要在事务中间等待用户输入。 因为事务提供并发控制,这通常意味着资源管理器将代表您获得您在事务期间访问的数 据项的锁, 并且它必须一直持有这些锁, 直到事务结束 (前面所讨论的 ACID 特性, 其中 “ACID”
杨教授工作室 精心创作的优秀程序员 职业提升必读系列资料
1.1
通过代码示例跟我学 JDBC 对数据库的事务操作实例
1.1.1 数据库事务及事务的特性 1、事务概述 事务是一组原子操作(执行一组 SQL)的工作单元,这个工作单元中的所有原子操作在执 行期间,与其它事务隔离,以避免数据源的交相更新而发生混乱,事务中的所有原子操作, 要嘛全部执行成功,要嘛全部失败(即使只有一个失败,所有的原子操作也要全部撤消)。 2、事务及事务的特性 在 JDBC 的数据库操作中,一项事务是由一条或是多条表达式所组成的一个不可分割的工 作单元。事务具有原子性、隔离性等的 ACID (代表不可分割性 ---atomicity 、一致性 ---consistency、隔离性----isolation 和稳定性----durability)。 (1)Atomic(原子性):事务中包含的操作被看作一个逻辑单元,这个逻辑单元中的操作要 么全部成功,要么全部失败。 (2)Consistency(一致性):只有合法的数据可以被写入数据库,否则事务应该将其回滚到 最初状态。 (3)Isolation(隔离性):事务允许多个用户对同一个数据的并发访问,而不破坏数据的正 确性和完整性。同时,并行事务的修改必须与其他并行事务的修改相互独立。 (4)Durability(持久性):事务结束后,事务处理的结果必须能够得到固化。 3、应用示例 通过一个去银行从储蓄帐户转存 500 美元到支票帐户的示例,可以帮助我们了解事务的 ACID 这四个特性的含意。 这里实际上发生了两个操作:首先,从储蓄帐户取出 500 美元,然后将这 500 美元存 到您的支票帐户里。如果两个操作都成功,您和银行都会满意。如果两个操作都失败,您们 也不必紧张,大家都可以接受这个结果,只要稍后再试一次就行了。 现在想象一下, 如果在帐户转存操作过程中银行的计算机崩溃了-----由于计算机可能会因 停电、网络中断等而出现故障,会发生什么情况?首先,假设银行计算机崩溃正好发生在从 储蓄帐户中取出 500 美元后,但在存入支票帐户之前。这样,您就会损失 500 美元。
1 杨教授工作室,版权所有,盗版必究, 1/25 页
杨教授工作室 精心创作的优秀程序员 职业提升必读系列资料
现在假设另外一种情况:如果在 500 美元记入支票帐户后,但在从储蓄帐户中取出之前 发生银行计算机崩溃,又会发生什么情况呢。您会很高兴,但银行是不会接受的。这两个操 作必需同时成功或同时失败------这就是原子性的定义。 (1)在此例中,一致性的含义是指存入支票帐户的钱数应与从储蓄帐户中取出的钱数相等。 借助于事务处理系统,一致性由应用程序逻辑来强制实施。 (2)隔离性的含义是与帐户转存并发执行的单独事务不应看到无效的中间状态。在此例中, 如果从储蓄帐户中取出 500 美元,您永远看不到这 500 美元尚未存到支票帐户的情况。隔 离性通常用锁定来实现。 (3)持久性的含义是在事务提交后,由事务进行的更新永远不会丢失。在事务提交之后,系 统崩溃、网络故障,甚至有人不小心拔出了电源线都不应造成更新丢失。大多数数据库(以 及其他类型的事务性资源)通过先将所有需要进行的更改写入持久存储的日记文件中,来确 保持久性。只有在写入日记文件后,才会提交事务。如果在事务提交后系统崩溃或有人从插 座中拔出电源插头,资源管理器会读取其日志并重试所有非永久性的已提交事务,或尝试回 滚所有已中止的事务。 4、什么场合下应该考虑应用事务处理 在一个操作中,如果牵涉到多个永久存储,而且是多步完成,并且需要修改数据的时候, 就一定要考虑加上事务处理。 5、为什么要提供事务 (1)事务是一种手段,用于保证一系列的数据库操作能够准确的完成。 使用事务的一个重要原因,是完成一个操作可能需要使用多步,其中任何一步操作的失 败,都希望全部回滚。以银行转账系统为例: 如下图所示,转账是通这是不允许的。
相关文档
最新文档