我在我的项目中通过简单的配置使用 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 检索对象历史记录。
谁能告诉我一些解决方案并解释为什么它会这样工作?我认为读取数据不应该需要事务,但我可能错了。