Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使托管实体具有上下文意识?_Java_Spring_Hibernate - Fatal编程技术网

Java 如何使托管实体具有上下文意识?

Java 如何使托管实体具有上下文意识?,java,spring,hibernate,Java,Spring,Hibernate,我有一个应用程序使用hibernate/JPA进行持久化。它使用弹簧 一些持久化bean依赖于我从REST服务检索的外部对象。 此REST服务的客户端存根是注册的Spring服务 我想在hibernate加载过程中包装这些外部对象的加载。通过这种方式,我确信我的对象在加载后总是有效的,即使我通过复杂的HQL查询获得这些对象 问题是,无论我使用什么方法,我都很难在持久化bean中获得Spring应用程序上下文(以及REST客户端) 我尝试了以下方法: 使用UserType通过其ID从REST获取

我有一个应用程序使用hibernate/JPA进行持久化。它使用弹簧
一些持久化bean依赖于我从REST服务检索的外部对象。

此REST服务的客户端存根是注册的Spring服务

我想在hibernate加载过程中包装这些外部对象的加载。通过这种方式,我确信我的对象在加载后总是有效的,即使我通过复杂的HQL查询获得这些对象

问题是,无论我使用什么方法,我都很难在持久化bean中获得Spring应用程序上下文(以及REST客户端)

我尝试了以下方法:

  • 使用UserType通过其ID从REST获取我的对象:
    CustomUserType由Hibernate实例化,因此不会发生Spring注入
  • 使用@AfterLoadJPA注释:
    更糟糕的是,没有EntityManager、会话或Spring上下文可用
  • 用户生命周期接口,onLoad(会话s,可序列化id)方法:
    我可以在这里参加会议。但我不知道如何创建一个自定义会话,该会话将ApplicationContext感知
目前,我正在使用一个肮脏的解决方法:一个ApplicationHolderSpring服务,它提供一个静态getter,让Spring世界之外的对象能够访问它

关于如何使hibernate或持久化bean上下文感知,您有什么最佳实践吗

THks

编辑

在DAO中执行此操作是我的第一种方法,但实际上我有许多子对象需要获取,如下所示:

LocalObject
* - localSubObject1
    - refToExternalObject ----------> externalObject1
* - localSubObject2 
    - refToExternalObject ----------> externalObject2
    - refToExternalObject ----------> externalObject3
我希望本地对象具有一致、干净的加载


这样,我就可以在我的DAO中编写复杂的HQL,而不必再为获取外部对象而烦恼。

一个解决方案的快速草图来解释我的评论:

@Component
public class HibernateDao {

    @Resource
    private SessionFactory sessionFactory;
    @Resource
    private RestClient restClient;


    public LocalObject loadLocalObject(Serializable id) {
        LocalObject localObject = sessionFactory.getCurrentSession().load(id);
        ExternalObject externalObject = restClient.getExternalObject(id);

        localObject.setVal(externalObject.getVal())
        // ... more of this ...

        return localObject;
    }
}

如果您不想在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的替代方法(在配置中或通过)不能用于Springbean,因为它们是直接实例化的(如本文所述)


希望这会有所帮助。

将Hibernate Dao作为一个bean(可能是注入SessionFactory等),并在返回它之前在Dao方法中完成实体初始化,这样会更干净。我仍然认为Dao是一种方式。您可以向需要获取的外部实体添加自定义注释,DAO将查找注释以查看要扫描的内容。另外,它将逻辑排除在域对象之外!