#76 - Adapt to API changes in Spring Data Commons.
This commit is contained in:
@@ -15,10 +15,17 @@
|
||||
*/
|
||||
package org.springframework.data.envers.repository.support;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.Value;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.hibernate.envers.DefaultRevisionEntity;
|
||||
import org.joda.time.DateTime;
|
||||
import org.springframework.data.history.RevisionMetadata;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link RevisionMetadata} working with a {@link DefaultRevisionEntity}.
|
||||
@@ -26,35 +33,25 @@ import org.springframework.util.Assert;
|
||||
* @author Oliver Gierke
|
||||
* @author Philip Huegelmeyer
|
||||
*/
|
||||
@Value
|
||||
public class DefaultRevisionMetadata implements RevisionMetadata<Integer> {
|
||||
|
||||
private final DefaultRevisionEntity entity;
|
||||
|
||||
/**
|
||||
* Creates a new {@link DefaultRevisionMetadata}.
|
||||
*
|
||||
* @param entity must not be {@literal null}.
|
||||
*/
|
||||
public DefaultRevisionMetadata(DefaultRevisionEntity entity) {
|
||||
|
||||
Assert.notNull(entity);
|
||||
this.entity = entity;
|
||||
}
|
||||
private final @NonNull @Getter(AccessLevel.NONE) DefaultRevisionEntity entity;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.history.RevisionMetadata#getRevisionNumber()
|
||||
*/
|
||||
public Integer getRevisionNumber() {
|
||||
return entity.getId();
|
||||
public Optional<Integer> getRevisionNumber() {
|
||||
return Optional.ofNullable(entity.getId());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.history.RevisionMetadata#getRevisionDate()
|
||||
*/
|
||||
public DateTime getRevisionDate() {
|
||||
return new DateTime(entity.getTimestamp());
|
||||
public Optional<LocalDateTime> getRevisionDate() {
|
||||
return Optional.of(LocalDateTime.from(Instant.ofEpochMilli(entity.getTimestamp())));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -16,13 +16,12 @@
|
||||
package org.springframework.data.envers.repository.support;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
@@ -42,7 +41,10 @@ import org.springframework.data.history.Revisions;
|
||||
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
|
||||
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
|
||||
import org.springframework.data.repository.core.EntityInformation;
|
||||
import org.springframework.data.repository.history.RevisionRepository;
|
||||
import org.springframework.data.repository.history.support.RevisionEntityInformation;
|
||||
import org.springframework.data.util.Pair;
|
||||
import org.springframework.data.util.StreamUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -53,7 +55,7 @@ import org.springframework.util.Assert;
|
||||
* @author Michael Igler
|
||||
*/
|
||||
public class EnversRevisionRepositoryImpl<T, ID extends Serializable, N extends Number & Comparable<N>>
|
||||
extends SimpleJpaRepository<T, ID> implements EnversRevisionRepository<T, ID, N> {
|
||||
extends SimpleJpaRepository<T, ID> implements RevisionRepository<T, ID, N> {
|
||||
|
||||
private final EntityInformation<T, ?> entityInformation;
|
||||
private final RevisionEntityInformation revisionEntityInformation;
|
||||
@@ -72,7 +74,7 @@ public class EnversRevisionRepositoryImpl<T, ID extends Serializable, N extends
|
||||
|
||||
super(entityInformation, entityManager);
|
||||
|
||||
Assert.notNull(revisionEntityInformation);
|
||||
Assert.notNull(revisionEntityInformation, "RevisionEntityInformation must not be null!");
|
||||
|
||||
this.entityInformation = entityInformation;
|
||||
this.revisionEntityInformation = revisionEntityInformation;
|
||||
@@ -84,7 +86,7 @@ public class EnversRevisionRepositoryImpl<T, ID extends Serializable, N extends
|
||||
* @see org.springframework.data.repository.history.RevisionRepository#findLastChangeRevision(java.io.Serializable)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Revision<N, T> findLastChangeRevision(ID id) {
|
||||
public Optional<Revision<N, T>> findLastChangeRevision(ID id) {
|
||||
|
||||
Class<T> type = entityInformation.getJavaType();
|
||||
AuditReader reader = AuditReaderFactory.get(entityManager);
|
||||
@@ -92,7 +94,7 @@ public class EnversRevisionRepositoryImpl<T, ID extends Serializable, N extends
|
||||
List<Number> revisions = reader.getRevisions(type, id);
|
||||
|
||||
if (revisions.isEmpty()) {
|
||||
return null;
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
N latestRevision = (N) revisions.get(revisions.size() - 1);
|
||||
@@ -101,7 +103,8 @@ public class EnversRevisionRepositoryImpl<T, ID extends Serializable, N extends
|
||||
|
||||
Object revisionEntity = reader.findRevision(revisionEntityClass, latestRevision);
|
||||
RevisionMetadata<N> metadata = (RevisionMetadata<N>) getRevisionMetadata(revisionEntity);
|
||||
return new Revision<N, T>(metadata, reader.find(type, id, latestRevision));
|
||||
|
||||
return Optional.of(Revision.of(metadata, reader.find(type, id, latestRevision)));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -109,7 +112,7 @@ public class EnversRevisionRepositoryImpl<T, ID extends Serializable, N extends
|
||||
* @see org.springframework.data.envers.repository.support.EnversRevisionRepository#findRevision(java.io.Serializable, java.lang.Number)
|
||||
*/
|
||||
@Override
|
||||
public Revision<N, T> findRevision(ID id, N revisionNumber) {
|
||||
public Optional<Revision<N, T>> findRevision(ID id, N revisionNumber) {
|
||||
|
||||
Assert.notNull(id, "Identifier must not be null!");
|
||||
Assert.notNull(revisionNumber, "Revision number must not be null!");
|
||||
@@ -128,7 +131,7 @@ public class EnversRevisionRepositoryImpl<T, ID extends Serializable, N extends
|
||||
AuditReader reader = AuditReaderFactory.get(entityManager);
|
||||
List<? extends Number> revisionNumbers = reader.getRevisions(type, id);
|
||||
|
||||
return revisionNumbers.isEmpty() ? new Revisions<N, T>(Collections.EMPTY_LIST)
|
||||
return revisionNumbers.isEmpty() ? Revisions.none()
|
||||
: getEntitiesForRevisions((List<N>) revisionNumbers, id, reader);
|
||||
}
|
||||
|
||||
@@ -149,13 +152,13 @@ public class EnversRevisionRepositoryImpl<T, ID extends Serializable, N extends
|
||||
}
|
||||
|
||||
if (pageable.getOffset() > revisionNumbers.size()) {
|
||||
return new PageImpl<Revision<N, T>>(Collections.<Revision<N, T>>emptyList(), pageable, 0);
|
||||
return new PageImpl<Revision<N, T>>(Collections.<Revision<N, T>> emptyList(), pageable, 0);
|
||||
}
|
||||
|
||||
int upperBound = pageable.getOffset() + pageable.getPageSize();
|
||||
long upperBound = pageable.getOffset() + pageable.getPageSize();
|
||||
upperBound = upperBound > revisionNumbers.size() ? revisionNumbers.size() : upperBound;
|
||||
|
||||
List<? extends Number> subList = revisionNumbers.subList(pageable.getOffset(), upperBound);
|
||||
List<? extends Number> subList = revisionNumbers.subList(toInt(pageable.getOffset()), toInt(upperBound));
|
||||
Revisions<N, T> revisions = getEntitiesForRevisions((List<N>) subList, id, reader);
|
||||
|
||||
revisions = isDescending ? revisions.reverse() : revisions;
|
||||
@@ -185,7 +188,7 @@ public class EnversRevisionRepositoryImpl<T, ID extends Serializable, N extends
|
||||
revisions.put((N) number, reader.find(type, id, number));
|
||||
}
|
||||
|
||||
return new Revisions<N, T>(toRevisions(revisions, revisionEntities));
|
||||
return Revisions.of(toRevisions(revisions, revisionEntities));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -197,31 +200,24 @@ public class EnversRevisionRepositoryImpl<T, ID extends Serializable, N extends
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private Revision<N, T> getEntityForRevision(N revisionNumber, ID id, AuditReader reader) {
|
||||
private Optional<Revision<N, T>> getEntityForRevision(N revisionNumber, ID id, AuditReader reader) {
|
||||
|
||||
Class<?> type = revisionEntityInformation.getRevisionEntityClass();
|
||||
|
||||
T revision = (T) reader.findRevision(type, revisionNumber);
|
||||
Object entity = reader.find(entityInformation.getJavaType(), id, revisionNumber);
|
||||
Optional<Object> entity = Optional.ofNullable(reader.find(entityInformation.getJavaType(), id, revisionNumber));
|
||||
|
||||
return new Revision<N, T>((RevisionMetadata<N>) getRevisionMetadata(revision), (T) entity);
|
||||
return entity.map(it -> Revision.of((RevisionMetadata<N>) getRevisionMetadata(revision), (T) it));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private List<Revision<N, T>> toRevisions(Map<N, T> source, Map<Number, Object> revisionEntities) {
|
||||
|
||||
List<Revision<N, T>> result = new ArrayList<Revision<N, T>>();
|
||||
|
||||
for (Entry<N, T> revision : source.entrySet()) {
|
||||
|
||||
N revisionNumber = revision.getKey();
|
||||
T entity = revision.getValue();
|
||||
RevisionMetadata<N> metadata = (RevisionMetadata<N>) getRevisionMetadata(revisionEntities.get(revisionNumber));
|
||||
result.add(new Revision<N, T>(metadata, entity));
|
||||
}
|
||||
|
||||
Collections.sort(result);
|
||||
return Collections.unmodifiableList(result);
|
||||
return source.entrySet().stream()//
|
||||
.map(entry -> Pair.of(revisionEntities.get(entry.getKey()), entry.getValue()))//
|
||||
.map(pair -> Revision.of((RevisionMetadata<N>) getRevisionMetadata(pair.getFirst()), pair.getSecond()))//
|
||||
.sorted()//
|
||||
.collect(StreamUtils.toUnmodifiableList());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -231,10 +227,18 @@ public class EnversRevisionRepositoryImpl<T, ID extends Serializable, N extends
|
||||
* @return
|
||||
*/
|
||||
private RevisionMetadata<?> getRevisionMetadata(Object object) {
|
||||
if (object instanceof DefaultRevisionEntity) {
|
||||
return new DefaultRevisionMetadata((DefaultRevisionEntity) object);
|
||||
} else {
|
||||
return new AnnotationRevisionMetadata<N>(object, RevisionNumber.class, RevisionTimestamp.class);
|
||||
|
||||
return object instanceof DefaultRevisionEntity //
|
||||
? new DefaultRevisionMetadata((DefaultRevisionEntity) object) //
|
||||
: new AnnotationRevisionMetadata<N>(object, RevisionNumber.class, RevisionTimestamp.class);
|
||||
}
|
||||
|
||||
private static int toInt(long value) {
|
||||
|
||||
if (value > Integer.MAX_VALUE) {
|
||||
throw new IllegalStateException(String.format("%s can't be mapped to an integer, too large!", value));
|
||||
}
|
||||
|
||||
return Long.valueOf(value).intValue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.envers.repository.support;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import org.hibernate.envers.RevisionNumber;
|
||||
import org.springframework.data.repository.history.support.RevisionEntityInformation;
|
||||
import org.springframework.data.util.AnnotationDetectionFieldCallback;
|
||||
@@ -27,6 +29,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Getter
|
||||
public class ReflectionRevisionEntityInformation implements RevisionEntityInformation {
|
||||
|
||||
private final Class<?> revisionEntityClass;
|
||||
@@ -39,24 +42,16 @@ public class ReflectionRevisionEntityInformation implements RevisionEntityInform
|
||||
*/
|
||||
public ReflectionRevisionEntityInformation(Class<?> revisionEntityClass) {
|
||||
|
||||
Assert.notNull(revisionEntityClass);
|
||||
Assert.notNull(revisionEntityClass, "Revision entity type must not be null!");
|
||||
|
||||
AnnotationDetectionFieldCallback fieldCallback = new AnnotationDetectionFieldCallback(RevisionNumber.class);
|
||||
ReflectionUtils.doWithFields(revisionEntityClass, fieldCallback);
|
||||
|
||||
this.revisionNumberType = fieldCallback.getType();
|
||||
this.revisionNumberType = fieldCallback.getRequiredType();
|
||||
this.revisionEntityClass = revisionEntityClass;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.history.support.RevisionEntityInformation#getRevisionNumberType()
|
||||
*/
|
||||
public Class<?> getRevisionNumberType() {
|
||||
return revisionNumberType;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.history.support.RevisionEntityInformation#isDefaultRevisionEntity()
|
||||
@@ -64,12 +59,4 @@ public class ReflectionRevisionEntityInformation implements RevisionEntityInform
|
||||
public boolean isDefaultRevisionEntity() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.history.support.RevisionEntityInformation#getRevisionEntityClass()
|
||||
*/
|
||||
public Class<?> getRevisionEntityClass() {
|
||||
return revisionEntityClass;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,15 +15,13 @@
|
||||
*/
|
||||
package org.springframework.data.envers.repository.support;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -88,17 +86,19 @@ public class RepositoryIntegrationTests {
|
||||
|
||||
countryRepository.save(de);
|
||||
|
||||
Revision<Integer, License> revision = licenseRepository.findLastChangeRevision(license.id);
|
||||
assertThat(revision, is(notNullValue()));
|
||||
Optional<Revision<Integer, License>> revision = licenseRepository.findLastChangeRevision(license.id);
|
||||
|
||||
Page<Revision<Integer, License>> revisions = licenseRepository.findRevisions(license.id, new PageRequest(0, 10));
|
||||
Revisions<Integer, License> wrapper = new Revisions<Integer, License>(revisions.getContent());
|
||||
assertThat(wrapper.getLatestRevision(), is(revision));
|
||||
assertThat(revision).hasValueSatisfying(it -> {
|
||||
|
||||
Page<Revision<Integer, License>> page = licenseRepository.findRevisions(license.id, PageRequest.of(0, 10));
|
||||
Revisions<Integer, License> revisions = Revisions.of(page.getContent());
|
||||
assertThat(revisions.getLatestRevision()).isEqualTo(it);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsEmptyRevisionsForUnrevisionedEntity() {
|
||||
assertThat(countryRepository.findRevisions(100L).getContent(), is(hasSize(0)));
|
||||
assertThat(countryRepository.findRevisions(100L)).isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,14 +119,19 @@ public class RepositoryIntegrationTests {
|
||||
|
||||
Revisions<Integer, Country> revisions = countryRepository.findRevisions(de.id);
|
||||
|
||||
assertThat(revisions, is(Matchers.<Revision<Integer, Country>>iterableWithSize(2)));
|
||||
assertThat(revisions).hasSize(2);
|
||||
|
||||
Iterator<Revision<Integer, Country>> iterator = revisions.iterator();
|
||||
Revision<Integer, Country> first = iterator.next();
|
||||
Revision<Integer, Country> second = iterator.next();
|
||||
|
||||
assertThat(countryRepository.findRevision(de.id, first.getRevisionNumber()).getEntity().name, is("Deutschland"));
|
||||
assertThat(countryRepository.findRevision(de.id, second.getRevisionNumber()).getEntity().name, is("Germany"));
|
||||
assertThat(countryRepository.findRevision(de.id, first.getRequiredRevisionNumber())).hasValueSatisfying(it -> {
|
||||
assertThat(it.getEntity().name).isEqualTo("Deutschland");
|
||||
});
|
||||
|
||||
assertThat(countryRepository.findRevision(de.id, second.getRequiredRevisionNumber())).hasValueSatisfying(it -> {
|
||||
assertThat(it.getEntity().name).isEqualTo("Germany");
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -145,10 +150,11 @@ public class RepositoryIntegrationTests {
|
||||
|
||||
countryRepository.save(de);
|
||||
|
||||
List<Revision<Integer, Country>> content = countryRepository
|
||||
.findRevisions(de.id, new PageRequest(0, 10, RevisionSort.desc())).getContent();
|
||||
Page<Revision<Integer, Country>> page = countryRepository.findRevisions(de.id,
|
||||
PageRequest.of(0, 10, RevisionSort.desc()));
|
||||
|
||||
assertThat(content, hasSize(2));
|
||||
assertThat(content.get(0).getRevisionNumber(), is(greaterThan(content.get(1).getRevisionNumber())));
|
||||
assertThat(page).hasSize(2);
|
||||
assertThat(page.getContent().get(0).getRequiredRevisionNumber())
|
||||
.isGreaterThan(page.getContent().get(1).getRequiredRevisionNumber());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,38 +15,15 @@
|
||||
*/
|
||||
package org.springframework.data.envers.sample;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
@MappedSuperclass
|
||||
@EqualsAndHashCode
|
||||
abstract class AbstractEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
public Long id;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(obj instanceof AbstractEntity)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AbstractEntity that = (AbstractEntity) obj;
|
||||
|
||||
return ObjectUtils.nullSafeEquals(this.id, that.id);
|
||||
}
|
||||
|
||||
}
|
||||
public @Id @GeneratedValue Long id;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user