JPA Criteria API не имеет такой функциональности. Кроме того, нелегко прочитать 100
JPA Criteria API
В Criteria API необходимо повторно использовать Expression
.
Рабочий код выглядит следующим образом:
public List<PersonVO> findActivePersonByFullName(String fullName) {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<PersonVO> cq = cb.createQuery(PersonVO.class);
Root<Person> root = cq.from(Person.class);
List<Predicate> predicates = new ArrayList<>();
predicates.add(cb.equal(root.get("active"), true));
Expression<String> fullNameExp =
cb.concat(cb.concat(root.get("firstName"), " "), root.get("lastName"));
cq.select(cb.construct(
PersonVO.class,
root.get("id"),
fullNameExp
));
if (fullName != null) {
predicates.add(cb.equal(fullNameExp, fullName));
}
cq.where(predicates.toArray(new Predicate[0]));
return entityManager.createQuery(cq).getResultList();
}
Сгенерированный SQL код:
select
person0_.id as col_0_0_,
((person0_.first_name||' ')||person0_.last_name) as col_1_0_
from
person person0_
where
person0_.active=?
and (
(
person0_.first_name||?
)||person0_.last_name
)=?
JPA Criteria API и @org.hibernate.annotations.Formula
Hibernate имеет аннотацию org.hibernate.annotations.Formula
, которая может упростить код немного.
Добавьте к сущности вычисляемое поле, помеченное @Formula("first_name || ' ' || last_name")
:
@Entity
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long id;
@Column
public String firstName;
@Column
public String lastName;
@Column
public boolean active;
@Formula("first_name || ' ' || last_name")
private String fullName;
//...getters and setters
}
И в запросе API JPA Criteria укажите поле fullName
:
public List<PersonVO> findActivePersonByFullName(String fullName) {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<PersonVO> cq = cb.createQuery(PersonVO.class);
Root<Person> root = cq.from(Person.class);
List<Predicate> predicates = new ArrayList<>();
predicates.add(cb.equal(root.get("active"), true));
cq.select(cb.construct(
PersonVO.class,
root.get("id"),
root.get("fullName")
));
if (fullName != null) {
predicates.add(cb.equal(root.get("fullName"), fullName));
}
cq.where(predicates.toArray(new Predicate[0]));
return entityManager.createQuery(cq).getResultList();
}
И сгенерированный SQL:
select
person0_.id as col_0_0_,
person0_.first_name || ' ' || person0_.last_name as col_1_0_
from
person person0_
where
person0_.active=?
and person0_.first_name || ' ' || person0_.last_name=?
API Hibernate Criteria
API Hibernate Criteria (устарел с Hibernate 5.2 в пользу JPA Criteria API) позволяет использовать псевдонимы. Но не все базы данных позволяют использовать псевдонимы (например, (full_name || ' ' || last_name) as full_name
) в предложении where
.
В соответствии с PostgreSQL документами :
Имя выходного столбца может использоваться для ссылки на значение столбца в предложениях ORDER BY и GROUP BY, но не в предложениях WHERE или HAVING; вместо этого вы должны написать выражение.
Это означает, что запрос SQL
select p.id,
(p.first_name || ' ' || p.last_name) as full_name
from person p
where p.active = true
and full_name = 'John Doe'
не работает в PostgreSQL.
использование псевдонима в предложении where
недопустимо.