访问Sping Boot Hibernate会话,以取消代理分离对象

e0bqpujr  于 2023-10-23  发布在  其他
关注(0)|答案(1)|浏览(174)

我需要在Sping Boot 3,Hibernate 6环境中取消代理分离的Hibernate对象。方法:

@Autowired
 private EntityManager entityManager;

 @Transactional 
 public <T> T loadUnproxied(T object) {
    if (!Hibernate.isInitialized(object)) {
      Session session = entityManager.unwrap(Session.class);

      // Reattach detached entity to a session.
      // Here it fails:
      session.merge(object);

      Hibernate.initialize(object);
    }
    return object;
 }

这总是导致这个例外:

java.lang.IllegalArgumentException: Unable to locate persister:
org.hibernate.collection.spi.PersistentBag

对此建议的解决方案基本上是修复实体扫描,但实体检测很好,Spring管理得很好,持久性在其他方面也很好。看起来我的代码为Hibernate打开了第二条路,绕过了Spring持久化。但是我需要访问Spring会话,它已经完成了扫描。@Transactional似乎没有帮助。

**我不会做的是在调用loadUnproxied(...)之前将传入的object加载为EAGER fetch *。**整个概念是传递延迟加载的对象,并且只按需加载所需的数据。

(我真的非常感谢任何帮助,但我发现其他类似的问题,人们提到他们仍然想使用LAZY加载,被如何禁用LAZY加载的答案淹没了。

rjzwgtxy

rjzwgtxy1#

我解决了它,有两个问题和解决方案:

  1. session.merge(object)。必须是session.update(object)update实际上是我的第一选择,但它已被弃用,Hibernate建议使用merge。但是merge不起作用。它不会将object重新连接到会话。
    1.在调试Hibernate时,java.lang.IllegalArgumentException: Unable to locate persister: org.hibernate.collection.spi.PersistentBag异常变得可以理解。当试图取消代理存储在org.hibernate.collection.spi.PersistentBag中的列表时,就会发生这种情况。Hibernate没有关于如何在分离后重新初始化该列表的数据。只有实体可以重新初始化/取消代理。我发现的唯一解决取消代理列表的方法是完全重新加载容器实体,并在该事务会话中初始化列表。
    解决方案:
@Autowired
private EntityManagerFactory entityManagerFactory;

public <T> T loadUnproxied(T object) {
  if (!Hibernate.isInitialized(object)) {
    if (object instanceof PersistentBag) {
      throw new IllegalArgumentException(
        "Can't unproxy list out of session");
    }

    final SessionFactory sessionFactory = entityManagerFactory.unwrap(
      SessionFactory.class
    );

    sessionFactory.inTransaction((Session session) -> {
      session.update(object);
      Hibernate.initialize(object);
    });
  }
  return object;
}

相关问题