[hibernate-dev] HHH-10478 : OperationContext

Gail Badner gbadner at redhat.com
Mon Feb 8 01:28:47 EST 2016

The POC [1] assumes that we only need a single OperationContext for each
type of operation. OperationContextManager has a Map of OperationContext by
OperationContextType. Each OperationContext object is lazily created on the
first occurence of the corresponding type of operation.

Currently, when an operation is initiated (e.g., by Session.merge( entity
)), OperationContextManager [2] does the following:
- calls ManageableOperationContext#beforeOperation, which puts the
OperationContext "in progress";
- executes the operation, which performs cascades according to mappings;
- calls ManageableOperationContext#afterOperation, which puts the
OperationContext in an invalid state that is "not in progress".

When an operation cascades to other entities, the same OperationContext is

Obviously, OperationContextManager needs to know if an operation is
"top-level" (meaning that the operation is on the original entity, and not
cascaded). In the POC, if the relevant OperationContext is not in progress
at the time that an opeation is initiated, then OperationContextManager
assumes that the operation is top-level. If the OperationContext is "in
progress", then OperationContextManager assumes that this is a cascaded

I am not sure this is always correct. Can anyone think of a case where this
could break down?

In the POC, the following EventSource methods that contain an argument for
the operation cache has been deprecated and is no longer used because the
contents of that argument has been moved into an OperationContext:

public void merge(String entityName, Object object, Map copiedAlready)
public void persist(String entityName, Object object, Map createdAlready)
public void persistOnFlush(String entityName, Object object, Map
public void refresh(String entityName, Object object, Map refreshedAlready)
public void delete(String entityName, Object child, boolean
isCascadeDeleteEnabled, Set transientEntities)

Before the POC, it was the above methods that indicated that it was not
top-level. If it turns out that having a single OperationContext is not
valid, then there needs to be some other way to determine if the operation
was top-level.

I had originally planned to use PersistenceContext#getCascadeLevel == 0 to
indicate an operation was at the top-level, but I found that won't work for
some operations. For example, the cascade level for a top-level delete can
be > 1 when deleting orphans due to merge or save-or-update operations.
Another example is that cascade level is not 0 on top-level save-or-update
while flushing.

I have some ideas to work around this, but I didn't want to get too far
down that path if it wasn't an issue.



On Fri, Feb 5, 2016 at 8:17 PM, Gail Badner <gbadner at redhat.com> wrote:

> I've created a gist with an overview of the design:
> https://gist.github.com/gbadner/f0e635e8fba7b84af233 . I will add a new
> section tomorrow about possible shortcomings.
> Here is my POC:
> https://github.com/hibernate/hibernate-orm/compare/master...gbadner:HHH-10478-OperationContext
> . Although no tests fail, the approach may be too simple to model what is
> necessary.
> At this point the POC is squashed down to 1 commit:
> https://github.com/hibernate/hibernate-orm/commit/3d0e2378cb998788b3205afb1e15c443c5ba77e8
> Have a look and feel free to comment.
> Thanks,
> Gail

More information about the hibernate-dev mailing list