spring-projects / spring-projects/spring-data-jpa

Envers: Allow to extend the default EnversRevisionRepositoryImpl

Open
#3,252 2 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

status: pending-design-work type: enhancement
Dominant language
Java
Stars
3.3k
Forks
1.6k
PR merge metrics
No merged PRs in 30d

Description

Recently in my job I had to expand the functionality of the RevisionRepository and I thought that could be great if this posibility is added to the Spring Data project.

To achieve this, I added the following method to the EnversRevisionRepositoryFactoryBean, treating it as if we were modifying the revision entity:

public void setRepositoryImplClass(Class<? extends EnversRevisionRepositoryImpl<T, S, N>> repositoryImplClass) {
    this.repositoryImplClass = repositoryImplClass;
}

This ensures the default behavior when the new parameter is null:

private static class RevisionRepositoryFactory<T, ID, N extends Number & Comparable<N>> extends JpaRepositoryFactory {

    private final Class<?> repositoryClass;

    public RevisionRepositoryFactory(EntityManager entityManager, Class<?> revisionEntityClass, Class<?> repositoryImplClass) {

        // original implementation

        this.repositoryClass = repositoryImplClass != null ? repositoryImplClass : EnversRevisionRepositoryImpl.class;
    }

    @Override
    protected RepositoryFragments getRepositoryFragments(RepositoryMetadata metadata) {

        Object fragmentImplementation = getTargetRepositoryViaReflection(
                repositoryClass,
                getEntityInformation(metadata.getDomainType()),
                revisionEntityInformation,
                entityManager
        );

        // original implementation
    }
}

Additionally, to maintain consistency with the return types of the original repository implementation, I changed the visibility of these methods and classes to protected:

public class EnversRevisionRepositoryImpl<T, ID, N extends Number & Comparable<N>>
        implements RevisionRepository<T, ID, N> {

    protected AuditOrder mapRevisionSort(RevisionSort revisionSort)

    protected List<AuditOrder> mapPropertySort(Sort sort)

    protected AuditQuery createBaseQuery(ID id)

    protected Revision<N, T> createRevision(QueryResult<T> queryResult)

    protected static class QueryResult<T> {
        protected QueryResult(Object[] data)
        protected RevisionMetadata<?> createRevisionMetadata()
        protected static RevisionMetadata.RevisionType convertRevisionType(RevisionType datum)
    }

}

Feel free to provide comments or advice in case I've attempted to reinvent the wheel or if there's an easier way to achieve this exact functionality

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading EnversRevisionRepositoryFactoryBean and EnversRevisionRepositoryImpl, including the factory's repository-fragment creation and the listed helper methods and nested QueryResult class. The change is done when a custom EnversRevisionRepositoryImpl can be configured while the default implementation remains unchanged and the proposed extension points retain compatible return types.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
backend, database
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.