JDBC之事务处理

来源:互联网 发布:mysql between 编辑:程序博客网 时间:2024/06/07 06:18

Java事务的类型主要有三种:JDBC事务,JTA(Java Transaction API)事务,容器事务,常见的容器事务如Spring事务,容器事务主要是J2EE应用服务器提供,容器事务大多是基于JTA完成,这是一个基于JNDI的,相当负责的API实现。

JDBC的一切行为包括事务是基于一个Connection的,在JDBC中是通过Connection对象进行事务管理。在JDBC中,常用的和事务相关的方法是: setAutoCommit、commit、rollback等。

事务的特点:

原子性(atomicity):组成事务处理的语句形成了一个逻辑单元,不能只执行其中的一部分。
一致性(consistency):在事务处理执行前后,数据库是一致的(两个账户要么都变,或者都不变)。
隔离性(isolcation):一个事务处理对另一个事务处理没有影响。
持续性(durability):事务处理的效果能够被永久保存下来 。

JDBC对事务的支持:

connection.setAutoCommit(false);//打开事务,关闭自动提交事务
connection.commit();//提交事务。
connection.rollback();//回滚事务。

DatabaseMetaData 数据库元数据
DatabaseMetaData meta = connection.getMetaData();
通过DatabaseMetaData可以获得数据库相关的信息如:数据库版本、数据库名、数据库厂商信息、是否支持事务、是否支持某种事务隔离级别,是否支持滚动结果集等。

ResultSetMetaData 结果集元数据
ResultSetMetaData meta = rs.getMetaData();
通过ResultSetMetaData可以获得结果有几列、各列名、各列别名、各列类型等。
可以将ResultSet放入Map(key:列名 value:列值)。
用反射ResultSetMetaData将查询结果读入对象中(简单的O/RMapping)
1)让SQL语句中列别名和要读入的对象属性名一样;
2)通过ResultSetMetaData获得结果列数和列别名;
3)通过反射将对象的所有setXxx方法找到;
4)将3)找到的方法setXxx和2)找到的列别名进行匹配(即方法中的xxx于列别名相等);
5)由上一步找到的方法和列别名对应关系进行赋值
Method.invoke(obj, rs.getObject(columnAliasName));

数据源和连接池
DataSource用来取代DriverManager来获取Connection;
通过DataSource获得Connection速度很快;
通过DataSource获得的Connection都是已经被包裹过的(不是驱动原来的连接),他的close方法已经被修改。
一般DataSource内部会用一个连接池来缓存Connection,这样可以大幅度提高数据库的访问速度;
连接池可以理解成一个能够存放Connection的集合;
我们的程序只和DataSource打交道,不会直接访问连接池;

事务隔离级别(Transaction Isolation Levels)
JDBC定义了五种事务隔离级别:

TRANSACTION_NONE JDBC驱动不支持事务
TARNSACTION_READ_UNCOMMITED 允许脏读,不可重复读和幻读
TRANSACTION_READ_COMMITTED 禁止脏读,但允许不可重复读和幻读。
TRANSACTION_REPEATABLE_READ 禁止脏读和不可重复读,单运行幻读。
TRANSACTION_SERIALIZABLE 禁止脏读、不可重复读和幻读。

事务的结束只能有两种形式:提交和回滚。操作完全成功则提交,产生永久性的修改;操作不完全成功则回滚,恢复到事务开始前的状态。它们将结束一个事务。

(1)关闭自动提交事务。通过设置连接的自动提交事务属性为false,如下:
Connection conn = DriverManager.getConnection(“连接URL”, “用户名”, “密码”);
//关闭自动提交事务
conn.setAutoCommit(false);
(2)如果执行顺利,提交事务;一旦发生异常,回滚(rollback)事务,如下:
try{
conn.setAutoCommit(false); //关闭自动提交事务
stmt = conn.createStatement(); //创建会话
stmt.executeUpdate(“sql语句”);
conn.commit(); //提交事务
}catch(Exception e)
{
e.printStackTrace();
conn.rollback(); //回滚事务
}
(3)关闭连接,如下:
finally{
if(stmt != null)
stmt.close();
if(conn != null)
conn.close();
}
  
注意:尽量在代码中控制JDBC的事务。

对于事务的编写,也是要遵守一定的顺序的:

首先,.设置事务的提交方式为非自动提交:
conn.setAutoCommit(false);
接下来,.将需要添加事务的代码放入try,catch块中。
然后,.在try块内添加事务的提交操作,表示操作无异常,提交事务。
conn.commit();
尤其不要忘记,.在catch块内添加回滚事务,表示操作出现异常,撤销事务:
conn.rollback();
最后,设置事务提交方式为自动提交:
conn.setAutoCommit(true);
这样,通过简单的几步,我们就可以完成对事务处理的编写了。

例:定义了一个事务方法并在方法内实现了语句之间的一致性操作

     Connection con =null;     Statement st=null;     ResultSet rs=null;    PreparedStatement ps=null;public void startTransaction(){              con = DBCManager.getConnect();//获取连接对象                            try {                  //设置事务的提交方式为非自动提交:              con.setAutoCommit(false);              //将需要添加事务的代码一同放入try,catch块中                  //创建执行语句                  String sql ="delete from me where id = 7";                  String sql1 = "update me set name ='chengong' ,age ='34' where id =4";          //分别执行事务                  ps = con.prepareStatement(sql);                  ps.executeUpdate();                  ps = con.prepareStatement(sql1);                  ps.executeUpdate();  //在try块内添加事务的提交操作,表示操作无异常,提交事务。                  con.commit();              } catch (SQLException e) {              try {  //.在catch块内添加回滚事务,表示操作出现异常,撤销事务                  con.rollback();              } catch (SQLException e1) {                  e1.printStackTrace();              }                  e.printStackTrace();              }finally{                  try {      //设置事务提交方式为自动提交:                     con.setAutoCommit(true);                  } catch (SQLException e) {                     e.printStackTrace();                  }                  DBCManager.release(rs, ps, con);              }       }

参考博客:
http://www.cnblogs.com/azhqiang/p/4044127.html

原创粉丝点击