`
qlma
  • 浏览: 53659 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论
阅读更多
Java中的事务处理

  一般情况下,J2EE应用服务器支持JDBC事务、JTA(Java Transaction API)事务、容器管理事务。一般情况下,最好不要在程序中同时使用上述三种事务类型,比如在JTA事务中嵌套JDBC事务。第二方面,事务要在尽可能短的时间内完成,不要在不同方法中实现事务的使用。下面我们列举两种事务处理方式。

  1、JavaBean中使用JDBC方式进行事务处理

  在JDBC中怎样将多个SQL语句组合成一个事务呢?在JDBC中,打开一个连接对象Connection时,缺省是auto-commit模式,每个SQL语句都被当作一个事务,即每次执行一个语句,都会自动的得到事务确认。为了能将多个SQL语句组合成一个事务,要将auto-commit模式屏蔽掉。在auto-commit模式屏蔽掉之后,如果不调用commit()方法,SQL语句不会得到事务确认。在最近一次commit()方法调用之后的所有SQL会在方法commit()调用时得到确认。


public int delete(int sID) {
 dbc = new DataBaseConnection();
 Connection con = dbc.getConnection();
 try {
  con.setAutoCommit(false);// 更改JDBC事务的默认提交方式
  dbc.executeUpdate("delete from bylaw where ID=" + sID);
  dbc.executeUpdate("delete from bylaw _content where ID=" + sID);
  dbc.executeUpdate("delete from bylaw _affix where bylawid=" + sID);
  con.commit();//提交JDBC事务
  con.setAutoCommit(true);// 恢复JDBC事务的默认提交方式
  dbc.close();
  return 1;
 }
 catch (Exception exc) {
  con.rollBack();//回滚JDBC事务
  exc.printStackTrace();
  dbc.close();
  return -1;
 }
}

stmt.executeUpdate("insert into test values(1,'aaa')");


  //定义一个回滚到(保存点)savepoint1,在事务失败的时候,可以回滚到定义的回滚点

  savepoint1 = conn.setSavepoint("insert_end");

  stmt.executeUpdate("update test set name = 'bbb' where id =1");

  //提交事务

  conn.commit();

  } catch (SQLException e) {

  try {

  //当事务失败时候,回滚到(保存点)savepoint1

  conn.rollback(savepoint1);

  // 当本事务中的插入和更新SQL其中一个执行异常的时候,整个事务回滚

  //conn.rollback();

  } catch (SQLException e1) {

  throw new RuntimeException("回滚事务发生异常!", e);

  }

  throw new RuntimeException("执行事务发生异常!", e);

  } finally {

  if (conn != null) {

  try {

  conn.close();

  } catch (SQLException e) {

  throw new RuntimeException("关闭数据库连接发生异常!", e);

  }

  }

  }

  }

  }

  上面代码中:

  //设置JDBC事务的级别

  conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);

  //当事务失败时候,回滚到(保存点)savepoint1

  conn.rollback(savepoint1);

  JDBC的事务级别设置,保存点(或回滚点)的设置与数据库和JDBC的驱动的实现有关系,并非完全支持,但是不支持也不会出错。

JDBC批量插入主要用于数据导入和日志记录因为日志一般都是先写在文件下的等。
我用Mysql 5.1.5的JDBC driver 分别对三种比较常用的方法做了测试


方法一,使用PreparedStatement加批量的方法
view plaincopy to clipboardprint?
try {     
      Class.forName("com.mysql.jdbc.Driver");     
      conn = DriverManager.getConnection(o_url, userName, password);     
      conn.setAutoCommit(false);     
      String sql = "INSERT adlogs(ip,website,yyyymmdd,hour,object_id) VALUES(?,?,?,?,?)";     
      PreparedStatement prest = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);     
      for(int x = 0; x < size; x++){     
         prest.setString(1, "192.168.1.1");     
         prest.setString(2, "localhost");     
         prest.setString(3, "20081009");     
         prest.setInt(4,;     
         prest.setString(5, "11111111");     
         prest.addBatch();     
      }     
      prest.executeBatch();     
      conn.commit();     
      conn.close();     
} catch (SQLException ex) {     
   Logger.getLogger(MyLogger.class.getName()).log(Level.SEVERE, null, ex);     
} catch (ClassNotFoundException ex) {     
     Logger.getLogger(MyLogger.class.getName()).log(Level.SEVERE, null, ex);     
}   
try {  
      Class.forName("com.mysql.jdbc.Driver");  
      conn = DriverManager.getConnection(o_url, userName, password);  
      conn.setAutoCommit(false);  
      String sql = "INSERT adlogs(ip,website,yyyymmdd,hour,object_id) VALUES(?,?,?,?,?)";  
      PreparedStatement prest = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);  
      for(int x = 0; x < size; x++){  
         prest.setString(1, "192.168.1.1");  
         prest.setString(2, "localhost");  
         prest.setString(3, "20081009");  
         prest.setInt(4,;  
         prest.setString(5, "11111111");  
         prest.addBatch();  
      }  
      prest.executeBatch();  
      conn.commit();  
      conn.close();  
} catch (SQLException ex) {  
   Logger.getLogger(MyLogger.class.getName()).log(Level.SEVERE, null, ex);  
} catch (ClassNotFoundException ex) {  
     Logger.getLogger(MyLogger.class.getName()).log(Level.SEVERE, null, ex);  
}


说明下在建Statement的时候,后面两个参数的意义:
第一个参数指定 ResultSet 的类型。其选项有:
TYPE_FORWARD_ONLY:缺省类型。只允许向前访问一次,并且不会受到其他用户对该数据库所作更改的影响。
TYPE_SCROLL_INSENSITIVE:允许在列表中向前或向后移动,甚至可以进行特定定位,例如移至列表中的第四个记录或者从当前位置向后移动两个记录。不会受到其他用户对该数据库所作更改的影响。
TYPE_SCROLL_SENSITIVE:象 TYPE_SCROLL_INSENSITIVE 一样,允许在记录中定位。这种类型受到其他用户所作更改的影响。如果用户在执行完查询之后删除一个记录,那个记录将从 ResultSet 中消失。类似的,对数据值的更改也将反映在 ResultSet 中。
第二个参数设置 ResultSet 的并发性,该参数确定是否可以更新 ResultSet。其选项有:
CONCUR_READ_ONLY:这是缺省值,指定不可以更新
ResultSet CONCUR_UPDATABLE:指定可以更新 ResultSet

方法二 使用Statement加批量的方法
view plaincopy to clipboardprint?
conn.setAutoCommit(false);     
Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);     
for(int x = 0; x < size; x++){     
   stmt.addBatch("INSERT INTO adlogs(ip,website,yyyymmdd,hour,object_id) VALUES('192.168.1.3', 'localhost','20081009',8,'23123')");     
}     
stmt.executeBatch();     
conn.commit();   
conn.setAutoCommit(false);  
Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);  
for(int x = 0; x < size; x++){  
   stmt.addBatch("INSERT INTO adlogs(ip,website,yyyymmdd,hour,object_id) VALUES('192.168.1.3', 'localhost','20081009',8,'23123')");  
}  
stmt.executeBatch();  
conn.commit();


方法三:直接使用Statement
view plaincopy to clipboardprint?
conn.setAutoCommit(false);     
Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,     
                                    ResultSet.CONCUR_READ_ONLY);     
for(int x = 0; x < size; x++){     
   stmt.execute("INSERT INTO adlogs(ip,website,yyyymmdd,hour,object_id) VALUES('192.168.1.3', 'localhost','20081009',8,'23123')");     
}     
conn.commit();   
conn.setAutoCommit(false);  
Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,  
                                    ResultSet.CONCUR_READ_ONLY);  
for(int x = 0; x < size; x++){  
   stmt.execute("INSERT INTO adlogs(ip,website,yyyymmdd,hour,object_id) VALUES('192.168.1.3', 'localhost','20081009',8,'23123')");  
}  
conn.commit();


使用上述方法分别插入10万条数据的平均测试时间为:
方法一:17.844s
方法二:18.421s
方法三:16.359s

可以看出JDBC的batch语句插入不但没有性能提升,反而比没有用batch的时候要慢,当然这可能跟JDBC具体驱动的实现方法有关。 附件中是我测试代码,可以用来在自己电脑上跑一下。

在执行批量插入的时候最主要的是将自动提交取消,这样不管是否用JDBC的batch语法应该都没有关系。
view plaincopy to clipboardprint?
conn.setAutoCommit(false)   
conn.setAutoCommit(false) 

个人觉得第一种方法是最方便最实用的。



分享到:
评论

相关推荐

    JDBCDriver3.0.rar_jdbc driver 3.0_sql jdbc 3.0_sql server jdbc_s

    《深入理解JDBC Driver 3.0:聚焦SQL Server JDBC》 在IT行业中,数据库连接是应用程序与数据存储之间的桥梁,而JDBC(Java Database Connectivity)则是Java平台中用于访问数据库的标准API。JDBC Driver 3.0是针对...

    sqlserver驱动包 jdbc驱动 sqljdbc.jar和sqljdbc4.jar

    SQL Server驱动包是用于Java应用程序通过JDBC(Java Database Connectivity)接口与Microsoft SQL Server数据库进行交互的必备组件。本文将详细介绍这两个重要的驱动文件——sqljdbc.jar和sqljdbc4.jar,以及如何...

    sqljdbc和sqljdbc4 sqlserver最新驱动

    SQLJDBC和SQLJDBC4是Microsoft为Java应用程序提供的用于连接SQL Server数据库的驱动程序。这两个版本都是JDBC(Java Database Connectivity)驱动,允许Java开发者在应用程序中与SQL Server进行交互。下面将详细介绍...

    Spring Data JDBC与JDBC的区别

    Spring Data JDBC与JDBC是两种不同的数据库访问方式,它们在Java开发中有着广泛的应用。JDBC(Java Database Connectivity)是Java平台的标准API,用于与各种数据库进行交互。它提供了低级别的数据库操作,如建立...

    sap JDBC数据源配置

    ### SAP JDBC 数据源配置 #### 引言与目的 本文档旨在提供详细的步骤指南,用于在SAP NetWeaver 7.0 和 SAP Composite Environment (CE) 7.1 上配置 JDBC 数据源和系统。通过这些步骤,用户可以创建一个独立的数据...

    mysql jdbc 驱动 适用于5.6版本及以下数据库

    mysql jdbc 驱动 适用于5.6版本及以下数据库 mysql jdbc 驱动 适用于5.6版本及以下数据库 mysql jdbc 驱动 适用于5.6版本及以下数据库 mysql jdbc 驱动 适用于5.6版本及以下数据库 mysql jdbc 驱动 适用于5.6版本及...

    mysql jdbc 驱动 适用于5.7及以上版本数据库

    mysql jdbc 驱动 适用于5.7及以上版本数据库 mysql jdbc 驱动 适用于5.7及以上版本数据库 mysql jdbc 驱动 适用于5.7及以上版本数据库 mysql jdbc 驱动 适用于5.7及以上版本数据库 mysql jdbc 驱动 适用于5.7及以上...

    sqljdbc41、sqljdbc42的官方jar包

    在Java编程语言中,JDBC(Java Database Connectivity)是一个核心的API,用于连接Java应用程序与各种类型的数据库。这里我们关注的是两个特定版本的Microsoft SQL Server的JDBC驱动:sqljdbc41.jar和sqljdbc42.jar...

    Dm7JdbcDriver16.jar Dm7JdbcDriver17.jar Dm7JdbcDriver18.jar

    在给定的压缩包文件中,包含了三个不同版本的达梦JDBC驱动,分别是Dm7JdbcDriver16.jar、Dm7JdbcDriver17.jar和Dm7JdbcDriver18.jar。 1. **JDBC驱动介绍**: JDBC是Java中用于与各种数据库进行交互的标准接口,它...

    自学jdbc心得体会

    JDBC 基础知识点 JDBC(Java Database Connectivity)是一种Java标准的数据库连接API,它允许Java程序访问各种关系数据库。下面是JDBC的基础知识点: 一、JDBC原理概述 * JDBC是一套协议,由Sun定义的一组接口,...

    jdbc jdbc jdbc

    Java Database Connectivity(JDBC)是Java编程语言中用于与各种数据库进行交互的一种标准接口。它由Sun Microsystems(现为Oracle公司)开发并定义,作为Java平台的一部分,允许Java应用程序通过编写Java代码来访问...

    sql server2000 jdbc

    SQL Server 2000 JDBC 是Java编程语言与Microsoft SQL Server 2000数据库进行交互的一种重要方式。JDBC(Java Database Connectivity)是Java API,允许Java应用程序通过Java虚拟机(JVM)与各种数据库建立连接。在...

    Access_JDBC30

    标题 "Access_JDBC30" 暗示了这是一个与Microsoft Access数据库相关的Java JDBC驱动程序。JDBC(Java Database Connectivity)是Java编程语言中用于连接和操作数据库的标准接口。这个jar包,"Access_JDBC30.jar",...

    kingbaseV8 jdbc 驱动

    KingbaseV8 JDBC驱动是连接KingbaseV8数据库的重要组件,允许Java应用程序通过JDBC(Java Database Connectivity)接口与数据库进行交互。JDBC是Java语言中用来规范客户端程序如何访问数据库的应用程序接口,提供了...

    sqljdbc42.jar、sqljdbc41.jar 更新日期2017-12-21

    标题中的"sqljdbc42.jar、sqljdbc41.jar 更新日期2017-12-21"指的是Microsoft SQL Server的Java Database Connectivity (JDBC) 驱动的两个不同版本,它们分别对应于Java SE 7和Java SE 8的兼容性。JDBC驱动是Java...

    sqljdbc4(sqlserver jdbc驱动下载和安装)

    在IT行业中,数据库是至关重要的组成部分,而SQL Server作为一款广泛应用的关系型数据库管理系统,它的连接与操作离不开JDBC(Java Database Connectivity)驱动。本篇将详细介绍如何下载和安装sqljdbc4,这是...

    sqljdbc4.jar, sqljdbc41.jar, sqljdbc42.jar三个包

    标题中的"sqljdbc4.jar, sqljdbc41.jar, sqljdbc42.jar"是指Microsoft SQL Server为Java应用程序提供的Java Database Connectivity (JDBC)驱动程序。这些JAR文件是数据库连接的关键,允许Java代码与SQL Server进行...

    access的jdbc驱动

    Access的JDBC驱动是Java数据库连接(Java Database Connectivity, JDBC)的一种实现,它允许Java程序与Microsoft Access数据库进行交互。在JDK 1.8之后,Oracle公司不再默认提供对ODBC(Open Database Connectivity...

    sqljdbc 3.0及4.0

    `sqljdbc`是Microsoft提供的一个驱动程序,使得Java应用程序能够与SQL Server数据库进行交互。在这个场景中,我们关注的是`sqljdbc 3.0`和`4.0`版本,这两个版本都是专门为Java设计的,用于连接SQL Server 2000。 `...

Global site tag (gtag.js) - Google Analytics