java criteria exist_关于Java:如何使用JPA检查记录是否存在

我想知道给定记录是否存在于数据库中。 到目前为止,我已经通过编写JPA查询并通过getSingleResult()方法运行它来实现这一点。 如果具有给定参数的记录不存在,则会抛出NoResultException。 当然,记录不是必须存在的,因此有时是正常的行为,这就是为什么我问自己,是否有必要抛出必须由catch块处理的Exception? 据我所知,异常处理的成本相当高,因此我对这种解决方案并不十分满意,而且,我什至不需要该对象,我只需要知道它在数据库中的存在即可。

有没有更好的方法来检查对象是否存在? 例如。 使用getResultList()并检查其大小?

很好的问题,但是您应该将标题更改为"如何使用JPA检查记录是否存在"或类似内容。

感谢您的发言,完成:)

更新:存储库exist(id)方法。 如果记录存在,则repo.exist(id)返回true,否则返回false

如果只想知道对象是否存在,请将SELECT COUNT发送到数据库。那将返回0或1。

异常处理的代价不是那么大(除非您在正常操作期间进行了数百万次),所以我不会打扰。

但是代码并没有真正反映出您的意图。由于getSingleResult()在内部调用getResultList(),因此更加清晰:

public boolean objExists(...) {

return getResultList(...).size() == 1;

}

如果您按对象ID查询并启用了缓存,那么如果对象已被加载,它将成为在缓存中的简单查找。

哦,您对SELECT COUNT解决方案绝对正确,由于某种原因,我忽略了它。但是答案的第二部分包含了我真正需要的信息,并对此表示非常感谢。

您是否同意,如果要获取查询的第一个结果,并且通常查询不返回任何内容,则最好执行query.setMaxResults(1)然后再执行getResultList()?这样,我们将避免处理异常。 (注意:我是在很多次的工作中运行此程序的)。

@GuilhermeA:有太多变量可以肯定地说。影响性能的因素:JDBC驱动程序,对OR映射器中DB的支持(它们如何在SQL级别上实现setMaxResults()?),表大小,查询本身等。运行一些性能测试以找出答案。

尝试避免将实体加载到会话(getSingleResult())中只是为了检查其是否存在。这里的计数更好。使用Criteria Query API,它将看起来像这样:

public boolean exists(final Class entityClass, final int id) {

final EntityManager em = getEntityManager();

final CriteriaBuilder cb = em.getCriteriaBuilder();

final CriteriaQuery cq = cb.createQuery(Long.class);

final Root from = cq.from(entityClass);

cq.select(cb.count(from));

cq.where(cb.equal(from.get(AbstractEntity_.id), id));

final TypedQuery tq = em.createQuery(cq);

return tq.getSingleResult() > 0;

}

您从示例中扩展哪个类?我无法在任何地方找到任何现有的exists方法。

您不会在JPA库的任何地方找到此方法。您需要在代码中的某处实现它,并使用JPA API。

那么为什么会有一个@Override注释?那就是让我感到困惑的;)

我懂了。我在接口中定义了方法,然后在类中实现了该方法。那就是它的来源。我将它从示例中删除,以避免造成进一步的混乱。

什么是AbstractEntity_?

JPA元模型。检查此答案。

只需在查询中使用count(e),就不会抛出NoResultException,并且避免加载实体对象

因此,Java代码可以如下所示:

public boolean isRecordExist() {

String query ="select count(e) from YOUR_ENTITY e where ....";

// you will always get a single result

Long count = (Long) entityManager.createQuery( query ).getSingleResult();

return ( ( count.equals( 0L ) ) ? false : true );

}

希望能帮助到某人:)

它有助于编写代码示例

如果要通过主键进行搜索,则还可以使用Entitymanger.find(entityClass, primaryKey),当该实体不存在时返回null。

如果实体存在,它将被加载到会话中,仅保留在那里。

@Radu自从我使用jpa以来已经有一段时间了,但是同样的问题将适用于使用getResultList的解决方案,对吗?

是的,考虑到getSingleResult()在内部也适用于结果列表。但是,我们这里需要的只是检查实体的存在,而没有将其加载到会话中的可能开销。计数操作将始终返回一个数字,因此我们甚至避免了NoResultException。

这是使用T类型和任意ID值的通用方法

public boolean exists(Object key) {

EntityManager entityManager = getEntityManager();

Metamodel metamodel = entityManager.getMetamodel();

EntityType< T > entity = metamodel.entity(entityClass);

SingularAttribute declaredId = entity.getDeclaredId(key.getClass());

CriteriaBuilder cb = entityManager.getCriteriaBuilder();

javax.persistence.criteria.CriteriaQuery< T > cq = cb.createQuery(entityClass);

Root< T > from = cq.from(entityClass);

Predicate condition = cb.equal(from.get(declaredId), key);

cq.where(condition);

TypedQuery< T > q = entityManager.createQuery(cq);

return q.getResultList().size() > 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值