jakartaee / jakartaee/persistence

access to original entity state in @PreUpdate lifecycle callback

Open
#757 1 comment 2 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
268
Forks
78
Avg merge
1d 6h
Merged PRs (30d)
13

Description

## Problem
Currently, the @PreUpdate lifecycle callback only provides access to the
modified entity state. There is no standard way to access the original
(pre-modification) values within this callback.

## Use Cases
- Audit logging (track what changed)
- Conditional validation based on previous values
- Sending notifications only when specific fields change
- Business rules that depend on state transitions

## Current Workarounds
Developers must use vendor-specific solutions:
- Hibernate: Interceptors or Envers
- @Transient fields with @PostLoad
- Manual database queries

These approaches are:
- Non-portable across JPA implementations
- Complex and error-prone
- Performance inefficient (extra queries)

## Comparison with Other ORMs
Modern ORMs provide this feature out-of-the-box:

**Entity Framework (.NET)**
```csharp
var oldValue = entry.OriginalValues["propertyName"];
var newValue = entry.CurrentValues["propertyName"];
```

**Ruby on Rails (Active Record)**
```ruby
old_value = name_was
new_value = name
```

**Sequelize (Node.js)**
```javascript
oldValue = instance._previousDataValues.name;
newValue = instance.dataValues.name;
```

## Proposed Solution

### Option A: Additional callback parameter
```java
@PreUpdate
public void beforeUpdate(EntityChangeSet changeSet) {
for (String property : changeSet.getModifiedProperties()) {
Object oldValue = changeSet.getOriginalValue(property);
Object newValue = changeSet.getCurrentValue(property);
// audit logic
}
}
```

### Option B: New annotation
```java
@PreUpdate
public void beforeUpdate() {
// current behavior
}

@PreUpdateWithChanges
public void beforeUpdateWithChanges(EntityChangeSet changeSet) {
// access to original values
}
```

### Option C: EntityManager API enhancement
```java
@PreUpdate
public void beforeUpdate() {
EntityChangeSet changes = entityManager.getChangeSet(this);
Object oldValue = changes.getOriginalValue("propertyName");
}
```

## Benefits
- Portable across all JPA implementations
- Simpler, cleaner code
- Better performance (no extra queries)
- Consistency with other modern ORM frameworks
- Backward compatible (doesn't break existing code)

## Questions
- Would this be feasible for Jakarta Persistence 4.0?
- Are there technical limitations I'm not considering?
- Which API approach would be preferred by the spec team?
```

Contributor guide

Open the contributing guide

Research direction

The issue names no repository files, tests, or entry points. Start by reviewing the existing @PreUpdate lifecycle-callback contract and comparing proposed options A–C for feasibility and portability. Done means the spec team has selected an API direction and recorded concrete scope and compatibility requirements.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
backend-api-design, databases
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.