开发者

How to check if a record exists using JPA

I want to know whether a given record is present in a database or not. so far I have achieved this by writing a JPA query and the running it by getSingleResult()开发者_JS百科 method. this would throw a NoResultException if the record with the given parameter does not exist. Of course, it's not a must for the record to exist, so it's the normal behaviour sometimes, that's why I asked to myself, is it neccessary to throw an Exception which I have to handle by a catch block? As far as I know the cost of Exception handling is quite big, so I'm not very satisfied with this solution, also, I don't even need the object, I only need to know it's existence in the DB.

Is there a better way to check whether an object exist or not? eg. using getResultList() and checking it's size maybe?


If you just want to know whether the object exists, send a SELECT COUNT to your database. That will return 0 or 1.

The cost of the exception handling isn't that big (unless you do that millions of times during a normal operation), so I wouldn't bother.

But the code doesn't really reflect your intention. Since getSingleResult() calls getResultList() internally, it's clearer like so:

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

If you query by object id and you have caching enabled, that will become a simple lookup in the cache if the object has already been loaded.


Try to avoid loading the entity into the session (getSingleResult()) just to check for it's existence. A count is better here. With the Criteria Query API it would look something like this:

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;
}


Simply use count(e) in your query, so no NoResultException will be thrown and you will avoid loading the entity object
So the Java code can be as follow:

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 );
}

Hope that helps someone :)


If you are searching by primary key you can also use Entitymanger.find(entityClass, primaryKey) which returns null when the entity does not exist.


here is a generic approach to work with a type T and an arbitrary ID value

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; 
}


Try this

public boolean exists(Object id){
    return getEntityManager().find(entityClass, id)!=null;
}


A much easier solution to this problem is expanding the repository with a function of the return type Optional<Datatype>. Using this within a stream with a filter applied, you can easily check if the object exists with .isPresent()

For example:

public interface ChatArchiveRepo extends JpaRepository<ChatArchive, Long> {

    List<ChatArchive> findByUsername(String username);

    Optional<ChatArchive> findByConversationUid(String conversationUid);

}

And within your function or stream:

.filter(conversation -> !chatArchiveRepo.findByConversationUid(conversation.getUid()).isPresent())


I would just add a custom method in jpa repository

@Query("SELECT COUNT(ID) FROM 'name' WHERE transactionId =:id")

int findIfTxnPresentById(@Param("id") Long txnId);

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