Все @version поля в таблице AUD является недействительным при использовании Hibernate-Envers, но в сущности - таблица заполнена ока?

Вопрос задан: 1 год назад Последняя активность: 1 год назад
up 10 down

Существует весной приложение + JPA + Envers (спящий режим) Envers необходимо сохранить историю субъектов в специальной таблице.

После того, как я сэкономил несколько раз мое лицо, я ожидал увидеть заполненную версию поля в таблице USER и наполненную версию поля в USER_AUT. Но фактический результат правильное значение в таблице USER, но добавил REV_TYPE, REV колонны (в поле только противоионы для всех строк) и нуль в версии colums.

Я использую 4.0.1.Final спящего режима

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-envers</artifactId>
    <version>4.0.1.Final</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>4.0.1.Final</version>
</dependency>

Но, когда я смотрю в таблицу, все значения в поле Version равны нулю

Моя организация является

import lombok.*;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.envers.Audited;

import javax.persistence.*;

@Entity
@Audited
@Table(name = "User", uniqueConstraints = {
        @UniqueConstraint(columnNames = { "prKey"})})
@NoArgsConstructor(access = AccessLevel.PUBLIC)
@AllArgsConstructor
@Getter
@Setter
public class User {
    @Id
    @GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "uuid2")
    @Column(name = "PR_KEY", unique = true)
    private String prKey;

    @Column(name = "name", length = 100, unique = false)
    private String name;

    @Version
    private int version;

    public User(String name){
        this.name = name;
    }
}

И когда я получаю объекты с помощью аудита:

 public List<User> getHistory(String id) {
        AuditReader auditReader = AuditReaderFactory.get(entityManagerFactory.createEntityManager());

        List<Number> auditVersions = auditReader.getRevisions(User.class, id);
        List<User> users = auditVersions.stream().map(item -> auditReader.find(User.class, id, item.intValue())).collect(Collectors.toList());

        return extractRiskMetrics(riskMetricRecords);
    }

Итак, моя настойчивость - это конфигурационный

@Configuration
@EnableTransactionManagement
@EnableJpaAuditing
@EnableJpaRepositories(basePackages = {"persistence"})
@ComponentScan(basePackages = {"persistence", "model"})
public class PersistenceConfig {
    private static final String PACKAGE_WITH_JPA_ENTITIES = "persistence";
    private final Logger log = Logger.getLogger(getClass());

    @Bean
    @Resource(type = DataSource.class, lookup = "jdbc/MyDatasource", name = "jdbc/MyDatasource")
    public DataSource dataSource() {
        final JndiDataSourceLookup dsLookup = new JndiDataSourceLookup();
        dsLookup.setResourceRef(true);
        DataSource dataSource = dsLookup.getDataSource("java:comp/env/jdbc/MyDatasource");
        return dataSource;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean();
        entityManager.setDataSource(dataSource());
        entityManager.setPackagesToScan(PACKAGE_WITH_JPA_ENTITIES);
        entityManager.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
        entityManager.setJpaProperties(getHibernateProperties());
        log.info("Entity Manager configured.");
        return entityManager;
    }

    @Bean
    public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory);
        return transactionManager;
    }

    //Set properties hibernate
    private Properties getHibernateProperties() {
        Properties properties = new Properties();
        properties.put("hibernate.dialect", "org.hibernate.dialect.OracleDialect");
        properties.put("hibernate.show_sql", "true");
        properties.put("hibernate.hbm2ddl.auto", "none");
        properties.put("org.hibernate.envers.do_not_audit_optimistic_locking_field", false);

        properties.put("verifyServerCertificate", false);
        properties.put("useSSL", false);
        properties.put("requireSSL", false);
        properties.put("useLegacyDatetimeCode", false);
        properties.put("useUnicode", "yes");
        properties.put("characterEncoding", "UTF-8");
        properties.put("serverTimezone", "UTC");
        properties.put("useJDBCCompliantTimezoneShift", true);
        return properties;
    }
}

Обновления:

org.hibernate.envers.do_not_audit_optimistic_locking_field установлен неверно, но версия поля еще нуль.

