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 ...
随机推荐
- Java文档上传问题设计
近期公司让做一个文档上传的功能,功能描写叙述大概是这样子滴 书籍名称.书籍定价.书籍封面图片(须要上传).文档内容 (须要上传) .还有其它相关的描写叙述信息. 我的设计 表 A 包括以上字段 , ...
- UE4制作插件的插件神器pluginCreator
本文章由cartzhang编写,转载请注明出处. 所有权利保留. 文章链接:http://blog.csdn.net/cartzhang/article/details/45644007 作者:car ...
- jquery画图插件jPainter
jquery画图插件jPainter 一.总结 一句话总结:四年前的项目,四年无更新,不好用. 二.基于HTML5 Canvas和jQuery 的画图工具的实现 简介 HTML5 提供了强大的Canv ...
- [CSS] Showing horizontal scrollbar always for the table
table { display: block; overflow: scroll; width: 200px; height:95vh; }
- 浅谈python字符串存储形式
http://blog.csdn.net/zhonghuan1992 钟桓 2014年8月31日 浅谈python字符串存储形式 记录一下自己今的天发现疑问而且给出自己现有知识有的回答. 长话短说,用 ...
- lower_case_table_names(大小写敏感)
1 简介 在MySQL中,数据库对应数据目录中的目录.数据库中的每个表至少对应数据库目录中的一个文件(也可能是多个,取决于存储引擎).因此,所使用操作系统的大小写敏感性决定了数据库名和表名的大小 ...
- iOS Animation具体解释
iOS Animation具体解释 本篇仅仅要解说iOS中动画的使用. Animtion主要分为两类:UIView动画和CoreAnimation动画. UIView动画有UIView属性动画,UIV ...
- 【iOS】怎样推断文本文件的字符编码格式
整体思路: 遍历全部的字符编码.能正确读取输出转换的就是文本文件的编码格式. 代码例如以下: // // main.m // 检測文本字符编码格式的小技巧 // // Created by 杜子兮 ( ...
- js页面加载函数
在未加载完文档,使用jquery选择器选择元素后,如果立即绑定事件进行调用,会引起js的报错(can not read property of undefined),导致事件不能绑定成功. alert ...
- html5常用属性text-shadow、vertical-align、background如何使用
html5常用属性text-shadow.vertical-align.background如何使用 一.总结 一句话总结: 1.text-shadow:[x轴(X Offset) y轴(Y Offs ...