jpa 在不检查@Id的情况下确定实体是否为新实体

sshcrbum  于 2023-04-21  发布在  其他
关注(0)|答案(4)|浏览(145)

是否有一种方法来确定给定的例如实体类:

@Entity
class A {

    String name;

}

boolean method(Object anyEntity) {
     // How can I check here, if this entity is completely new    
}

所谓new,我的意思是有人调用了new A(),甚至可能设置了名称,但从未被保存或持久化。
通常可以检查id,但我想要一个不需要id或getId()方法的解决方案。
基本上,这个实体是否持久化在数据库中,即使是在分离模式下。
@VersiongetVersion也不是令人满意的解决方案。
也许是分离||isAttached可能会起作用,但我不确定如何在Hibernate API上进行调用。
编辑:
还澄清,我不控制实体,所以我不能添加任何字段给他们。解决方案应尽量利用底层机制来确定这一点。

a0x5cqrl

a0x5cqrl1#

如果某个API方法不可用,那么我们可以使用Listeners:来实现。这将在JPA/Hibernate上工作。
如下所示:

@Transient 
private boolean isNew;

@PostPersist
@PostLoad
public void setWhetherNew() {
    isNew = true;
}
yyyllmsg

yyyllmsg2#

您可以使用transient字段并使用Entity-Listeners来设置此字段。

@Transient
private boolean persisted;

@PostLoad
@PostPersist
public void setPersisted() {
   persisted=true;
}

然后,您可以使用persisted来判断该实体是否已被持久化。

--编辑--

@PostLoad是必需的,这样从数据库加载的已持久化的实体也会将persisted设置为true。否则,即使可以在数据库中找到它们,它们也会显示为“new”。

cbeh67ev

cbeh67ev3#

可以检查实体是否由PersistenceContext管理

EntityManager.contains(entity)
agyaoht7

agyaoht74#

经过对Hibernate源代码的一些工作和分析,我相信这就是答案:

boolean isNew(T entity) {
        return ((SessionImplementor) session()).getPersistenceContext().getEntry(entity) == null;
}

另一方面,在不依赖实现的情况下获取id可以这样做:

boolean hasId(Object entity) {
            return getId(entity) != null;
    }

    Serializable getId(Object entity) {
            ClassMetadata metadata = metadata(entity);
            if ( metadata.hasIdentifierProperty() ) {
                    return metadata.getIdentifier(entity);
            }
            return null;
    }

    ClassMetadata metadata(Object entity) {
            return getRepository().session().getSessionFactory().getClassMetadata(entity.getClass());
    }

相关问题