0

我在我的项目中通过简单的配置使用 Hibernate Envers。

pom.xml

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.1</version>
    <relativePath/>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-envers</artifactId>
    </dependency>
</dependencies>

环境配置

@Configuration
@EnableJpaAuditing
public class EnversConfiguration {

  @Bean
  AuditorAware<Auditor> auditorProvider() {
    return new AuditorAwareImplementation();
  }
}

AuditorAwareImplementation只是 AuditorAware 的简单实现

我还AuditReader用来读取某些实体的更改。我的方法总是抛出java.lang.IllegalStateException: Session/EntityManager is closed.

java.lang.IllegalStateException: Session/EntityManager is closed
    at org.hibernate.internal.AbstractSharedSessionContract.checkOpen(AbstractSharedSessionContract.java:375) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
    at org.hibernate.engine.spi.SharedSessionContractImplementor.checkOpen(SharedSessionContractImplementor.java:148) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
    at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:709) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
    at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:113) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
    at org.hibernate.envers.internal.tools.query.QueryBuilder.toQuery(QueryBuilder.java:323) ~[hibernate-envers-5.4.25.Final.jar:5.4.25.Final]
    at org.hibernate.envers.query.internal.impl.AbstractAuditQuery.buildQuery(AbstractAuditQuery.java:98) ~[hibernate-envers-5.4.25.Final.jar:5.4.25.Final]
    at org.hibernate.envers.query.internal.impl.AbstractAuditQuery.buildAndExecuteQuery(AbstractAuditQuery.java:104) ~[hibernate-envers-5.4.25.Final.jar:5.4.25.Final]
    at org.hibernate.envers.query.internal.impl.RevisionsOfEntityQuery.getQueryResults(RevisionsOfEntityQuery.java:173) ~[hibernate-envers-5.4.25.Final.jar:5.4.25.Final]
    at org.hibernate.envers.query.internal.impl.RevisionsOfEntityQuery.list(RevisionsOfEntityQuery.java:136) ~[hibernate-envers-5.4.25.Final.jar:5.4.25.Final]
    at org.hibernate.envers.query.internal.impl.AbstractAuditQuery.getResultList(AbstractAuditQuery.java:112) ~[hibernate-envers-5.4.25.Final.jar:5.4.25.Final]

如果我运行带有@Transactional注释的方法,一切都会很好。在另一个@Transactional具有非常相似的配置和旧 Spring Boot 版本的项目(没有)中,没有@Transactional.

其实我不知道发生了什么。

有效的代码:

@Service
@AllArgsConstructor
public class CarHistoryService {
  private final EntityManager entityManager;

  @Transactional
  @SuppressWarnings("unchecked")
  public List<Object[]> getHistory() {
    final AuditReader reader = AuditReaderFactory.get(entityManager);
    return (List<Object[]>) reader.createQuery()
      .forRevisionsOfEntityWithChanges(Car.class, true)
      .add(AuditEntity.property("id").eq("5ee7c9dd-a986-4030-8294-3f5dfa2fd6ab"))
      .getResultList();
  }
}

不起作用的代码:

@Service
@AllArgsConstructor
public class CarHistoryService {
  private final EntityManager entityManager;

  // @Transactional
  @SuppressWarnings("unchecked")
  public List<Object[]> getHistory() {
    final AuditReader reader = AuditReaderFactory.get(entityManager);
    return (List<Object[]>) reader.createQuery()
      .forRevisionsOfEntityWithChanges(Car.class, true)
      .add(AuditEntity.property("id").eq("5ee7c9dd-a986-4030-8294-3f5dfa2fd6ab"))
      .getResultList();
  }
}

使用以下内容查找实体的代码EntityManager

@Service
@AllArgsConstructor
public class CarHistoryService {
  private final EntityManager entityManager;

  @SuppressWarnings("unchecked")
  public List<Object[]> getHistory() {
    final Object object = entityManager.find(Car.class, UUID.fromString("5ee7c9dd-a986-4030-8294- 3f5dfa2fd6ab"));
    final AuditReader reader = AuditReaderFactory.get(entityManager);
    return (List<Object[]>) reader.createQuery()
      .forRevisionsOfEntityWithChanges(Car.class, true)
      .add(AuditEntity.property("id").eq("5ee7c9dd-a986-4030-8294-3f5dfa2fd6ab"))
      .getResultList();
  }
}

如果我在上面执行和调试代码,它会正确检索实体,entityManager并且我看到它object具有一些属性。但是继续使用该方法-它会为下一行引发相同的异常,我想在其中使用 Envers 检索对象历史记录。

谁能告诉我一些解决方案并解释为什么它会这样工作?我认为读取数据不应该需要事务,但我可能错了。

4

0 回答 0