带有UserThread和序列化的线程中的Hibernate会话

时间:2012-03-05 12:32:16

标签: java hibernate concurrency

我有以下情况: 我有一个使用会话保存或更新的线程

public void run()
{
    Session session = DAO.getInstance().getCurrentSession();
    Transaction tx = null;
        try
    {

        tx = session.beginTransaction();
        session.saveOrUpdate(entity);
             }catch.....
     }

但与此同时,在使用session.saveorUpdate进行序列化时,我更改了实体对象... 因此,用户线程将在会话序列化期间更改数据..

我该如何克服这个问题? hibernate有一个简单的方法吗?

编辑: 最大的问题在于UserThread在saveOrUpdate方法中更改实体对象中的某些数据。

2 个答案:

答案 0 :(得分:2)

听起来您对使用版本控制的乐观并发控制感兴趣。

乐观并发控制

如果您以前没有遇到它,那么比较和交换的想法类似,Hibernate将与实体一起管理版本。通过在更新期间增加版本号并检查它之后没有更改,Hibernate可以检测到冲突和错误。它乐观地认为实际争用很少,并且让开发人员处理异常。我一般都认为这是事实,正如Hibernate文档所说的那样;

  

唯一与高并发性和高并发性的方法   可伸缩性,是带版本控制的乐观并发控制。

您可以调整Hibernate的事务可见性和隔离级别以影响更精细的细节,请参阅

http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/transactions.html#transactions-optimistic

交易划分

我无法从问题的代码片段中分辨出来,但也可能值得考虑事务边界。通常,我会在业务操作开始或请求,提交和完成时启动事务(beginTransaction)。所有更新都在此会话中执行(使用一个每个会话的线程Hibernate)模型。我仍然在他们自己的线程上处理每个业务操作或请求,并依赖通常的Hiernate issolation级别等来管理冲突。

我提到它是因为可能有机会退后一步,考虑为什么要从多个线程进行更新。可能是您的应用程序不适合我试图概述的方法,但可能值得考虑是否可以转移以避免真正的多线程更新。

如果生产中可能经常发生冲突,那么当然不值得理解。测试这可以帮助您了解您是否真的需要担心它,或者您是否可以依赖通常的事务控制来检测冲突并以其他方式处理它们。

答案 1 :(得分:1)

一种方法是在实体对象上进行同步:

public void run()
{
    Session session = DAO.getInstance().getCurrentSession();
    Transaction tx = null;
        try
    {

        tx = session.beginTransaction();
        synchronized(entity) {
            session.saveOrUpdate(entity);
        }
     }