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

时间:2016-01-19 15:57:49

标签: jpa eclipselink entitymanager

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

4 个答案:

答案 0 :(得分:3)

EclipseLink的JPA接口几乎包含其本机代码,以便EntityManager使用下面的UnitOfWork会话(并且EMF包装ServerSession)。如果您想查看它正在管理的实体,您需要访问UnitOfWork。

如果使用JPA 2.0,则可以使用EntityManager解包方法:

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

否则,使用一些演员

printRegisteredObjects()

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

您还可以使用getDeletedObjects().keySet()然后使用hasNewObjectsInParentOriginalToClone()查看已删除的对象,如果使用getNewObjectsCloneToOriginal().keySet()和{{1}}

答案 1 :(得分:1)

你可以在很多方面使用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);
        }
    }
}

答案 2 :(得分:0)

您可以通过检查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)从缓存中获取对象。这不会返回任何集合或任何东西,但它是下一个最好的东西。

不幸的是,如果你想真正访问缓存中的对象,你需要自己管理它。

答案 3 :(得分:0)

我在EntityManager界面中看不到这样的选项。只有contains(Object entity)方法,但您需要传递conrete对象,并在PersistenceContext中检查它们是否存在。另外看PersistenceContext界面我没看到这样的选项。