Может быть это связано с конфликтом Spring Data JPA и Hibernate - Envers?

В самом деле, выполняется запрос (изменение и F.C.)

[1/22/19 14:04:51:996 MSK] 00000096 SystemOut     O Hibernate: update UserRecord set User=?, version=? where PR_KEY=? and version=?
[1/22/19 14:04:51:998 MSK] 00000096 SystemOut     O Hibernate: select hibernate_sequence.nextval from dual
[1/22/19 14:04:52:000 MSK] 00000096 SystemOut     O Hibernate: insert into REVINFO (REVTSTMP, REV) values (?, ?)
[1/22/19 14:04:52:002 MSK] 00000096 SystemOut     O Hibernate: insert into UserRecord_AUD (REVTYPE, busId, User, UserType, someInfo, PR_KEY, REV) values (?, ?, ?, ?, ?, ?, ?)

Так что, в AUD таблице нет где версия =?

2 ответа

Возможно, для Вашего проекта будут необходимы бесплатные векторные карты. На нашем сайте представлены карты для всех стран.

Реклама

up 1 down

Посмотрите настройки конфигурации org.hibernate.envers.do_not_audit_optimistic_locking_field.

Этот параметр управления конфигурацией или нет Hibernate Envers будет включать @Version аннотированный поле в схеме аудита или нет. По умолчанию параметр имеет значение true это означает, что оптимистическое поле блокировки не будет проверяться. Установив это false, вы ревизовать значение столбца.

Я хочу предупредить вас об установке в этом поле false.

Если ваше приложение выполняет явное оптимистически-фиксирующую функции приращения, то это приведет к дополнительные строки добавляются в таблицу истории аудита, даже если ни один из других столбцов базы данных не меняются, как часть вашего бизнес-процесса. Это происходит потому, что, как только вы включите @Version поля, которые необходимо отслеживать, Hibernate Envers просто обрабатывает их, как и любой другой основной атрибут на сущности. Поэтому, принудительное приращение оптимистичной блокировки вызовет изменение аудита.

up 0 down

Как вы упомянули - REVINFO централизованной таблицы для всех проверяемых субъектов.

Основная идея представлена ​​ниже переназначить номера ревизий в целое последовательности - так RevNumber (2,5,31,125) будет переназначен к customVersion (1,2,3,4)

Скажем, у вас есть EntityA и вы хотите получать все ревизии с для нее (и переводящих данные ревизий для пользовательского класса RevisionEntityDto).

С помощью AuditReader от Envers вы можете сделать что-то вроде:

AuditReader auditReader = AuditReaderFactory.get(entityManager);
//getRevisions() returns revisions sorted in ascending order (older revisions come first)
List<Number> entityARevisions = auditReader.getRevisions(EntityA.class, primaryKeyOfEntityA);

//entityARevisions is already sorted;
for (int customVersion = 0; customVersion < entityARevisions.size(); customVersion++) {
   createRevisionEntityDto(primaryKeyOfEntityA, auditReader, revision, customVersion);
}

private RevisionEntityDto createRevisionEntityDto(Long primaryKeyOfEntityA, AuditReader, Number revision) {
  EntityA revisionOfEntityA = auditReader.find(EntityA.class, primaryKey, revision);
  Date revDate = auditReader.getRevisionDate(revision);
  // at this point you have a single revision of EntityA
  return toRevisionEntityDto(revision, revisionOfEntityA, revDate);
}

private RevisionEntityDto toRevisionEntityDto(Number revision, EntityA revisionOfEntityA, Date revisionDate, int customVersion) {
  //here you do the mapping logic;
  RevisionEntityDto revEntityDto = new RevisionEntityDto();
  revEntityDto.setFieldA(revisionOfEntityA.getFieldA);
  revEntityDto.setDate(revisionDate); // you can use the date to sort if you want at a later stage;
  revEntityDto.setCustomVersion(customVersion);
  return revEntityDto;
}

Ошибка 505

Что-то пошло не так

Попробуйте воспользоваться поиском