Java事务管理学习之JDBC详解

什么是Java事务

通常的观念认为,事务仅与数据库相关。

事务必须服从ISO/IEC所制定的ACID原则。ACID是原子性(atomicity)、一致性(consistency)、隔离性(isolation)和持久性(durability)的缩写。事务的原子性表示事务执行过程中的任何失败都将导致事务所做的任何修改失效。一致性表示当事务执行失败时,所有被该事务影响的数据都应该恢复到事务执行前的状态。隔离性表示在事务执行过程中对数据的修改,在事务提交之前对其他事务不可见。持久性表示已提交的数据在事务执行失败时,数据的状态都应该正确。

通俗的理解,事务是一组原子操作单元,从数据库角度说,就是一组SQL指令,要么全部执行成功,若因为某个原因其中一条指令执行有错误,则撤销先前执行过的所有指令。更简答的说就是:要么全部执行成功,要么撤销不执行。

既然事务的概念从数据库而来,那Java事务是什么?之间有什么联系?

实际上,一个Java应用系统,如果要操作数据库,则通过JDBC来实现的。增加、修改、删除都是通过相应方法间接来实现的,事务的控制也相应转移到Java程序代码中。因此,数据库操作的事务习惯上就称为Java事务。

事务的特性:

1) 原子性(atomicity):事务是数据库的逻辑工作单位,而且是必须是原子工作单位,对于其数据修改,要么全部执行,要么全部不执行。

2) 一致性(consistency):事务在完成时,必须是所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。

3) 隔离性(isolation):一个事务的执行不能被其他事务所影响。

4) 持久性(durability):一个事务一旦提交,事物的操作便永久性的保存在DB中。即使此时再执行回滚操作也不能撤消所做的更改。

事务(Transaction):是并发控制的单元,是用户定义的一个操作序列。这些操作要么都做,要么都不做,是一个不可分割的工作单位。通过事务,sql server 能将逻辑相关的一组操作绑定在一起,以便服务器 保持数据的完整性。事务通常是以begin transaction开始,以commit或rollback结束。Commint表示提交,即提交事务的所有操作。具体地说就是将事务中所有对数据的更新写回到磁盘上的物理数据库中去,事务正常结束。Rollback表示回滚,即在事务运行的过程中发生了某种故障,事务不能继续进行,系统将事务中对数据库的所有已完成的操作全部撤消,滚回到事务开始的状态。

自动提交事务:每条单独的语句都是一个事务。每个语句后都隐含一个commit。 (默认)

显式事务:以begin transaction显示开始,以commit或rollback结束。

隐式事务:当连接以隐式事务模式进行操作时,sql server数据库引擎实例将在提交或回滚当前事务后自动启动新事务。无须描述事物的开始,只需提交或回滚每个事务。但每个事务仍以commit或rollback显式结束。连接将隐性事务模式设置为打开之后,当数据库引擎实例首次执行下列任何语句时,都会自动启动一个隐式事务:alter table,insert,create,open ,delete,revoke ,drop,select, fetch ,truncate table,grant,update在发出commit或rollback语句之前,该事务将一直保持有效。在第一个事务被提交或回滚之后,下次当连接执行以上任何语句时,数据库引擎实例都将自动启动一个新事务。该实例将不断地生成隐性事务链,直到隐性事务模式关闭为止。

JDBC事务管理

在使用JDBC的时候, 如何进行事务的管理。直接看一下代码

示例代码

/**
 * @Title: JDBCTrans.java
 * @Package com.oscar999.trans
 * @Description:
 * @author XM
 * @date Feb 14, 2017 4:38:27 PM
 * @version V1.0
 */
package com.oscar999.trans; 

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement; 

/**
 * @author
 *
 */
public class JDBCTrans { 

 public JDBCTrans() { 

 } 

 /**
 *
 * @param sHostName
 * @param sPortNumber
 * @param sSid
 * @param userName
 * @param password
 * @return
 * @throws SQLException
 */
 public Connection getConnection(String sHostName, String sPortNumber, String sSid, String userName, String password) throws SQLException {
 Connection conn = null;
 String url = getOraclURL(sHostName, sPortNumber, sSid);
 conn = DriverManager.getConnection(url,userName,password);
 return conn;
 } 

