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);
精彩评论