【问题标题】:How to find all managed attached objects in EntityManager (JPA)如何在 EntityManager (JPA) 中查找所有托管附加对象
【发布时间】:2016-04-25 04:36:37
【问题描述】:

有没有办法获取当前附加在实体管理器中的所有对象?
我想编写一些监控代码来报告附加对象的数量及其类。
意思是查找之前查询加载的所有对象,并将操作查找到实体管理器中。
我正在使用EclipseLink,所以具体的解决方案也很好。

【问题讨论】:

    标签: jpa eclipselink entitymanager


    【解决方案1】:

    EclipseLink 的 JPA 接口几乎包装了它的本机代码,因此 EntityManager 在下面使用 UnitOfWork 会话(而 EMF 包装了一个 ServerSession)。如果您想查看 UnitOfWork 管理的实体,您需要访问 UnitOfWork。

    如果使用 JPA 2.0,可以使用 EntityManager 展开方法:

    UnitOfWork uow = em.unwrap(UnitOfWork.class);
    

    否则,使用一些强制转换

    UnitOfWork uow = ((EntityManagerImpl)em).getUnitOfWork();
    

    从那里,UnitOfWork 拥有所有已注册(也称为托管)实体的列表。您可以使用 UOW 直接使用printRegisteredObjects() 方法记录它所拥有的内容,或者使用getCloneMapping().keySet() 自己获取它。

    您还可以使用hasDeletedObjects()getDeletedObjects().keySet()(如果有)来查看已删除的对象,对于使用hasNewObjectsInParentOriginalToClone()getNewObjectsCloneToOriginal().keySet() 的新对象也是如此

    【讨论】:

      【解决方案2】:

      您可以通过很多我还不知道的方式使用 JPA,并且在 eclipselink 的幕后发生了很多我仍然不完全理解的事情,但看起来有可能看到持久性语境。使用此代码需您自担风险。它只是为了给您一个提示,即可以检查上下文。 (无论代码是对还是错,我都会发布它,因为当我试图决定是否使用 eclipselink 时它会对我有所帮助。关于如何正确执行此操作的文档方式似乎并不多。 )

      public void saveChanges() {
          Date now = new Date();
      
          JpaEntityManager jem = em.unwrap(JpaEntityManager.class);
          UnitOfWorkImpl uow = jem.unwrap(UnitOfWorkImpl.class);
      
          // inserts
      
          for (Object entity : uow.getNewObjectsCloneToOriginal().keySet()) {
              if (entity instanceof IAuditedEntity) {
                  IAuditedEntity auditedEntity = (IAuditedEntity) entity;
                  auditedEntity.setAuditedUserId(this.userId);
                  auditedEntity.setAuditedAt(now);
                  auditedEntity.setCreatedAt(now);
              }
          }
      
          // updates
      
          UnitOfWorkChangeSet uowChangeSet = (UnitOfWorkChangeSet) uow.getUnitOfWorkChangeSet();
          if (uowChangeSet != null) {
              List<IAuditedEntity> toUpdate = new ArrayList<>();
              for(Entry<Object, ObjectChangeSet> entry : uowChangeSet.getCloneToObjectChangeSet().entrySet()) {
                  if (entry.getValue().hasChanges()) {
                      if (entry.getKey() instanceof IAuditedEntity) {
                          toUpdate.add((IAuditedEntity) entry.getKey());
                      }
                  }
              }
              for (IAuditedEntity auditedEntity : toUpdate) {
                  auditedEntity.setAuditedUserId(this.userId);
                  auditedEntity.setAuditedAt(now);
              }
          }
      
          // deletions
      
          Project jpaProject = uow.getProject();
          boolean anyAuditedDeletions = false;
      
          for (Object entity : uow.getDeletedObjects().keySet()) {
              if (entity instanceof IAuditedEntity) {
                  anyAuditedDeletions = true;
                  DeletedEntity deletion = new DeletedEntity();
                  deletion.setTableName(jpaProject.getClassDescriptor(entity.getClass()).getTableName());
                  deletion.setEntityId(((IAuditedEntity) entity).getId());
                  deletion.setAuditedUserId(this.userId);
                  em.persist(deletion);
              }
          }
      }
      

      【讨论】:

        【解决方案3】:

        您可以通过检查MetaModel 上的实体来实现这一点,这些实体可以从任何EntityManager 获得。

        使用示例:

        EntityManager em = // get your EM however...
        for(EntityType<?> entityType : em.getMetaModel().getEntities()) 
        {
            Class<?> managedClass = entityType.getBindableJavaType();
            System.out.println("Managing type: " + managedClass.getCanonicalName());
        }
        

        此示例将打印出由 EntityManager 管理的所有类类型。要获取所有被管理的实际对象,只需在 EntityManager 上查询该类型的所有对象。


        更新:

        从 JPA 2.0 开始,您可以缓存将由 javax.persistence.Cache 管理的结果。但是,使用纯 JPA 无法实际检索存储在缓存中的对象,您可以做的最好的事情是通过 Cache.contains(Class cls, Object pk) 检查某个对象是否在缓存中:

        em.getEntityManagerFactory().getCache().contains(MyData.class, somePK);
        

        但是,EclipseLink 将Cache 扩展为JpaCache。您可以使用它通过JpaCache.getObject(Class cls, Object id) 从缓存中实际获取对象。这不会返回集合或任何东西,但它是次优的。

        不幸的是,如果您想实际访问缓存中的对象,则需要自己管理。

        【讨论】:

        • 感谢您的详细回答,但我要求的是其他内容。我想从之前的精细/查询操作中找到所有已加载到实体管理器中的附加对象。
        • 你说的加载到实体管理器中是什么意思?这不是 EM 管理的所有类型的对象吗?
        • 没有。如果我做了一个从 A 类返回 100 个对象的查询和另一个加载 B 类的 100 个对象的查询,它们都由实体管理器管理。我想在内存中迭代这 200 个对象。
        • 现在我了解您的问题,并相应地更新了我的答案。不幸的是,没有很好的方法可以做到这一点,但为什么不重新运行您的查询呢?由于对象被缓存,它与运行一些cache.getAllObjects() 方法一样快。
        • 我们有很多开发人员,一旦加载了大量对象,实体管理器的操作就会显着变慢。我需要编写代码来监控大型交易并发现潜在问题。
        【解决方案4】:

        我在EntityManager 界面中没有看到这样的选项。只有一个contains(Object entity) 方法,但您需要传递具体对象,并且它们在 PersistenceContext 中被检查是否存在。还在查看PersistenceContext 界面,我没有看到这样的选项。

        【讨论】:

          猜你喜欢
          • 2012-10-20
          • 1970-01-01
          • 2011-02-25
          • 1970-01-01
          • 2012-05-25
          • 1970-01-01
          • 2021-03-13
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多