You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Hibernate调用lock时自动提交数据库变更问题求助

问题解析与解决方案

Hey there, let's tackle your Hibernate/JSF issue step by step. First, let's unpack why that lock call is causing unintended database commits, then cover fixes and best practices.

Why the auto-commit happens

Hibernate's Session works with a persistence context (first-level cache) and uses dirty checking by default. Here's the breakdown:

  • When you load myDataObject into the Session (either via a previous fetch or initial load), it enters a persistent state.
  • Even with LockOptions.NONE, the object stays in the persistent context. Hibernate automatically tracks all changes to persistent objects in the background.
  • When the Session flushes (this happens automatically on transaction commit, or even during some query executions), Hibernate compares the object's current state to its state when it was first loaded. If there are differences (from JSF page inputs modifying bean properties, for example), it will generate an UPDATE statement and commit those changes to the database—no explicit save() or update() needed.

How to prevent unintended commits

Here are a few reliable ways to stop this auto-save behavior:

1. Replace the dirty object with a fresh database copy

Instead of locking the existing (potentially modified) myDataObject, fetch a clean version directly from the database and overwrite your bean's reference:

// Fetch a fresh, unmodified copy from the database
MyData freshData = sess.get(MyData.class, myDataObject.getId());
myDataObject = freshData; // Update your bean to use this clean object

This discards the dirty state entirely, so Hibernate won't trigger any updates when the Session flushes.

2. Mark the object as read-only

Tell Hibernate to skip dirty checking for this object explicitly:

Session sess = getCurrentSession();
sess.buildLockRequest(LockOptions.NONE).lock(myDataObject);
sess.setReadOnly(myDataObject, true); // Disable change tracking for this object

Once marked as read-only, Hibernate will ignore any changes to myDataObject and won't generate update statements for it.

3. Evict the object from the Session

Remove the object from Hibernate's persistence context, turning it into a detached object (detached objects aren't tracked for changes):

Session sess = getCurrentSession();
sess.buildLockRequest(LockOptions.NONE).lock(myDataObject);
sess.evict(myDataObject); // Remove from the persistence context

Just keep in mind: if you need to modify this object later, you'll have to reattach it via merge() or update().

Better practices for your use case

  • Shift permission checks earlier: Instead of waiting until save time to block unauthorized changes, validate permissions when the user first accesses the edit page or initiates a modify action. This reduces unnecessary database load and gives users clearer feedback faster.
  • Fix the JSF auto-save root cause: Page navigation triggering saves points to a JSF configuration issue. Check:
    • Are your managed beans using @SessionScoped (which retains state across navigation)? Switching to @ViewScoped might prevent unintended property updates.
    • Do any form components have valueChangeListener or immediate="true" set, which could trigger partial submits during navigation?
  • Quick note on NonUniqueObjectException: Even though you said it's not the main focus, this usually happens when the Session already contains another instance of the same entity with the same ID. Fix it by using merge() instead of save()/update(), or evict the existing instance from the Session first.

内容的提问来源于stack exchange,提问作者Pere

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 08:17:45