Polishing.

Support ordering by more than a single property.
Fixed formatting.
Added `@uthor` annotations.

See https://github.com/spring-projects/spring-data-envers/issues/379
Original Pull Request https://github.com/spring-projects/spring-data-envers/pull/381
This commit is contained in:
Jens Schauder
2023-04-18 14:26:28 +02:00
parent e71b17020e
commit 1e4cb6ed1e
4 changed files with 55 additions and 38 deletions

View File

@@ -117,7 +117,7 @@
<repositories>
<repository>
<id>spring-libs-snapshot</id>
<url>https://repo.spring.io/libs-snapshot</url>
<url>https://repo.spring.io/snapshot</url>
</repository>
</repositories>

View File

@@ -15,14 +15,6 @@
*/
package org.springframework.data.envers.repository.support;
import static org.springframework.data.history.RevisionMetadata.RevisionType.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import javax.persistence.EntityManager;
import org.hibernate.Hibernate;
import org.hibernate.envers.AuditReader;
import org.hibernate.envers.AuditReaderFactory;
@@ -32,6 +24,7 @@ import org.hibernate.envers.RevisionTimestamp;
import org.hibernate.envers.RevisionType;
import org.hibernate.envers.query.AuditEntity;
import org.hibernate.envers.query.AuditQuery;
import org.hibernate.envers.query.criteria.AuditProperty;
import org.hibernate.envers.query.order.AuditOrder;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
@@ -49,6 +42,14 @@ import org.springframework.data.repository.history.support.RevisionEntityInforma
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import javax.persistence.EntityManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import static org.springframework.data.history.RevisionMetadata.RevisionType.*;
/**
* Repository implementation using Hibernate Envers to implement revision specific query methods.
*
@@ -72,12 +73,12 @@ public class EnversRevisionRepositoryImpl<T, ID, N extends Number & Comparable<N
* Creates a new {@link EnversRevisionRepositoryImpl} using the given {@link JpaEntityInformation},
* {@link RevisionEntityInformation} and {@link EntityManager}.
*
* @param entityInformation must not be {@literal null}.
* @param entityInformation must not be {@literal null}.
* @param revisionEntityInformation must not be {@literal null}.
* @param entityManager must not be {@literal null}.
* @param entityManager must not be {@literal null}.
*/
public EnversRevisionRepositoryImpl(JpaEntityInformation<T, ?> entityInformation,
RevisionEntityInformation revisionEntityInformation, EntityManager entityManager) {
RevisionEntityInformation revisionEntityInformation, EntityManager entityManager) {
Assert.notNull(revisionEntityInformation, "RevisionEntityInformation must not be null!");
@@ -145,29 +146,47 @@ public class EnversRevisionRepositoryImpl<T, ID, N extends Number & Comparable<N
private AuditOrder mapRevisionSort(RevisionSort revisionSort) {
return RevisionSort.getRevisionDirection(revisionSort).isDescending() //
? AuditEntity.revisionNumber().desc() //
: AuditEntity.revisionNumber().asc();
return RevisionSort.getRevisionDirection(revisionSort).isDescending() //
? AuditEntity.revisionNumber().desc() //
: AuditEntity.revisionNumber().asc();
}
private AuditOrder mapPropertySort(Sort sort) {
return sort.stream().findFirst().map(order -> order.getDirection().isAscending() ?
AuditEntity.property(order.getProperty()).asc() :
AuditEntity.property(order.getProperty()).desc())
.orElse(AuditEntity.revisionNumber().asc());
private List<AuditOrder> mapPropertySort(Sort sort) {
if (sort.isEmpty()) {
return Collections.singletonList(AuditEntity.revisionNumber().asc());
}
List<AuditOrder> result = new ArrayList<>();
for (Sort.Order order : sort) {
AuditProperty<Object> property = AuditEntity.property(order.getProperty());
AuditOrder auditOrder = order.getDirection().isAscending() ?
property.asc() :
property.desc();
result.add(auditOrder);
}
return result;
}
@SuppressWarnings("unchecked")
public Page<Revision<N, T>> findRevisions(ID id, Pageable pageable) {
AuditOrder orderMapped = (pageable.getSort() instanceof RevisionSort) ?
mapRevisionSort((RevisionSort) pageable.getSort()) :
mapPropertySort(pageable.getSort());
List<Object[]> resultList = createBaseQuery(id) //
.addOrder(orderMapped) //
.setFirstResult((int) pageable.getOffset()) //
.setMaxResults(pageable.getPageSize()) //
.getResultList();
AuditQuery baseQuery = createBaseQuery(id);
List<AuditOrder> orderMapped = (pageable.getSort() instanceof RevisionSort) ?
Collections.singletonList(mapRevisionSort((RevisionSort) pageable.getSort())) :
mapPropertySort(pageable.getSort());
orderMapped.forEach(baseQuery::addOrder);
List<Object[]> resultList = baseQuery //
.setFirstResult((int) pageable.getOffset()) //
.setMaxResults(pageable.getPageSize()) //
.getResultList();
Long count = (Long) createBaseQuery(id) //
.addProjection(AuditEntity.revisionNumber().count()).getSingleResult();
@@ -224,7 +243,7 @@ public class EnversRevisionRepositoryImpl<T, ID, N extends Number & Comparable<N
return metadata instanceof DefaultRevisionEntity //
? new DefaultRevisionMetadata((DefaultRevisionEntity) metadata, revisionType) //
: new AnnotationRevisionMetadata<>(Hibernate.unproxy(metadata), RevisionNumber.class, RevisionTimestamp.class,
revisionType);
revisionType);
}
private static RevisionMetadata.RevisionType convertRevisionType(RevisionType datum) {

View File

@@ -51,6 +51,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
*
* @author Oliver Gierke
* @author Jens Schauder
* @author Niklas Loechte
*/
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = Config.class)
@@ -68,13 +69,6 @@ class RepositoryIntegrationTests {
countryRepository.deleteAll();
}
@AfterEach
void tearDown() {
licenseRepository.deleteAll();
countryRepository.deleteAll();
}
@Test
void testLifeCycle() {
@@ -246,19 +240,22 @@ class RepositoryIntegrationTests {
@Test // #47
void paginationWithEmptyResult() {
check(23L, 0, 0, 0);
check(-23L, 0, 0, 0);
}
@Test
@Test // Envers #379
void testSort_pageableByProperty() {
Country de = new Country();
de.code = "de";
de.name = "Deutschland";
de.timestamp = Instant.parse("2000-01-01T00:00:00Z");
countryRepository.save(de);
de.timestamp = Instant.parse("2000-01-04T00:01:00Z");
countryRepository.save(de);
de.timestamp = Instant.parse("2000-01-04T00:00:00Z");
countryRepository.save(de);

View File

@@ -27,6 +27,7 @@ import org.hibernate.envers.Audited;
*
* @author Oliver Gierke
* @author Jens Schauder
* @author Niklas Loechte
*/
@Audited
@Entity