#30 - Added Querydsl support based on fragments.

EnversRevisionRepositoryImpl is now just a fragment and doesn’t inherit any implementation.

Original pull requests: #45.
This commit is contained in:
Jens Schauder
2018-01-04 13:51:11 +01:00
committed by Oliver Gierke
parent 9446be0b5f
commit bdb539d800
3 changed files with 19 additions and 147 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,13 +21,8 @@ import javax.persistence.EntityManager;
import org.hibernate.envers.DefaultRevisionEntity;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.core.GenericTypeResolver;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.querydsl.QuerydslUtils;
import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.RepositoryComposition.RepositoryFragments;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
@@ -76,14 +71,16 @@ public class EnversRevisionRepositoryFactoryBean<T extends RevisionRepository<S,
* Repository factory creating {@link RevisionRepository} instances.
*
* @author Oliver Gierke
* @author Jens Schauder
*/
private static class RevisionRepositoryFactory<T, ID, N extends Number & Comparable<N>> extends JpaRepositoryFactory {
private final RevisionEntityInformation revisionEntityInformation;
private final EntityManager entityManager;
/**
* Creates a new {@link RevisionRepositoryFactory} using the given {@link EntityManager} and revision entity class.
*
*
* @param entityManager must not be {@literal null}.
* @param revisionEntityClass can be {@literal null}, will default to {@link DefaultRevisionEntity}.
*/
@@ -91,73 +88,26 @@ public class EnversRevisionRepositoryFactoryBean<T extends RevisionRepository<S,
super(entityManager);
this.entityManager = entityManager;
this.revisionEntityInformation = Optional.ofNullable(revisionEntityClass) //
.filter(it -> !it.equals(DefaultRevisionEntity.class))//
.<RevisionEntityInformation> map(ReflectionRevisionEntityInformation::new) //
.orElseGet(DefaultRevisionEntityInformation::new);
}
/*
* (non-Javadoc)
* @see org.springframework.data.jpa.repository.support.JpaRepositoryFactory#getTargetRepository(org.springframework.data.repository.core.RepositoryInformation, javax.persistence.EntityManager)
*/
@Override
@SuppressWarnings("unchecked")
protected EnversRevisionRepositoryImpl<?, ?, ?> getTargetRepository(RepositoryInformation information,
EntityManager entityManager) {
protected RepositoryFragments getRepositoryFragments(RepositoryMetadata metadata) {
JpaEntityInformation<T, ?> entityInformation = (JpaEntityInformation<T, ?>) getEntityInformation(
information.getDomainType());
Object fragmentImplementation = getTargetRepositoryViaReflection( //
EnversRevisionRepositoryImpl.class, //
getEntityInformation(metadata.getDomainType()), //
revisionEntityInformation, //
entityManager //
);
return new EnversRevisionRepositoryImpl<T, ID, N>(entityInformation, revisionEntityInformation, entityManager);
}
/*
* (non-Javadoc)
* @see org.springframework.data.jpa.repository.support.JpaRepositoryFactory#getRepositoryBaseClass(org.springframework.data.repository.core.RepositoryMetadata)
*/
@Override
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
if (isQueryDslExecutor(metadata.getRepositoryInterface())) {
return QueryDslWithEnversRevisionRepository.class;
} else {
return EnversRevisionRepositoryImpl.class;
}
}
/**
* Returns whether the given repository interface requires a QueryDsl specific implementation to be chosen.
*
* @param repositoryInterface
* @return
*/
private boolean isQueryDslExecutor(Class<?> repositoryInterface) {
return QuerydslUtils.QUERY_DSL_PRESENT && QuerydslPredicateExecutor.class.isAssignableFrom(repositoryInterface);
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.core.support.RepositoryFactorySupport#getRepository(java.lang.Class, org.springframework.data.repository.core.support.RepositoryComposition.RepositoryFragments)
*/
@Override
@SuppressWarnings("hiding")
public <T> T getRepository(Class<T> repositoryInterface, RepositoryFragments fragments) {
if (RevisionRepository.class.isAssignableFrom(repositoryInterface)) {
Class<?>[] typeArguments = GenericTypeResolver.resolveTypeArguments(repositoryInterface,
RevisionRepository.class);
Class<?> revisionNumberType = typeArguments[2];
if (!revisionEntityInformation.getRevisionNumberType().equals(revisionNumberType)) {
throw new IllegalStateException(String.format(
"Configured a revision entity type of %s with a revision type of %s "
+ "but the repository interface is typed to a revision type of %s!",
repositoryInterface, revisionEntityInformation.getRevisionNumberType(), revisionNumberType));
}
}
return super.getRepository(repositoryInterface, fragments);
return RepositoryFragments //
.just(fragmentImplementation) //
.append(super.getRepositoryFragments(metadata));
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -38,11 +38,11 @@ import org.springframework.data.history.RevisionMetadata;
import org.springframework.data.history.RevisionSort;
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.StreamUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
/**
@@ -53,7 +53,8 @@ import org.springframework.util.Assert;
* @author Michael Igler
* @author Jens Schauder
*/
public class EnversRevisionRepositoryImpl<T, ID, N extends Number & Comparable<N>> extends SimpleJpaRepository<T, ID>
@Transactional(readOnly = true)
public class EnversRevisionRepositoryImpl<T, ID, N extends Number & Comparable<N>>
implements RevisionRepository<T, ID, N> {
private final EntityInformation<T, ?> entityInformation;
@@ -71,8 +72,6 @@ public class EnversRevisionRepositoryImpl<T, ID, N extends Number & Comparable<N
public EnversRevisionRepositoryImpl(JpaEntityInformation<T, ?> entityInformation,
RevisionEntityInformation revisionEntityInformation, EntityManager entityManager) {
super(entityInformation, entityManager);
Assert.notNull(revisionEntityInformation, "RevisionEntityInformation must not be null!");
this.entityInformation = entityInformation;

View File

@@ -1,77 +0,0 @@
/*
* Copyright 2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.envers.repository.support;
import java.io.Serializable;
import java.util.Optional;
import javax.persistence.EntityManager;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.history.Revision;
import org.springframework.data.history.Revisions;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.QuerydslJpaRepository;
import org.springframework.data.repository.history.support.RevisionEntityInformation;
/**
* Repository implementation for both {@link org.springframework.data.repository.history.RevisionRepository} and
* {@link org.springframework.data.querydsl.QuerydslPredicateExecutor} interfaces.
*
* @author Dmytro Iaroslavskyi
*/
public class QueryDslWithEnversRevisionRepository<T, ID extends Serializable, N extends Number & Comparable<N>>
extends QuerydslJpaRepository<T, ID> implements EnversRevisionRepository<T, ID, N> {
private final EnversRevisionRepositoryImpl<T, ID, N> delegateRepository;
/**
* Creates a new {@link QueryDslWithEnversRevisionRepository} using the given {@link JpaEntityInformation},
* {@link RevisionEntityInformation} and {@link EntityManager}.
*
* @param entityInformation must not be {@literal null}.
* @param revisionEntityInformation must not be {@literal null}.
* @param entityManager must not be {@literal null}.
*/
public QueryDslWithEnversRevisionRepository(JpaEntityInformation<T, ID> entityInformation,
RevisionEntityInformation revisionEntityInformation, EntityManager entityManager) {
super(entityInformation, entityManager);
this.delegateRepository = new EnversRevisionRepositoryImpl<T, ID, N>(entityInformation, revisionEntityInformation,
entityManager);
}
@Override
public Optional<Revision<N, T>> findLastChangeRevision(ID id) {
return delegateRepository.findLastChangeRevision(id);
}
@Override
public Optional<Revision<N, T>> findRevision(ID id, N revisionNumber) {
return delegateRepository.findRevision(id, revisionNumber);
}
@Override
public Revisions<N, T> findRevisions(ID id) {
return delegateRepository.findRevisions(id);
}
@Override
public Page<Revision<N, T>> findRevisions(ID id, Pageable pageable) {
return delegateRepository.findRevisions(id, pageable);
}
}