在实际业务中,我们常常能够遇到一些需求,这个需求中有数个操作,要所有操作都成功完成了这个需求才实现了,这就是原子性事务。比如说,银行交易,转账过程包括转账者钱的数量扣除和接受者钱的数量增加,要同时完成才能算转账成功,不允许只完成一部分。
jdbc实现原子事务的过程主要是通过手动控制提交(commit)来实现的,在一次提交过程中将所有需要的操作都准备好,然后一次性提交到数据库中,如果中间某一个过程执行失败,则会进行回滚操作,防止部分更新,以下面的代码为例,代码是实现报表的定制,需要往两个表中插入数据才算定制成功,往这两个表中插入数据算一个原子事务,代码如下:
/*
* 通过传入的TableItem参数来保存报表,返回保存的报表条目的主键值
* 报表插入过程应该为一个整体的事务,要么都成功,要么都失败
* params:
* value:报表需要的参数
* rowList:行列条件
* colList:列条件
* return:
* primaryKey:生成的主键值
*/
public int saveReportTable(TableItem value,List<TJItem> rowList,List<TJItem> colList){
int primaryKey=0;
String sql="insert into REPORTTABLE(TITLE";
boolean hasSD=false; //是否有起始日期
boolean hasED=false; //是否有终止日期
if(value.getStartDate()!=null){
hasSD=true;
sql+=",STARTDATE";
}
if(value.getEndDate()!=null){
hasED=true;
sql+=",ENDDATE";
}
sql+=",STARTTIME"; //不管是否是空,都插入,判断在后面
sql+=",ENDTIME";
sql+=") VALUES(?";
if(hasSD)
sql+=",?";
if(hasED)
sql+=",?";
sql+=",?";
sql+=",?";
sql+=")";
logger.info("保存报表构造的sql为:"+sql);
//插入行列条件的sql
String tjSql="insert into REPORTTJ(TABLE_ID,ROWORCOL,TABLE_NAME,TABLE_SK,TJVALUE,TJNAME) VALUES(?,?,?,?,?,?)";
logger.info("插入行列条件的sql为:");
try {
con.setAutoCommit(false); //取消自动提交,改为手动提交
//保存报表sql过程
String generatedColumns[] = { "TABLE_ID" };
pres=con.prepareStatement(sql,generatedColumns);
int num=1;
pres.setString(num, value.getTableTitle());
num++;
if(hasSD){
pres.setDate(num, value.getStartDate());
num++;
}
if(hasED){
pres.setDate(num, value.getEndDate());
num++;
}
pres.setInt(num, value.getStartTime());
num++;
pres.setInt(num, value.getEndTime());
num++;
pres.executeUpdate(); //插入到数据库
ResultSet res=pres.getGeneratedKeys(); //返回生成的主键
while(res.next()){
primaryKey=res.getInt(1); //生成的主键
}
//保存行条件过程
pres=con.prepareStatement(tjSql);
TJItem tItem;
for(int i=0;i<rowList.size();i++){
tItem=rowList.get(i);
pres.setInt(1, primaryKey); //所属的报表的ID
pres.setInt(2, tItem.getFlag());
pres.setString(3, tItem.getTableName());
pres.setString(4, tItem.getKeyName());
pres.setString(5, tItem.getWhereStr());
pres.setString(6, tItem.getWhereName());
pres.addBatch(); //为了批量处理
}
pres.executeBatch(); //实现批量插入
//保存列条件过程
pres=con.prepareStatement(tjSql);
for(int i=0;i<colList.size();i++){
tItem=colList.get(i);
pres.setInt(1, primaryKey); //所属的报表的ID
pres.setInt(2, tItem.getFlag());
pres.setString(3, tItem.getTableName());
pres.setString(4, tItem.getKeyName());
pres.setString(5, tItem.getWhereStr());
pres.setString(6, tItem.getWhereName());
pres.addBatch(); //为了批量处理
}
pres.executeBatch(); //实现批量插入
con.commit(); //提交所有事务
if(res!=null)
res.close();
if(pres!=null)
pres.close();
con.setAutoCommit(true); //打开自动提交过程
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return primaryKey;
}