Как проверить, существует ли запись с использованием JPA - PullRequest
26 голосов
/ 07 декабря 2010

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

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

Ответы [ 5 ]

26 голосов
/ 07 декабря 2010

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

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

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

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

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

18 голосов
/ 07 мая 2015

Старайтесь не загружать сущность в сеанс (getSingleResult()) только для проверки ее существования.Счет здесь лучше.С Criteria Query 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;
}
7 голосов
/ 30 августа 2017

Просто используйте 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 голосов
/ 07 декабря 2010

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

1 голос
/ 14 декабря 2017

здесь используется общий подход для работы с типом 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; 
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...