15
15
*/
16
16
package org .springframework .data .envers .repository .support ;
17
17
18
- import static org .springframework .data .history .RevisionMetadata .RevisionType .*;
19
-
20
- import java .util .ArrayList ;
21
- import java .util .List ;
22
- import java .util .Optional ;
23
-
24
18
import jakarta .persistence .EntityManager ;
25
-
26
19
import org .hibernate .Hibernate ;
27
20
import org .hibernate .envers .AuditReader ;
28
21
import org .hibernate .envers .AuditReaderFactory ;
32
25
import org .hibernate .envers .RevisionType ;
33
26
import org .hibernate .envers .query .AuditEntity ;
34
27
import org .hibernate .envers .query .AuditQuery ;
28
+ import org .hibernate .envers .query .criteria .AuditProperty ;
35
29
import org .hibernate .envers .query .order .AuditOrder ;
36
30
import org .springframework .data .domain .Page ;
37
31
import org .springframework .data .domain .PageImpl ;
38
32
import org .springframework .data .domain .Pageable ;
33
+ import org .springframework .data .domain .Sort ;
39
34
import org .springframework .data .history .AnnotationRevisionMetadata ;
40
35
import org .springframework .data .history .Revision ;
41
36
import org .springframework .data .history .RevisionMetadata ;
48
43
import org .springframework .transaction .annotation .Transactional ;
49
44
import org .springframework .util .Assert ;
50
45
46
+ import java .util .ArrayList ;
47
+ import java .util .Collections ;
48
+ import java .util .List ;
49
+ import java .util .Optional ;
50
+
51
+ import static org .springframework .data .history .RevisionMetadata .RevisionType .*;
52
+
51
53
/**
52
54
* Repository implementation using Hibernate Envers to implement revision specific query methods.
53
55
*
58
60
* @author Julien Millau
59
61
* @author Mark Paluch
60
62
* @author Sander Bylemans
63
+ * @author Niklas Loechte
61
64
*/
62
65
@ Transactional (readOnly = true )
63
66
public class EnversRevisionRepositoryImpl <T , ID , N extends Number & Comparable <N >>
@@ -70,14 +73,14 @@ public class EnversRevisionRepositoryImpl<T, ID, N extends Number & Comparable<N
70
73
* Creates a new {@link EnversRevisionRepositoryImpl} using the given {@link JpaEntityInformation},
71
74
* {@link RevisionEntityInformation} and {@link EntityManager}.
72
75
*
73
- * @param entityInformation must not be {@literal null}.
76
+ * @param entityInformation must not be {@literal null}.
74
77
* @param revisionEntityInformation must not be {@literal null}.
75
- * @param entityManager must not be {@literal null}.
78
+ * @param entityManager must not be {@literal null}.
76
79
*/
77
80
public EnversRevisionRepositoryImpl (JpaEntityInformation <T , ?> entityInformation ,
78
- RevisionEntityInformation revisionEntityInformation , EntityManager entityManager ) {
81
+ RevisionEntityInformation revisionEntityInformation , EntityManager entityManager ) {
79
82
80
- Assert .notNull (revisionEntityInformation , "RevisionEntityInformation must not be null" );
83
+ Assert .notNull (revisionEntityInformation , "RevisionEntityInformation must not be null! " );
81
84
82
85
this .entityInformation = entityInformation ;
83
86
this .entityManager = entityManager ;
@@ -91,7 +94,7 @@ public Optional<Revision<N, T>> findLastChangeRevision(ID id) {
91
94
.setMaxResults (1 ) //
92
95
.getResultList ();
93
96
94
- Assert .state (singleResult .size () <= 1 , "We expect at most one result" );
97
+ Assert .state (singleResult .size () <= 1 , "We expect at most one result. " );
95
98
96
99
if (singleResult .isEmpty ()) {
97
100
return Optional .empty ();
@@ -104,14 +107,14 @@ public Optional<Revision<N, T>> findLastChangeRevision(ID id) {
104
107
@ SuppressWarnings ("unchecked" )
105
108
public Optional <Revision <N , T >> findRevision (ID id , N revisionNumber ) {
106
109
107
- Assert .notNull (id , "Identifier must not be null" );
108
- Assert .notNull (revisionNumber , "Revision number must not be null" );
110
+ Assert .notNull (id , "Identifier must not be null! " );
111
+ Assert .notNull (revisionNumber , "Revision number must not be null! " );
109
112
110
113
List <Object []> singleResult = (List <Object []>) createBaseQuery (id ) //
111
114
.add (AuditEntity .revisionNumber ().eq (revisionNumber )) //
112
115
.getResultList ();
113
116
114
- Assert .state (singleResult .size () <= 1 , "We expect at most one result" );
117
+ Assert .state (singleResult .size () <= 1 , "We expect at most one result. " );
115
118
116
119
if (singleResult .isEmpty ()) {
117
120
return Optional .empty ();
@@ -133,15 +136,46 @@ public Revisions<N, T> findRevisions(ID id) {
133
136
return Revisions .of (revisionList );
134
137
}
135
138
136
- @ SuppressWarnings ("unchecked" )
137
- public Page <Revision <N , T >> findRevisions (ID id , Pageable pageable ) {
138
139
139
- AuditOrder sorting = RevisionSort .getRevisionDirection (pageable .getSort ()).isDescending () //
140
+ private AuditOrder mapRevisionSort (RevisionSort revisionSort ) {
141
+
142
+ return RevisionSort .getRevisionDirection (revisionSort ).isDescending () //
140
143
? AuditEntity .revisionNumber ().desc () //
141
144
: AuditEntity .revisionNumber ().asc ();
145
+ }
146
+
147
+ private List <AuditOrder > mapPropertySort (Sort sort ) {
148
+
149
+ if (sort .isEmpty ()) {
150
+ return Collections .singletonList (AuditEntity .revisionNumber ().asc ());
151
+ }
152
+
153
+ List <AuditOrder > result = new ArrayList <>();
154
+ for (Sort .Order order : sort ) {
155
+
156
+ AuditProperty <Object > property = AuditEntity .property (order .getProperty ());
157
+ AuditOrder auditOrder = order .getDirection ().isAscending () ?
158
+ property .asc () :
159
+ property .desc ();
160
+
161
+ result .add (auditOrder );
162
+ }
163
+
164
+ return result ;
165
+ }
166
+
167
+ @ SuppressWarnings ("unchecked" )
168
+ public Page <Revision <N , T >> findRevisions (ID id , Pageable pageable ) {
169
+
170
+ AuditQuery baseQuery = createBaseQuery (id );
171
+
172
+ List <AuditOrder > orderMapped = (pageable .getSort () instanceof RevisionSort ) ?
173
+ Collections .singletonList (mapRevisionSort ((RevisionSort ) pageable .getSort ())) :
174
+ mapPropertySort (pageable .getSort ());
175
+
176
+ orderMapped .forEach (baseQuery ::addOrder );
142
177
143
- List <Object []> resultList = createBaseQuery (id ) //
144
- .addOrder (sorting ) //
178
+ List <Object []> resultList = baseQuery //
145
179
.setFirstResult ((int ) pageable .getOffset ()) //
146
180
.setMaxResults (pageable .getPageSize ()) //
147
181
.getResultList ();
@@ -185,7 +219,7 @@ static class QueryResult<T> {
185
219
Assert .notNull (data , "Data must not be null" );
186
220
Assert .isTrue ( //
187
221
data .length == 3 , //
188
- () -> String .format ("Data must have length three, but has length %d" , data .length ));
222
+ () -> String .format ("Data must have length three, but has length %d. " , data .length ));
189
223
Assert .isTrue ( //
190
224
data [2 ] instanceof RevisionType , //
191
225
() -> String .format ("The third array element must be of type Revision type, but is of type %s" ,
@@ -201,7 +235,7 @@ RevisionMetadata<?> createRevisionMetadata() {
201
235
return metadata instanceof DefaultRevisionEntity //
202
236
? new DefaultRevisionMetadata ((DefaultRevisionEntity ) metadata , revisionType ) //
203
237
: new AnnotationRevisionMetadata <>(Hibernate .unproxy (metadata ), RevisionNumber .class , RevisionTimestamp .class ,
204
- revisionType );
238
+ revisionType );
205
239
}
206
240
207
241
private static RevisionMetadata .RevisionType convertRevisionType (RevisionType datum ) {
0 commit comments