Well, when there is something to copy-paste (thanks, Victor)
public Long query(String name) { CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Role> cq = cb.createQuery(Role.class); Root<Role> root = cq.from(Role.class); cq.where(cb.equal(root.get("name"), cb.parameter(String.class, "name"))); try { // Тут возможно надо делать приведение типов, // либо вызывать вариант метода, в котором указывается тип возвращаемого параметра // em.createQuery(cq, Role.class)... // либо и так сойдёт return em.createQuery(cq).setParameter("name", name).getSingleResult().getId(); } catch (NoResultException ex) { return null; } }
or
public Long query(String name) { CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Role> cq = cb.createQuery(Role.class); Root<Role> root = cq.from(Role.class); cq.where(cb.equal(root.get("name"), cb.parameter(String.class, "name"))); List<Role> roles = em.createQuery(cq).setParameter("name", name).getResultList(); return roles.isEmpty() ? null : roles.get(0).getId(); }
Well, that is, a variant of Victor without extra distinct and in places assembled in one line at the expense of the fluent, which is widely used in JPA API.
If you are using static metamodel generation, then root.get ("name") is replaced by root.get (Role_.name). Type safe. Cho. Otherwise on the fig you generally criteria, when there is a text JPQL, and even better than SQL?