 /**
 *
 * @param conn
 * @param sql
 * @throws SQLException
 */
 public void add(Connection conn, String sql) throws SQLException {
 Statement stmt = null;
 try {
  stmt = conn.createStatement();
  stmt.execute(sql);
 } catch (SQLException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
 } finally {
  if (stmt != null)
  stmt.close();
 }
 } 

 /**
 * @param args
 */
 public static void main(String[] args) {
 // TODO Auto-generated method stub
 String sHostName = "";
 String sPortNumber = "";
 String sSid = "";
 String userName = "";
 String password = ""; 

 sHostName = "";
 sPortNumber = "";
 sSid = "";
 userName = "";
 password = ""; 

 try {
  Class.forName("oracle.jdbc.driver.OracleDriver");
 } catch (ClassNotFoundException e1) {
  // TODO Auto-generated catch block
  e1.printStackTrace();
 } 

 JDBCTrans jdbcTrans = new JDBCTrans();
 Connection conn = null;
 try {
  conn = jdbcTrans.getConnection(sHostName, sPortNumber, sSid, userName, password);
  conn.setAutoCommit(false);// can't insert, update 

  //1. add SQL
  String addSQL = "insert into TEST_TABLE values('name1','value1')";
  jdbcTrans.add(conn,addSQL); 

 } catch (SQLException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
 } finally {
  /*if (conn != null)
  {
  try {
   conn.close();
  } catch (SQLException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  }*/
 } 

 } 

 private String getOraclURL(String sHostName, String sPortNumber, String sSid) {
 String url = "jdbc:oracle:thin:@" + sHostName + ":" + sPortNumber + ":" + sSid;
 return url;
 } 

} 

针对以上代码, 说明如下:

以上代码有几点说明的部分:

1. conn.setAutoCommit(false) 执行之后不提交事务。

对于Select没有影响, 但对于Insert和Update的话, 没有提交数据就不会被修改

2.  conn.close(); 关闭Connection的代码有被Mark掉, 是想呈现conn.setAutoCommit(false)的效果。

原因是在 Connection Close的时候会执行一次Commit.

而如果Connection是在应用服务器中使用连接池的话, Connection就不会被Close, 也就不会执行Commit.

3. setAutoCommit(false) 用法大多数是在要执行多条语句才提交。

所以针对以上第三点, 更接近实际的状况的代码如示例代码2

示例代码2

/**
 * @Title: JDBCTrans.java
 * @Package com.oscar999.trans
 * @Description:
 * @author XM
 * @date Feb 14, 2017 4:38:27 PM
 * @version V1.0
 */
package com.oscar999.trans; 

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement; 

/**
 * @author
 *
 */
public class JDBCTrans { 

 public JDBCTrans() { 

 } 

 /**
 *
 * @param sHostName
 * @param sPortNumber
 * @param sSid
 * @param userName
 * @param password
 * @return
 * @throws SQLException
 */
 public Connection getConnection(String sHostName, String sPortNumber, String sSid, String userName, String password) throws SQLException {
 Connection conn = null;
 String url = getOraclURL(sHostName, sPortNumber, sSid);
 conn = DriverManager.getConnection(url, userName, password);
 return conn;
 } 

 /**
 *
 * @param conn
 * @param sql
 * @throws SQLException
 */
 public void add(Connection conn, String sql) throws SQLException {
 Statement stmt = null;
 try {
  stmt = conn.createStatement();
  stmt.execute(sql);
 } catch (SQLException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
 } finally {
  if (stmt != null)
  stmt.close();
 }
 } 

