Как проверить, существует ли запись с помощью JPA
Я хочу знать, присутствует ли данная запись в базе данных или нет. до сих пор я достиг этого, написав запрос JPA и выполнив его методом getSingleResult()
. это запустило бы NoResultException
, если запись с данным параметром не существует. Конечно, это не обязательное условие для записи, так что иногда это обычное поведение, поэтому я спросил себя, нужно ли бросать исключение, которое мне нужно обработать блоком catch? Насколько я знаю, стоимость обработки исключений довольно велика, поэтому я не очень доволен этим решением, также мне даже не нужен объект, мне нужно только знать его существование в БД.
Есть ли лучший способ проверить, существует или нет объект? например. используя getResultList()
и проверить его размер, может быть?
Ответы
Ответ 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;
}