Java事务管理学习之JDBC详解

 更新时间:2017年03月26日 09:37:21   作者:oscar999   我要评论

这篇文章主要介绍了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能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

相关文章

  • Spring Cloud中Eureka开启密码认证的实例

    Spring Cloud中Eureka开启密码认证的实例

    这篇文章主要介绍了Spring Cloud中Eureka开启密码认证的实例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-05-05
  • java实现查找文本内容替换功能示例

    java实现查找文本内容替换功能示例

    文本替换几乎是所有文本编辑器都支持的功能,但是要限制在编辑其中才可以执行该功能。本实例实现了制定文本文件的内容替换,并且不需要再编辑其中打开文本文件
    2014-02-02
  • java WSDL接口webService实现方式

    java WSDL接口webService实现方式

    这篇文章主要为大家详细介绍了java WSDL接口webService实现方式的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-04-04
  • spring boot和spring cloud之间的版本关系

    spring boot和spring cloud之间的版本关系

    这篇文章主要介绍了spring boot和spring cloud之间的版本关系,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-08-08
  • SpringMVC实现前端后台交互传递数据

    SpringMVC实现前端后台交互传递数据

    本篇文章主要介绍了SpringMVC实现前端后台传递数据的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-03-03
  • java  StringBuilder类的详解及简单实例

    java StringBuilder类的详解及简单实例

    这篇文章主要介绍了java StringBuilder类的详解及简单实例的相关资料,实现了StringBuilder类的追加、插入、替换、删除等操作,需要的朋友可以参考下
    2017-08-08
  • MyBatis逆向工程的创建和使用

    MyBatis逆向工程的创建和使用

    这篇文章主要介绍了MyBatis逆向工程的创建和使用,需要的朋友可以参考下
    2017-08-08
  • Spring Boot 快速入门指南

    Spring Boot 快速入门指南

    Spring 框架是非常著名的 Java 开源框架,历经十多年的发展,整个生态系统已经非常完善甚至是繁杂,Spring Boot 正是为了解决这个问题而开发的,为 Spring 平台和第三方库提供了开箱即用的设置,只需要很少的配置就可以开始一个 Spring 项目
    2017-03-03
  • 使用XSD校验Mybatis的SqlMapper配置文件的方法(2)

    使用XSD校验Mybatis的SqlMapper配置文件的方法(2)

    这篇文章主要介绍了使用XSD校验Mybatis的SqlMapper配置文件的方法(2)的相关资料,非常不错具有参考借鉴价值,需要的朋友可以参考下
    2016-11-11
  • 使用Post方法模拟登陆爬取网页的实现方法

    使用Post方法模拟登陆爬取网页的实现方法

    下面小编就为大家带来一篇使用Post方法模拟登陆爬取网页的实现方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-03-03

最新评论