targetAuditMode=RelationTargetAuditMode.NOT_AUDITED should allow for missing entity targets

Description

If you use targetAuditMode=RelationTargetAuditMode.NOT_AUDITED on a relation and delete the (non-audited) target entity, queries for audits that contain links to the deleted target entity will throw an exception. Where it is thrown depends on how the source entity is implemented: if it implements hashCode() and includes the target entity in the hash, it'll be deep within the query itself.

Here's a concrete example:

Now suppose we issue three transactions:

  1. Transaction 1 creates and persists a Foo and a Bar.

  2. Transaction 2 deletes both the Foo and the Bar.

  3. Transaction 3 queries for all revisions.

The query will throw an exception like so:

It would be nice to fail gracefully in the face of non-existent entity targets, by nullifying the relation, perhaps.

Activity

Show:

Chris Cranford February 17, 2020 at 8:59 PM

It did but unfortunately what is now wip/6.0 is not the same branch in which I worked on before I moved to the DBZ team. I will re-prepare the fix against master and submit a new PR.

Former user February 13, 2020 at 9:51 PM

, it doesn't look like the fix made it to 6.0.alpha1...

Steve Ebersole December 6, 2018 at 3:43 PM

Preparing Alpha1 release

Chris Cranford April 12, 2017 at 5:05 PM

Upon testing this in action, I believe I'd rather see a few slight changes.

First, the RelationTargetNotFoundAction enum will maintain 3 values rather than 2:

Secondly, the Audited annotation will use a different default:

Lastly, the configuration property:

What this leads to is that users upgrading to 6.0 will see no change in behavior. The EntityNotFoundException will continue to be thrown without users having to make a single change to their classes, annotations, or configurations. This allows easy backward compatibility but flexibility for users to engage in the new behavior as needed.

So in order to actually ignore these EntityNotFoundException cases, users have several options.

The first is to enable the feature globally. Users can do that by changing the org.hibernate.envers.global_relation_not_found_legacy_flag to false. In other words, the default enum value of DEFAULT directly translates to whether legacy behavior is ON or OFF based on the configuration setting.

The second option is to enable the feature for a specific entity class by specifying the targetNotFoundAction attribute at the class level's @Audited annotation. This means if the property uses the DEFAULT value but the class specifies IGNORE or ERROR, the properties will use the value defined at the class level. The only exception is for cases where your property defines itself explicitly as IGNORE or ERROR and then the class-level value won't have precedence.

And obviously the third is to enable the feature by specifying the targetNotFoundAction attribute at the property level's @Audited annotation as mentioned above.

Users can also mix-n-match the global configuration property & annotation values as needed to address their individual needs.

Chris Cranford April 11, 2017 at 7:49 PM

I have also decided to add the following configuration setting:

By default, Envers will assume the IGNORE behavior. This means any @Audited to-one property will be handled to be ignored if not found. But some users may prefer the legacy behavior without having to modify all their @Audited annotations and rather be explicit about the cases where they'd like IGNORE to be used. For those situations, users can set this global configuration to false to invert the default behavior to do precisely that.

Fixed

Details

Assignee

Reporter

Components

Fix versions

Priority

Created March 5, 2013 at 7:58 PM
Updated January 18, 2024 at 1:50 PM
Resolved December 16, 2021 at 6:05 AM