使用同一会话和事务进行Hibernate保存和获取操作

8

我有一个场景,服务层是事务性的,只有在事务完成后才能提交。我将其简化为以下形式。

begin transaction

for(loop){

getHibernateTemplate().save(object);


getHibernateTemplate().get(object_by_key); //cannot get object by object_by_key because "object" is not commit into database until entire for(loop) completed. 

}

end transaction. commit();

我尝试在save()之后添加getHibernateTemplate().flush()。我能够在show_sql中看到"insert",但记录没有出现在数据库中。如何强制在每次save()之后立即写入数据库,而不是等待提交?
4个回答

6

getHibernateTemplate().flush()是强制Hibernate将数据写入数据库(发送插入和更新查询)的方法。这将在事务内完成,因此在提交事务之前(从SQL客户端查询)对其他事务不可见。

如果插入查询显示在日志中,则已将其发送到数据库。 如果要测试记录是否已正确插入,则可以执行getHibernateTemplate().clear()(将删除所有缓存数据),然后执行getHibernateTemplate.get()(将从数据源查询)。 或者,另一种测试方法是使用jdbcTemplate(使用相同的数据库)进行查询和检查。

如果您使用的SQL客户端工具允许您指定隔离级别-以未提交读隔离级别启动SQL客户端会话-则可以在提交事务之前查看所做的更改。


getHibernateTemplate().flush() 不是一个重量级操作吗?如果我们在循环内调用它,会不会影响应用程序的负载和性能呢? - Chamly Idunil

0

getHibernateTemplate() 方法每次返回相同的模板吗?或者,如果不是基于公共会话的模板。最好将模板保存到本地变量中并重复使用它,而不是每次调用 getHibernateTemplate()。

begin transaction

template = getHibernateTemplate();

for(loop){

template.save(object);


template.get(object_by_key); //cannot get object by object_by_key because "object" is not commit into database until entire for(loop) completed. 

}

end transaction. commit();

我认为你的问题可能是因为你在保存和获取调用时使用了不同的会话。如果它们是在同一个会话中进行的,你应该能看到你想要的行为。


如何检查是否为同一个 HibernateTemplate()?在 HibernateTemplate() 中有没有任何方法,我可以检查类序列号等等?=) - cometta
@cometta 只需分配并重用它,而不是一遍又一遍地调用getHibernateTemplate。 - James DW

0

据我所知,你根本无法做到这一点。它不起作用。在同一事务中检索保存的对象是不可能的。我认为这是因为会话是一级缓存,只有在创建该对象的另一个事务提交后,Hibernate 才能获取新对象。


0
为什么需要通过键获取对象?你已经有了对象!如果你真的需要对象键(用于打印吗?),你可以为每个保存操作使用一个新事务,在循环中放置transaction begincommit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接