 /**
 * @param args
 */
 public static void main(String[] args) {
 // TODO Auto-generated method stub
 String sHostName = "";
 String sPortNumber = "";
 String sSid = "";
 String userName = "";
 String password = ""; 

 sHostName = "";
 sPortNumber = "";
 sSid = "";
 userName = "";
 password = ""; 

 try {
  Class.forName("oracle.jdbc.driver.OracleDriver");
 } catch (ClassNotFoundException e1) {
  // TODO Auto-generated catch block
  e1.printStackTrace();
 } 

 JDBCTrans jdbcTrans = new JDBCTrans();
 Connection conn = null;
 try {
  conn = jdbcTrans.getConnection(sHostName, sPortNumber, sSid, userName, password);
  conn.setAutoCommit(false);// can't insert, update 

  // 1. add SQL 1
  String addSQL = "insert into TEST_TABLE values('name1','value1')";
  jdbcTrans.add(conn, addSQL); 

  //2. add SQL 2
  addSQL = "insert into TEST_TABLE values('name2','value2')";
  jdbcTrans.add(conn, addSQL); 

  conn.commit();
 } catch (SQLException e) {
  // TODO Auto-generated catch block
  if(conn!=null){
   try {
   conn.rollback();
   } catch (SQLException e1) {
   e1.printStackTrace();
   }
  }
  e.printStackTrace();
 } finally {
  if (conn != null) {
  try {
   conn.close();
  } catch (SQLException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  }
 } 

 } 

 private String getOraclURL(String sHostName, String sPortNumber, String sSid) {
 String url = "jdbc:oracle:thin:@" + sHostName + ":" + sPortNumber + ":" + sSid;
 return url;
 } 

} 

这里需要说明的是: conn.rollback();

只要执行有异常,就要rollback , 这一步必不可少

如果没有在执行出现异常的时候进行回滚。如果在执行第一条语句之后出现异常,con既没有提交也没有回滚,表就会被锁住(如果oracle数据库就是行锁),而这个锁却没有机会释放。

可能在执行con.close()的时候会释放锁,但还是如果应用服务器使用了数据库连接池,连接不会被断开。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家学习或者使用java能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • Java框架篇:Spring+SpringMVC+hibernate整合开发

    前言: 最近没什么事做,搭个框架写成博客记录下来,拉通一下之前所学知识. 话不多说,我们直接步入正题. 准备工作: 1/安装并配置java运行环境 2/数据库的安装配置(Mysql) 3/安装并配置服务器(Tomcat) 4/Maven 5/ IntelliJIDEA的安装配置(本人使用的主要软件是IntelliJIDEA,没用eclipse什么的) 6/ 使用IntelliJIDEA创建一个web app项目. 貌似就这些了吧 导包 不同于以往的导包,由于我们创建的是maven的webapp项

  • 详解Java的Spring框架中的事务管理方式

    数据库事务是被当作单个工作单元的操作序列.这些操作要么全部完成或全部不成功.事务管理是面向企业应用程序,以确保数据的完整性和一致性RDBMS中的重要组成部分.事务的概念可以用下面的描述为ACID四个关键属性来描述: 原子性: 一个事务应该被视为单个操作单元表示的操作的任一整个序列是成功的或不成功的. 一致性: 这代表了数据库的参照完整性,在桌等唯一主键的一致性 隔离性: 可能有很多事务处理相同的数据集的同时,每个事务都应由他人隔离,以防止数据损坏. 持久性: 一旦事务完成,本次事务的结果必须作出

  • Java事务管理学习之Hibernate详解

    环境与版本 hibernate 版本:Hibernate 4.2.2 (下载后的文件名为hibernate-release-4.2.2.Final.zip,解压目录hibernate-release-4.2.2.Final) 数据库: Oracle 10g 导入lib\required 中的所有jar 包 理论说明 1.SessionFactory负责创建Session,SessionFactory是线程安全的,多个并发线程可以同时访问一个SessionFactory 并从中获取Session实

  • 从最基本的Java工程搭建SpringMVC+SpringDataJPA+Hibernate

