问题是这样的,先更新一个实体数据,再根据其ID反查数据库查询更新后的数据,组装另一类实体数据保存
想把 更新和新增操作放在同一事务里以达到任一出错就回滚的目的,但是这样一来如何在新增时读到更新数据?此时因为更新和新增处于同一事务,还未提交。
问题是这样的,先更新一个实体数据,再根据其ID反查数据库查询更新后的数据,组装另一类实体数据保存
想把 更新和新增操作放在同一事务里以达到任一出错就回滚的目的,但是这样一来如何在新增时读到更新数据?此时因为更新和新增处于同一事务,还未提交。
在同一个事物中,更新后(事务未提交)再查询也是可以查询到更新后的数据,所以你的这个过程是可以的,是有数据库保证的。
举个例子吧:
package com.lz.dao.base;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Test {
public static void main(String[] args){
execute();
}
/**
* 使用的数据库为mysql,数据库默认隔离级别为:repeatable
* 下面的代码只为演示用
*/
public static void execute(){
Connection con = null;
try{
con = DbUtils.getConnection();
con.setAutoCommit(false);
String updateSql = "update lz_nav_category set name = 'google' where id = 55";//更新分类名称
PreparedStatement ps = con.prepareStatement(updateSql);
ps.executeUpdate();
String querySql = "select name from lz_nav_category where id = 55";//查询新分类名称,是可以查到的。
PreparedStatement ps2 = con.prepareStatement(querySql);
ResultSet set = ps2.executeQuery();
String newName = "";
if(set.next()){
newName = set.getString(1);
}
String insertSql = "INSERT INTO `lz`.`lz_nav` (`nav_name`, `nav_desc`) VALUES (?,?)";//用上面查询的新的名字组织数据,插入记录
PreparedStatement ps3 = con.prepareStatement(insertSql);
ps3.setString(1, newName);
ps3.setString(2, "描述");
ps3.executeUpdate();
con.commit(); //提交事务
}catch(Exception ex){
DbUtils.rollback(con);//回滚事务
}finally{
DbUtils.release(con, null, null);
}
}
}
最后结果:
保证不了,常用做法是加一个version或者update timestamp,entity每次更新都会更新version或者timestamp。如果事物查询后得到的数据,做更新,发现version或者timestamp与读取时不同,就抛出异常,回滚事务。