如何在 EntityManager (JPA) 中查找所有托管附加对象

How to find all managed attached objects in EntityManager (JPA)

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

您可以通过检查 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 管理的所有 class 类型。要管理所有实际的 object,只需在 EntityManager 上查询该类型的所有 object。


更新:

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

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

但是,EclipseLink 使用 JpaCache 扩展了 Cache。您可以使用它通过 JpaCache.getObject(Class cls, Object id) 从缓存中实际获取 object。这不是 return collection 或其他任何东西,但它是下一个最好的东西。

不幸的是,如果你想实际访问缓存中的 objects,你需要自己管理它。

我在 EntityManager 界面中没有看到这样的选项。只有一个 contains(Object entity) method but you need to pass the conrete objects and they are the checked for existentnce in the PersistenceContext. Also looking at the PersistenceContext 界面,我没有看到这样的选项。

EclipseLink 的 JPA 接口几乎包装了它的本机代码,这样 EntityManager 在下面使用 UnitOfWork 会话(而 EMF 包装了 ServerSession)。如果您想查看它管理的实体,您需要访问 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()[ 的新对象也是如此=18=]

您可以通过很多我仍然不知道的方式使用 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);
        }
    }
}