    本文会介绍从一个最基本的java工程,到Web工程,到集成Spring.SpringMVC.SpringDataJPA+Hibernate. 平时我们可能是通过一个模板搭建一个工程,或者是直接导入一个项目,而本文选择从最基本的java工程开始,目的是为了展示更多原理. 当然,我们还是从一个最基本的Maven工程开始,其实普通的非Maven工程,搭建过程几乎是一模一样的,只是Jar包需要我们手动的添加到工程中,而Maven工程就只是修改配置文件即可. 下面就正式开始. 1.基于Maven(如果不使

  • Java事务管理学习之Spring和Hibernate详解

    环境与版本 本文出来之前的一篇文章中的hibernate的相关lib 外 Java事务管理之Hibernate 还需要加入spring的lib 包和如下的一些依赖包 org.aopalliance org.aspectj org.apache.commons Spring 的版本是Spring 4.1.5. 依赖包也可以到Spring 官方网站下载到 ,名字类似 spring-framework-3.0.2.RELEASE-dependencies 理论知识 Spring和Hibernate整合

  • Java事务管理学习之JDBC详解

    什么是Java事务 通常的观念认为,事务仅与数据库相关. 事务必须服从ISO/IEC所制定的ACID原则.ACID是原子性(atomicity).一致性(consistency).隔离性(isolation)和持久性(durability)的缩写.事务的原子性表示事务执行过程中的任何失败都将导致事务所做的任何修改失效.一致性表示当事务执行失败时,所有被该事务影响的数据都应该恢复到事务执行前的状态.隔离性表示在事务执行过程中对数据的修改,在事务提交之前对其他事务不可见.持久性表示已提交的数据在事务

  • Spring事务管理原理及方法详解

    这篇文章主要介绍了Spring事务管理原理及方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 事务,在日常开发或者面试中都必定会涉及到.开发工作中,结合数据库开发理解就是:一组dml要么全部成功执行提交,要么因为某一个操作异常,撤销之前所做的成功的操作,整体执行失败.再简单点的一句话:生死与共. 由此,可以看出,事务的必要性:在开发工作中,保证操作数据的安全性.事务的控制也就是保证数据的访问安全性. 一.事务的四大特性 A:原子性(ato

  • Spring boot jpa 删除数据和事务管理的问题实例详解

    今天我们介绍的是jpa删除和事务的一些坑,接下来看看具体内容. 业务场景(这是一个在线考试系统)和代码:根据问题的id删除答案 repository层: int deleteByQuestionId(Integer questionId); service 层: public void deleteChoiceAnswerByQuestionId(Integer questionId) { choiceAnswerRepository.deleteByQuestionId(questionId)

  • Vue3中Vuex状态管理学习实战示例详解

    目录 引言 一.目录结构 二.版本依赖 三.配置Vuex 四.使用Vuex 引言 Vuex 是 Vue 全家桶重要组成之一,专为 Vue.js 应用程序开发的 状态管理模式 + 库 ,它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化. 一.目录结构 demo/ package.json vite.config.js index.html public/ src/ api/ assets/ common/ components/ store/ index.

  • Java高级语法学习之反射详解

    目录 一.什么是反射 二.准备测试:实体类的创建 三.反射中的几个重要类及方法 (一)反射中的重要类之Class (二)反射中的重要类之Field (三)反射中的重要类之Constructor (四)反射中的重要类之Method 四.综合实战:利用反射机制编写对象拷贝工具类 (一)业务分析 (二)实体类准备 (三)工具类编写 总结 一.什么是反射 java.lang包提供java语言程序设计的基础类,在lang包下存在一个子包:reflect,与反射相关的APIs均在此处: 官方对reflect

  • Java Spring5学习之JdbcTemplate详解

    一.JdbcTemplate Spring 框架对 JDBC 进行封装,使用 JdbcTemplate 方便实现对数据库操作 二.实战 2.1 引入依赖 <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.24</version> </dependency> <!-

  • Java图形化界面设计之布局管理器之BorderLayout案例详解

    边界布局管理器把容器的的布局分为五个位置:CENTER.EAST.WEST.NORTH.SOUTH.依次对应为:上北(NORTH).下南(SOUTH).左西(WEST).右东(EAST),中(CENTER),如下图所示. 特征: l  可以把组件放在这五个位置的任意一个,如果未指定位置,则缺省的位置是CENTER. l  南.北位置控件各占据一行,控件宽度将自动布满整行.东.西和中间位置占据一行;若东.西.南.北位置无控件,则中间控件将自动布满整个屏幕.若东.西.南.北位置中无论哪个位置没有控件

  • Java基础学习之构造方法详解

    目录 一.构造方法概述 二.构造方法的注意事项 三.标准类制作 一.构造方法概述 构造方法是一种特殊的方法 作用:创建对象Student stu = new Student(); 格式: pucli class 类名{        修饰符 类名(参数){        } } 功能:主要是完成对象数据的初始化 示例代码: class Student { private String name; private int age; //构造方法 public Student() { System.

随机推荐