Hibernate:如何禁用脏对象的自动保存?

30

我很惊讶地发现,Hibernate会在事务结束时自动保存脏对象,而无需显式调用类似于

dao.save(object)

我想到了这篇文章中描述的情况。

我的问题是:是否有一种方法可以禁用此行为?乍一看,这种自动保存似乎相当危险,因为您需要知道哪些对象连接到会话,哪些对象没有连接,而且似乎非常容易出错。您能告诉我这种自动保存方法的好处是什么吗?我几乎看不到任何好处。我希望总是显式地调用dao.save(object)来更新任何内容。

我听说过一种可能的解决方法,即在sessionFactory上使用entityInterceptor。这个自定义entityInterceptor将覆盖findDirty方法,以永远不查找任何脏数据,但在这种情况下,我认为dao.save也将无法工作。有任何想法吗?


1
这确实是关于Hibernate最令人讨厌的事情之一。考虑改用Ebean :) - Hoof
2个回答

15

我同意,您不应该手动刷新。 我的Web应用程序开发经验表明,FlushMode应该设置为“AUTO”。 但有时我需要禁用脏检查(用于验证数据,在数据库中验证数据和通过表单或服务返回的数据)。 为此,我创建了一个特殊类,并通过更改FLUSHMODE禁用了脏检查:

@Component
public class ValidateRefPaysService implements IValidateRefPaysService {

    ...

    @Autowired
    @Qualifier("sessionFactory")
    private SessionFactory sessionFactory;

    @Override
    @Transactional(readOnly=true) 
    public void validate(RefPays refPays) throws BusinessException {
        
        try {
            sessionFactory.getCurrentSession().setFlushMode(FlushMode.MANUAL);
        
            if ( refPays.getId() != null ) {
                RefPays refPaysBase = refPaysDAO.getById(refPays.getId());
                if ( refPaysBase != null )  {
                    throw new BusinessException("id already exists in database.", "RefPays.savePays.id.alreadyexist", "refPays.savePays.id.alreadyexist");
                }
            }
        } finally {
            sessionFactory.getCurrentSession().setFlushMode(FlushMode.AUTO);
        }
    }
}

1
如果您只验证实体,为什么需要禁用脏检查? - manash

5

要禁用自动状态管理,请将您的会话的flush模式设置为手动。然后,您可以调用session.flush()来实际写出与您的会话相关的所有脏实体。


9
嗯...我并不想禁用Hibernate的自动刷新功能,否则我将失去Hibernate性能相关设施带来的好处。我只想让那些我明确调用dao.save或dao.update的对象变为脏对象(dirty objects)。 - machinery
1
你无法手动跟踪对象的更改状态,这是使用 ORM 的主要优势之一:自动跟踪哪些对象已更改并发出必要的 SQL 操作。 - Stefan Haberl
9
这是主要优势之一的原因是什么?你有多经常编写代码时没有明确地在实际想要保存的实体上发出“保存”命令?当然,脏数据检查仍然应该存在,这样如果你发出保存命令但实体并不脏,则不会向数据库发出查询。 - Hoof

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