Why would @OptimisticLock(excluded=true) not be working for fields that implement associations?

Hi –

we implement versioned optimistic locking in our project. We are trying to avoid the version number being updated across associations – any associations and in any direction. We implement bi-directional associations.

However, we can’t seem to be able to stop the version number being incremented on children when the parent is updated, even with this annotation.

CascadeType we use for OneToManys is CascadeType.ALL. Fetching is always LAZY in both directions.

What are we doing wrong?

Thanks in advance!

Show us the entity model and the transaction code you are running.

Here is how we annotate one to many relationships:

class Parent {
     @OneToMany(cascade={CascadeType.ALL}, mappedBy="parent", fetch=FetchType.LAZY)
     @BatchSize(size=25)
     @Cascade(CascadeType.ALL)
     @OptimisticLock(excluded=true)
     Set<Child> children;
}

I can’t think of a reason why we use both the javax and Hibernate Cascade. Somebody must have found it solved for some issue. If you think that may be problematic, it would be worth investigating.

Here’s the child

class Child {
     @JoinColumn(name="parentId")
     @ManyToOne(optional=false, fetch=FetchType.LAZY)
     @OptimisticLock(excluded=true)
     Parent parent;
}

As far as transaction code, there are several layers of our custom data framework code before we get to hibernate, so it’s difficult for me to provide it meaningfully. But there’s nothing particularly funky going on. L1 session cache lifetimes are mapped to transaction lifetimes. In write transactions (we force the user to declare write or read intent when a transaction is begun) we set defaultReadOnly to false…

Anyhow, when we update Parent, all child versions are updated as well (and a fetch is executed to get the children if they aren’t already in session). We’re trying to stop version increments in all directions across associations.

We use saveOrUpdate() when saving entities.

All classes are annotated with

@OptimisticLocking(type=OptimisticLockType.VERSION)

Anyhow, when we update Parent, all child versions are updated as well (and a fetch is executed to get the children if they aren’t already in session). We’re trying to stop version increments in all directions across associations.

I think this is because your use of CascadeType.ALL.

We use saveOrUpdate() when saving entities.

This can be another reason for this behavior, as that will trigger a different cascade type, namely SAVE_UPDATE.

You should consider switching to the more standard session.merge() method instead, which will only trigger SAVE_UPDATE if Hibernate was booted through the native APIs.

1 Like