您的位置:首页 > 编程语言 > Java开发

Spring整合hibernate关于控制事务的问题

2017-07-25 14:31 579 查看
今天在使用spring整合hibernate的框架中控制事务遇到数据更新未取到最新的数据,代码结构如下:

注:此处调用查询方法定义为query(),

调用更新方法定义为update(),

调用执行sql的方法定义为execute();

TableObject 对应表 dataTable;

汇总表对应 totalDataTable;

/**
*a方法循环调用b方法
*/
public void a(){ //事务控制层
List<String> priNumbers = new ArrayList<String>();
priNumbers.add("1");
priNumbers.add("2");
priNumbers.add("3");
//循环修改dataTable的值
for(String priNumber : priNumbers ){
b(priNumber);
}

//根据dataTable的最新值修改totalDataTable的汇总值
c();
}
/**
*b方法查询对象并更新对象
*/
public void b(String priNumber){
//根据主键查询数据库表对象obj
TableObject obj = query(priNumber);
.
.
.//修改obj的值,此处省略

//更新obj值
update(obj);
}

/**
*c方法执行sql根据数据库表dataTable中的最新数据所有值之和修改汇总表totalDataTable的数据
*/
public void c(){
execute(sql);
}


在执行上述代码后,totalDataTable表中的数据总是取的是前两次更新后数据和最后一次未更新的数据值的汇总值,原因是:

事务控制在a()方法层因此事务提交是在a()方法结束时再调用commit()方法,而hibernate机制是在事务提交时才调用flush()方法将持久化对象同步到数据库,在此之前,该持久化对象是存在缓存中的,因此在b方法中执行update时数据库中的数据是没有同步的,所以我们会读取到最后一次未更新的数据值,但是为什么前两次更新后的数据是数据库的最新值呢?这是因为hibernate的缓存中只能存在一个同一类型的持久化对象,在我们调用query()方法时,hibernate就会将上一次的保存在缓存中的持久化对象flush到数据库同步,并更新缓存中的持久化对象。

解决方法:因为我们要取到数据必须是数据库最新的值,因此我们需要在调用hibernate的save()、update()、saveOrUpdate()方法后手动的调用一次flush()方法,使缓存数据与数据库数据同步。

注:如果我们不添加事务,实际是不会出现以上问题的,因为未加事务时,hibernate默认事务提交是在dao层方法调用结束后调用flush()和commit()方法,而正是因为我们添加了事务,导致hibernate调用flush()和commit()延迟到我们控制的事务结束时,这时执行的数据库更新操作如果没有调用flush()操作实际是存在缓存中而并没有和数据库同步的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  hibernate spring 事务