Подтвердить что ты не робот

Как проверить, существует ли запись с помощью JPA

Я хочу знать, присутствует ли данная запись в базе данных или нет. до сих пор я достиг этого, написав запрос JPA и выполнив его методом getSingleResult(). это запустило бы NoResultException, если запись с данным параметром не существует. Конечно, это не обязательное условие для записи, так что иногда это обычное поведение, поэтому я спросил себя, нужно ли бросать исключение, которое мне нужно обработать блоком catch? Насколько я знаю, стоимость обработки исключений довольно велика, поэтому я не очень доволен этим решением, также мне даже не нужен объект, мне нужно только знать его существование в БД.

Есть ли лучший способ проверить, существует или нет объект? например. используя getResultList() и проверить его размер, может быть?

4b9b3361

Ответ 1

Если вы просто хотите знать, существует ли объект, отправьте SELECT COUNT в свою базу данных. Это вернет 0 или 1.

Стоимость обработки исключений не такая большая (если вы не делаете это миллионы раз во время нормальной работы), поэтому я бы не стал беспокоиться.

Но код на самом деле не отражает ваше намерение. Поскольку getSingleResult() вызывает getResultList() внутренне, он становится яснее:

public boolean objExists(...) {
    return getResultList(...).size() == 1;
}

Если вы запрашиваете идентификатор объекта и активируете кеширование, это станет простым поиском в кеше, если объект уже загружен.

Ответ 2

Попробуйте не загружать объект в сеанс (getSingleResult()), чтобы проверить его существование. Счет здесь лучше. С API запросов критериев будет выглядеть примерно так:

public <E extends AbstractEntity> boolean exists(final Class<E> entityClass, final int id) {
    final EntityManager em = getEntityManager();
    final CriteriaBuilder cb = em.getCriteriaBuilder();

    final CriteriaQuery<Long> cq = cb.createQuery(Long.class);
    final Root<E> from = cq.from(entityClass);

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

    final TypedQuery<Long> tq = em.createQuery(cq);
    return tq.getSingleResult() > 0;
}

Ответ 3

Просто используйте 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 );
}

Надеюсь, что это поможет кому-то:)

Ответ 4

Если вы выполняете поиск по первичному ключу, вы также можете использовать Entitymanger.find(entityClass, primaryKey), который возвращает null, когда сущность не существует.

Ответ 5

вот общий подход к работе с типом T и произвольным значением ID

public boolean exists(Object key) { 
    EntityManager entityManager = getEntityManager();
    Metamodel metamodel = entityManager.getMetamodel();
    EntityType<T> entity = metamodel.entity(entityClass);
    SingularAttribute<T, ? extends Object> 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; 
}