JDBC学习笔记——事务、存储过程以及批量处理
1、事务
1.1、事务的基本概念和使用示例
数据库事务,是指作为单个逻辑工作单元执行的一系列操作,要么完整地执行,要么完全地不执行。 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性。
JDBC可以操作Connection的setAutoCommit()方法,给它false参数,提示数据库启动事务,在下达一连串的SQL命令后,自行调用Connection的commit()方法,提示数据库确认(Commit)操作。如果中间发生错误,则调用rollback(),提示数据库撤销(ROLLBACK)所有执行。同时,如果仅想要撤回某个SQL执行点,则可以设置存储点(SAVEPOINT)。一个示范的事务流程如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
Connection conn = ...; Savepoint point = null ; try { conn.setAutoCommit( false ); Statement stmt = conn.createStatement(); stmt.executeUpdate( "INSERT INTO ..." ); ... point = conn.setSavepoint(); stmt.executeUpdate( "INSERT INTO ..." ); ... conn. commit (); } catch (SQLException e) { e.printStackTrace(); if (conn != null ) { try { if (point == null ) { conn. rollback (); } else { conn. rollback (point); conn.releaseSavepoint(point); } } catch (SQLException ex) { ex.printStackTrace(); } } } finally { ... if (conn != null ) { try { conn.setAutoCommit( true ); conn. close (); } catch (SQLException ex) { ex.printStackTrace(); } } } |
需要说明的是,JDBC操作事务的前提条件是数据库支持事务,如果数据库本身不支持事务,那么我们即使调用setAutoCommit(false)也无法启动事务。对于MYSQL来说,MyIsam数据库引擎不支持事务操作,InnoDB数据库引擎支持事务操作。
1.2、隔离级别
要理解隔离级别,首先要了解多个事务并行时,可能引发的数据不一致问题有哪些,常见的事务并行引发问题有以下几类:
更新遗失
更新遗失是指某个事务对字段进行更新的信息,因另一个事务的介入而遗失更新的效力,一个简单的示例如下:
- 事务A更新数据表字段为AAA;
- 事务B更新数据表字段为BBB;
- 事务A提交;
- 事务B提交。
这个序列就是典型的更新丢失,因为第三步所做的所有修改全部会丢失。如果要避免更新遗失问题,可以设置隔离级别为"read uncommitted",这样A事务已更新但未确认的数据,B事务仅可做读取操作,但不可做更新操作。这样上面的四个步骤就是不合法的,必须A事务完全提交,B事务才能做更新操作。
脏读
"read uncommitted"隔离级别保证了在A事务提交之前,B事务不能做更改操作,但是没有阻止B事务做读取操作,但是这个其实是有问题的:如果A事务更新字段为"AAA",B事务读取值为"AAA"并使用,然后A事务回滚事务,那么B事务读取的"AAA"就属于脏数据。如果要避免脏读问题,可以设置隔离级别为"Read Commited",也就是事务读取的数据必须是其他事务已经确认的数据。
不可重复读
不可重复度是指两次读取同一字段的数据不一致,例如:事务A读取字段为"AAA",事务B更新数据为"BBB",事务B提交,事务A读取字段为"BBB",事务A连续的两次读取,字段值不一样。要避免这种问题,可以设置数据库隔离级别为"Repeatable Read",对于这种隔离界别,事务A读取字段为"AAA"后,其他事务在事务A提交前只可读取该字段,不可更新该字段。
幻读
幻读是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,比如这种修改涉及到表中的"全部数据行"。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入"一行新数据"。那么,以后就会发生操作第一个事务的用户发现表中还是有没有修改的数据行,就好象发生了幻觉一样。要解决幻读问题,必须设置隔离级别为Serializable,Serializable是数据库隔离级别的最高级别,串行化读,事务只能一个一个执行,避免了脏读、不可重复读、幻读,但是执行效率慢,需要谨慎使用。
1.3、悲观锁、乐观锁
悲观锁是采用一种悲观的态度来对待事务并发问题,认为系统中的并发更新会非常频繁,并且事务失败了以后重来的开销很大,这样一来,我们就需要采用真正意义上的锁来进行实现。悲观锁的实现,往往依靠数据库提供的锁机制。悲观锁的基本思想就是每次一个事务读取某一条记录后,就会把这条记录锁住,这样其它的事务要想更新,必须等以前的事务提交或者回滚解除锁。
乐观锁,顾名思义就是保持一种乐观的态度,我们认为系统中的事务并发更新不会很频繁,即使冲突了也没事,大不了重新再来一次。它的基本思想就是每次提交一个事务更新时,我们先看看要修改的东西从上次读取以后有没有被其它事务修改过,如果修改过,那么更新就会失败。乐观锁的实现方式大多是基于数据版本 ( Version )记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来实现。 读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提 交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。
总的来说,悲观锁的机制依赖数据库的锁机制,较安全,而乐观锁机制通过应用程序控制,性能较好。
2、存储过程
JDBC可以调用存储过程,要调用存储过程,首先我们应该创建存储过程:
1
2
3
4
5
6
7
8
9
10
11
12
|
//创建表,并插入数据 create table g(num int ,value varchar (10)); insert into g values (1, '1' ),(10, '10' ),(60, '60' ),(100, '100' ); //创建存储过程 DELIMITER $ CREATE PROCEDURE p1( IN n int , OUT avg double , OUT min int ) BEGIN select avg (num) from g where num > n INTO avg ; select min (num) from g where num > n INTO min ; END $ DELIMITER ; |
JDBC调用存储过程的接口与增删改查的不同,JDBC调用存储过程应该使用CallableStatement,简单示例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
private static void ps() throws SQLException{ Connection conn = null ; CallableStatement cs = null ; try{ conn = JdbcUtils.getConnection(); cs = conn.prepareCall( "call p1(?,?,?)" ); cs.registerOutParameter(2, Types. DOUBLE );//设置 out 参数 cs.registerOutParameter(3, Types. INTEGER );//设置 out 参数 cs.setInt(1, 18);//设置 in 参数 cs.executeUpdate(); System. out .println(cs.getInt(2) + " " + cs.getInt(3)); } finally{ JdbcUtils. free ( null , cs, conn); } } |
3、批次更新
如果需要对对数据库进行大量数据更新,使用循环多次操作更新是比较浪费性能的,对于这种场景,我们可以使用addBatch()方法来收集SQL,并使用executeBatch()方法将收集的SQL批次更新,例如:
1
2
3
4
5
|
Statement stmt = conn.createStatement(); while(someCondition) { stmt.addBatch( "INSERT INTO ..." ); } stmt.executeBatch(); |
JDBC学习笔记——事务、存储过程以及批量处理的更多相关文章
- JDBC 学习笔记(十一)—— JDBC 的事务支持
1. 事务 在关系型数据库中,有一个很重要的概念,叫做事务(Transaction).它具有 ACID 四个特性: A(Atomicity):原子性,一个事务是一个不可分割的工作单位,事务中包括的诸操 ...
- JDBC学习笔记二
JDBC学习笔记二 4.execute()方法执行SQL语句 execute几乎可以执行任何SQL语句,当execute执行过SQL语句之后会返回一个布尔类型的值,代表是否返回了ResultSet对象 ...
- JDBC学习笔记一
JDBC学习笔记一 JDBC全称 Java Database Connectivity,即数据库连接,它是一种可以执行SQL语句的Java API. ODBC全称 Open Database Conn ...
- MyBatis 学习笔记(七)批量插入ExecutorType.BATCH效率对比
MyBatis 学习笔记(七)批量插入ExecutorType.BATCH效率对比一.在mybatis中ExecutorType的使用1.Mybatis内置的ExecutorType有3种,默认的是s ...
- VSTO学习笔记(五)批量编辑Excel 2010 x64
原文:VSTO学习笔记(五)批量编辑Excel 2010 x64 近期因为工作的需要,经常要批量处理大量的Excel文件,如果纯手工一个个修改,非常的麻烦,于是写了这么一个帮助类,希望能对你有所帮助. ...
- MySQL学习笔记-事务相关话题
事务机制 事务(Transaction)是数据库区别于文件系统的重要特性之一.事务会把数据库从一种一致状态转换为另一个种一致状态.在数据库提交工作时,可以确保其要么所有修改都已经保存了,要么所有修改都 ...
- JDBC 学习笔记(十)—— 使用 JDBC 搭建一个简易的 ORM 框架
1. 数据映射 当我们获取到 ResultSet 之后,显然这个不是我们想要的数据结构. 数据库中的每一个表,在 Java 代码中,一定会有一个类与之对应,例如: package com.gerrar ...
- JDBC 学习笔记(六)—— PreparedStatement
1. 引入 PreparedStatement PreparedStatement 通过 Connection.createPreparedStatement(String sql) 方法创建,主要用 ...
- JDBC 学习笔记(四)—— 自定义JDBC框架+Apache—DBUtils框架+事务管理+操作多表
本文目录: 1.自定义JDBC框架 ——数据库元数据:DataBaseMetaData 2.自定义JDBC框架 ——数据库元数据:DataBaseMetaData ...
随机推荐
- MSYS2是对MSYS的一个独立的重写,是基于当前的Cygwin和MinGW-w64重写的,以同原生的Windows软件有更好的交互性为目的
MSYS2的官网:http://sourceforge.net/projects/msys2/ 官网的描述: Description MSYS2 is an independent rewrite o ...
- [内核编程] visual studio 2010配置驱动开发环境
visual studio 2010 配置驱动开发环境 ** 工具/材料 VS2010.WDK开发包 ** 配置过程 以下将讲述VS2010驱动开发环境的配置过程,至于必要软件的安装过程这里不再赘述 ...
- GeoTiff如何存储颜色表的研究
作者:朱金灿 来源:http://blog.csdn.net/clever101 在一次偶然的机会中得知tiff图像时可以存诸颜色表的,心想以后用GeoTiff来保存图像分类图像就十分方便了.于是研究 ...
- iis MP4 不能访问404
为什么我上传了flv或MP4文件到服务器,可输入正确地址通过http协议来访问总是出现“无法找到该页”的404错误呢?这就表明mp4格式文件是服务器无法识别的,其实,这是没有在iis中将相应的MIME ...
- 二:新浪微博:第三方框架管理工具CocoaPods的安装和使用
一:CocoaPods的安装 我们可以用淘宝的Ruby镜像来访问cocoapods.按照下面的顺序在终端中敲入依次敲入 $ gem sources --remove https://rubygems. ...
- 给自己加油,一定要学会MFC!(刚刚发现一篇文章,兼听则明: MFC,一开始就错了)
我自己对于没有学会MFC始终耿耿于怀,都什么时代了啊,但是我仍然坚持会去学MFC,因为MFC虽然落后与复杂,但是在Windows平台上仍然是无所不能的(其实Windows平台仍然是唯一可以赚钱的平台, ...
- 【codeforces 757C】Felicity is Coming!
time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...
- ITFriend创业败局(三):技术人员创业,需要尽可能避免,或者需要解决的5个重要问题
一.插科打诨: 本想给小雷粉,做一个创业"成功案例"的,结果做成了一个"反面教材"~ No zuo,no die~ 二.写作目的:分享自己作为一名技术人员,或者 ...
- BZOJ 1864 三色二叉树 - 树型dp
传送门 题目大意: 给一颗二叉树染色红绿蓝,父亲和儿子颜色必须不同,两个儿子颜色必须不同,问最多和最少能染多少个绿色的. 题目分析: 裸的树型dp:\(dp[u][col][type]\)表示u节点染 ...
- Vue Router的官方示例改造
基于Vue Router 2018年8月的官方文档示例,改造一下,通过一个最简单的例子,解决很多初学者的一个困惑. 首先是官方文档示例代码 <!DOCTYPE html> <html ...