Hibernate Envers:初始化Envers代理

在Hibernate Envers中,无论设置了什么类型,都会延迟加载实体的所有相关集合。 因此,当审计具有其他实体集合的实体(当然都是经过审计)时,该集合首先是一个SetProxy (在调试时可以看到)。

那么,我该如何初始化该代理呢? 使用Hibernate.initialize()没有任何效果(我怀疑是因为Hibernate和Envers使用不同的代理对象)。 我知道我可以通过迭代它的项目来初始化集合,但这对我来说不是一个选项,因为我在一个实体中有多个集合,更不用说维护问题了。

我需要急切地初始化它们,因为我在Hibernate会话已经关闭的时候访问该集合(将域对象转换为dtos)。

我正在使用Hibernate 3.5.6。

显然,这是Hibernate Envers的一个开放性问题。 他们的JIRA已经存在一个问题: https : //hibernate.atlassian.net/browse/HHH-3552 。 随意投票,也许它会加速,当他们看到有些人希望这个被修复;)

在Envers团队修复此问题之前,有一个适用于我的工作:在集合上调用size()初始化代理对象。

到目前为止,我发现初始化Envers代理的最佳解决方法是使用Dozer 。 将Envers返回的审计实体映射到自身会强制初始化。

例如:

  // Assuming you have an initialized EntityManager in entityManager & // id contains your entity id.. List auditList = (List)AuditReaderFactory. get(entityManager). createQuery(). forRevisionsOfEntity(Foo.class, false, true). add(AuditEntity.id().eq(id)). getResultList(); // Use a singleton in production apps instead... DozerBeanMapper mapper = new DozerBeanMapper(); for(Object[] audit : auditList) { audit[0] = mapper.map(audit[0], Foo.class); } // The proxies in the Foo instances in auditList are now initialized 

我对这个解决方案不是很满意,但我更喜欢通过手动触摸集合来初始化代理。 希望有人提出更好的选择或HHH-3552得到修复!

你的设计有问题。

如果你需要在拦截器中初始化它们(我怀疑Envers通过拦截hibernate调用来工作),这意味着你需要事先了解你的域模型。 审核应该是域建模的一个完全独立的问题。

说到这里,您可以使用一些通用的reflection方法来滚动自己的初始化程序来迭代集合,或者您可以使用Open-Session-In-View模式并使其适应Envers(即在拦截器内)。

请记住,访问这些项目可能会触发其他查询,如果您分析日志,这可能会造成混淆。


编辑 :似乎hibernate具有获取配置文件,可以让您在运行时选择获取计划。 请参阅此SO问题和文档 。