我有一个使用 hibernate/JPA 进行持久化的应用程序。它使用Spring。
一些持久化 Bean 依赖于我从 REST 服务检索的外部对象。
此 REST 服务的客户端 stub 是一个注册的 Spring 服务。
我想在 hibernate 加载过程中包装这些外部对象的加载。这样,我可以确定我的对象在加载后始终有效,即使我通过复杂的 HQL 查询获取这些对象也是如此。
问题是,无论我使用什么方法,我都很难在持久化 bean 中获取 Spring 应用程序上下文(以及 REST 客户端)。
我尝试过以下方法:
- 使用 UserType 通过 ID 从 REST 获取我的对象:
CustomUserType 由 Hibernate 实例化,因此不会发生 Spring 注入(inject)。 - 使用@AfterLoad JPA注释:
这个更糟糕,没有 EntityManager、Session 或 Spring 上下文可用 - 用户LifeCycle接口(interface),onLoad(Session s, Serialized id)方法:
我可以访问这里的 session 。但我不知道如何创建一个能够识别 ApplicationContext 的自定义 session 。
目前,我正在使用一个肮脏的解决方法:ApplicationHolder Spring 服务,它提供静态 getter,以便 Spring 世界之外的对象能够访问它。
关于如何使 hibernate 或持久化 beans 上下文感知,您有任何最佳实践吗?
谢谢
编辑
在我的 DAO 中执行此操作是我的第一个方法,但实际上我有许多需要获取的子对象,如下所示:
LocalObject
* - localSubObject1
- refToExternalObject ----------> externalObject1
* - localSubObject2
- refToExternalObject ----------> externalObject2
- refToExternalObject ----------> externalObject3
我希望我的 LocalObject 具有一致、干净的负载。
这样,我就可以在 DAO 中编写复杂的 HQL,而不必再担心外部对象获取了。
最佳答案
如果你不想在 Dao 中这样做,那么也许这可行:
@Component
public class MyPostLoadEventListener implements PostLoadEventListener {
@Resource
private SessionFactoryImpl sessionFactoryImpl;
@Resource
private RestClient restClient;
@PostConstruct
public void installAsEventListener() {
sessionFactoryImpl.getServiceRegistry()
.getService(EventListenerRegistry.class)
.getEventListenerGroup(EventType.POST_LOAD)
.appendListener(this);
}
@Override
public void onPostLoad(PostLoadEvent event) {
if (event.getEntity() instanceof LocalObject) {
// fill with data from RestClient
}
}
}
这有点困惑,但不幸的是,注册 Hibernate EventListener 的替代方法(在配置中或通过 Integrators )不能与 Spring beans 一起使用,因为它们是直接实例化的(如本文中提到的 abandoned JIRA entry ) .
希望有帮助。
关于java - 如何使受管实体具有上下文感知能力?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14160385/