Динамическое создание Spring EnversRevisionRepository из класса Java

Как создать EnversRevisionRepository динамически заданный объект класса Java?

Благодаря этому ответу https://stackoverflow.com/a/22342025/3771679 можно успешно создать JpaRepository динамически, но Я хотел бы добиться того же для репозитория, который эквивалентен:

public interface MyRevisionedRepository extends RevisionRepository<X,Y,Z>, JpaRepository<X,Y> {

}

person GrowlingBadger    schedule 28.01.2021    source источник
comment
Напишите пользовательский процессор аннотаций.   -  person silentsudo    schedule 28.01.2021
comment
Вероятно, потребуется больше деталей, чем это. Смысл этого вопроса в том, что вообще не нужно создавать определение интерфейса, поэтому я не уверен, как поможет пользовательский процессор аннотаций.   -  person GrowlingBadger    schedule 28.01.2021


Ответы (1)


Spring Data предоставляет EnversRevisionRepositoryImpl по умолчанию RevisionRepository реализации.

Как вы можете видеть в конструкторе репозитория:

    /**
     * Creates a new {@link EnversRevisionRepositoryImpl} 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 EnversRevisionRepositoryImpl(JpaEntityInformation<T, ?> entityInformation,
            RevisionEntityInformation revisionEntityInformation, EntityManager entityManager) {

        Assert.notNull(revisionEntityInformation, "RevisionEntityInformation must not be null!");

        this.entityInformation = entityInformation;
        this.entityManager = entityManager;
    }

вам нужны три вещи, чтобы создать новый экземпляр этого репозитория:

  • EntityManager, который можно легко получить с помощью @PersistenceContext или, возможно (я никогда не проверял) с помощью @Autowiring.

  • А JpaEntityInformation. Следуя примеру SimpleJpaRepository:

final JpaEntityInformation<T, ?> entityInformation =
  JpaEntityInformationSupport.getEntityInformation(domainClass, em)
  • А RevisionEntityInformation. Любопытно, поскольку утверждается, что объект не является нулевым, но на самом деле он кажется неиспользуемым в остальной части кода реализации. Здесь мы можем последовать примеру EnversRevisionRepositoryFactoryBean:
final RevisionEntityInformation revisionEntityInformation =
  Optional.ofNullable(revisionEntityClass) //
    .filter(it -> !it.equals(DefaultRevisionEntity.class))//
    .<RevisionEntityInformation> map(ReflectionRevisionEntityInformation::new) //
    .orElseGet(DefaultRevisionEntityInformation::new); 

DefaultRevisionEntityInformation находится в пределах пакета, но вы можете легко воспроизвести его:

import org.hibernate.envers.DefaultRevisionEntity;
import org.springframework.data.repository.history.support.RevisionEntityInformation;

/**
 * {@link RevisionEntityInformation} for {@link DefaultRevisionEntity}.
 */
public class DefaultRevisionEntityInformation implements RevisionEntityInformation {

    /*
     * (non-Javadoc)
     * @see org.springframework.data.repository.history.support.RevisionEntityInformation#getRevisionNumberType()
     */
    public Class<?> getRevisionNumberType() {
        return Integer.class;
    }

    /*
     * (non-Javadoc)
     * @see org.springframework.data.repository.history.support.RevisionEntityInformation#isDefaultRevisionEntity()
     */
    public boolean isDefaultRevisionEntity() {
        return true;
    }

    /*
     * (non-Javadoc)
     * @see org.springframework.data.repository.history.support.RevisionEntityInformation#getRevisionEntityClass()
     */
    public Class<?> getRevisionEntityClass() {
        return DefaultRevisionEntity.class;
    }
}

В итоге:

// Obtain a reference to the underlying EntityManager
final EntityManager entityManager = ...;
// Provide JpaEntityInformation
final JpaEntityInformation<User, ?> entityInformation =
  JpaEntityInformationSupport.getEntityInformation(User.class, entityManager);
// Provide RevisionEntityInformation. The solution is based on 
// DefaultRevisionEntity but you can provide your custom revision entity
// if appropriate
final RevisionEntityInformation revisionEntityInformation =
  new DefaultRevisionEntityInformation();
// Build your custom revision repository, for example:
final RevisionRepository userRevisionRepository =
  new EnversRevisionRepositoryImpl<User, Integer, DefaultRevisionEntity>(
    entityInformation, revisionEntityInformation, entityManager
  )
;
person jccampanero    schedule 16.03.2021
comment
Великолепно, спасибо, еще не пробовал, но скоро понадобится, так что скрестим пальцы и большое спасибо за ваше время. - person GrowlingBadger; 20.03.2021
comment
Пожалуйста, @GrowlingBadger. Я надеюсь, что это помогает. Пожалуйста, если у вас возникнут какие-либо проблемы с кодом, дайте мне знать, я буду рад адаптировать его по мере необходимости, чтобы предоставить вам правильное решение. - person jccampanero; 20.03.2021