Skip to content

Commit 8c3a067

Browse files
Chaediemp911de
authored andcommitted
Allow customization of @RevisionTimestamp property name.
We now detect the property name annotated with RevisionTimestamp to determine the property name from the model instead of assuming a hard-coded timestamp property. Signed-off-by: ChaedongIm <[email protected]> See #2850 Original pull request: #4003
1 parent 18db5fa commit 8c3a067

File tree

5 files changed

+91
-4
lines changed

5 files changed

+91
-4
lines changed

spring-data-envers/src/main/java/org/springframework/data/envers/repository/support/DefaultRevisionEntityInformation.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
* {@link RevisionEntityInformation} for {@link DefaultRevisionEntity}.
2323
*
2424
* @author Oliver Gierke
25+
* @author Chaedong Im
2526
*/
2627
class DefaultRevisionEntityInformation implements RevisionEntityInformation {
2728

@@ -36,4 +37,8 @@ public boolean isDefaultRevisionEntity() {
3637
public Class<?> getRevisionEntityClass() {
3738
return DefaultRevisionEntity.class;
3839
}
40+
41+
public String getRevisionTimestampFieldName() {
42+
return "timestamp";
43+
}
3944
}

spring-data-envers/src/main/java/org/springframework/data/envers/repository/support/EnversRevisionRepositoryImpl.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,14 @@
6666
* @author Greg Turnquist
6767
* @author Aref Behboodi
6868
* @author Ngoc Nhan
69+
* @author Chaedong Im
6970
*/
7071
@Transactional(readOnly = true)
7172
public class EnversRevisionRepositoryImpl<T, ID, N extends Number & Comparable<N>>
7273
implements RevisionRepository<T, ID, N> {
7374

7475
private final EntityInformation<T, ?> entityInformation;
76+
private final RevisionEntityInformation revisionEntityInformation;
7577
private final EntityManager entityManager;
7678

7779
/**
@@ -90,14 +92,16 @@ public EnversRevisionRepositoryImpl(JpaEntityInformation<T, ?> entityInformation
9092
Assert.notNull(revisionEntityInformation, "RevisionEntityInformation must not be null!");
9193

9294
this.entityInformation = entityInformation;
95+
this.revisionEntityInformation = revisionEntityInformation;
9396
this.entityManager = entityManager;
9497
}
9598

9699
@SuppressWarnings("unchecked")
97100
public Optional<Revision<N, T>> findLastChangeRevision(ID id) {
98101

102+
String timestampFieldName = getRevisionTimestampFieldName();
99103
List<Object[]> singleResult = createBaseQuery(id) //
100-
.addOrder(AuditEntity.revisionProperty("timestamp").desc()) //
104+
.addOrder(AuditEntity.revisionProperty(timestampFieldName).desc()) //
101105
.addOrder(AuditEntity.revisionNumber().desc()) //
102106
.setMaxResults(1) //
103107
.getResultList();
@@ -213,6 +217,16 @@ private Revision<N, T> createRevision(QueryResult<T> queryResult) {
213217
return Revision.of((RevisionMetadata<N>) queryResult.createRevisionMetadata(), queryResult.entity);
214218
}
215219

220+
private String getRevisionTimestampFieldName() {
221+
if (revisionEntityInformation instanceof ReflectionRevisionEntityInformation reflection) {
222+
return reflection.getRevisionTimestampFieldName();
223+
} else if (revisionEntityInformation instanceof DefaultRevisionEntityInformation defaultInfo) {
224+
return defaultInfo.getRevisionTimestampFieldName();
225+
} else {
226+
return "timestamp";
227+
}
228+
}
229+
216230
@SuppressWarnings("unchecked")
217231
static class QueryResult<T> {
218232

spring-data-envers/src/main/java/org/springframework/data/envers/repository/support/ReflectionRevisionEntityInformation.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package org.springframework.data.envers.repository.support;
1717

1818
import org.hibernate.envers.RevisionNumber;
19+
import org.hibernate.envers.RevisionTimestamp;
1920

2021
import org.springframework.data.repository.history.support.RevisionEntityInformation;
2122
import org.springframework.data.util.AnnotationDetectionFieldCallback;
@@ -27,11 +28,13 @@
2728
* find out about the revision number type.
2829
*
2930
* @author Oliver Gierke
31+
* @author Chaedong Im
3032
*/
3133
public class ReflectionRevisionEntityInformation implements RevisionEntityInformation {
3234

3335
private final Class<?> revisionEntityClass;
3436
private final Class<?> revisionNumberType;
37+
private final String revisionTimestampFieldName;
3538

3639
/**
3740
* Creates a new {@link ReflectionRevisionEntityInformation} inspecting the given revision entity class.
@@ -42,10 +45,14 @@ public ReflectionRevisionEntityInformation(Class<?> revisionEntityClass) {
4245

4346
Assert.notNull(revisionEntityClass, "Revision entity type must not be null");
4447

45-
AnnotationDetectionFieldCallback fieldCallback = new AnnotationDetectionFieldCallback(RevisionNumber.class);
46-
ReflectionUtils.doWithFields(revisionEntityClass, fieldCallback);
48+
AnnotationDetectionFieldCallback revisionNumberFieldCallback = new AnnotationDetectionFieldCallback(RevisionNumber.class);
49+
ReflectionUtils.doWithFields(revisionEntityClass, revisionNumberFieldCallback);
4750

48-
this.revisionNumberType = fieldCallback.getRequiredType();
51+
AnnotationDetectionFieldCallback revisionTimestampFieldCallback = new AnnotationDetectionFieldCallback(RevisionTimestamp.class);
52+
ReflectionUtils.doWithFields(revisionEntityClass, revisionTimestampFieldCallback);
53+
54+
this.revisionNumberType = revisionNumberFieldCallback.getRequiredType();
55+
this.revisionTimestampFieldName = revisionTimestampFieldCallback.getRequiredField().getName();
4956
this.revisionEntityClass = revisionEntityClass;
5057

5158
}
@@ -61,4 +68,8 @@ public Class<?> getRevisionEntityClass() {
6168
public Class<?> getRevisionNumberType() {
6269
return this.revisionNumberType;
6370
}
71+
72+
public String getRevisionTimestampFieldName() {
73+
return this.revisionTimestampFieldName;
74+
}
6475
}

spring-data-envers/src/test/java/org/springframework/data/envers/repository/support/EnversRevisionRepositoryImplUnitTests.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.hibernate.envers.DefaultRevisionEntity;
2222
import org.hibernate.envers.RevisionType;
2323
import org.junit.jupiter.api.Test;
24+
2425
import org.springframework.data.history.AnnotationRevisionMetadata;
2526
import org.springframework.data.history.RevisionMetadata;
2627

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright 2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.envers.sample;
17+
18+
import jakarta.persistence.Entity;
19+
import jakarta.persistence.GeneratedValue;
20+
import jakarta.persistence.Id;
21+
22+
import org.hibernate.envers.RevisionEntity;
23+
import org.hibernate.envers.RevisionNumber;
24+
import org.hibernate.envers.RevisionTimestamp;
25+
26+
/**
27+
* Custom revision entity with a non-standard timestamp field name to test dynamic timestamp property detection.
28+
*
29+
* @author Chaedong Im
30+
*/
31+
@Entity
32+
@RevisionEntity
33+
public class CustomRevisionEntityWithDifferentTimestamp {
34+
35+
@Id @GeneratedValue @RevisionNumber
36+
private int revisionId;
37+
38+
@RevisionTimestamp
39+
private long myCustomTimestamp; // Non-standard field name
40+
41+
public int getRevisionId() {
42+
return revisionId;
43+
}
44+
45+
public void setRevisionId(int revisionId) {
46+
this.revisionId = revisionId;
47+
}
48+
49+
public long getMyCustomTimestamp() {
50+
return myCustomTimestamp;
51+
}
52+
53+
public void setMyCustomTimestamp(long myCustomTimestamp) {
54+
this.myCustomTimestamp = myCustomTimestamp;
55+
}
56+
}

0 commit comments

Comments
 (0)