The following JPA criteria query succeeds on Hibernate (4.2.7 final).
CriteriaBuilder criteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaQuery<Boolean>criteriaQuery=criteriaBuilder.createQuery(Boolean.class);
Root<UserTable> root = criteriaQuery.from(entityManager.getMetamodel().entity(UserTable.class));
criteriaQuery.multiselect(root.get(UserTable_.enabled));
ParameterExpression<String>parameterExpression=criteriaBuilder.parameter(String.class);
criteriaQuery.where(criteriaBuilder.equal(criteriaBuilder.lower(criteriaBuilder.trim(root.get(UserTable_.emailId))), criteriaBuilder.lower(criteriaBuilder.trim(parameterExpression))));
List<Boolean> list = entityManager.createQuery(criteriaQuery).setParameter(parameterExpression, "admin").getResultList();
for(Boolean o:list)
{
System.out.println("enabled : "+o);
}
It is simply meant to return a scalar Boolean value from MySQL database. The corresponding column is of type TINYINT(1)
in MySQL.
It generate the following SQL statement.
SELECT
usertable0_.enabled as col_0_0_
FROM
social_networking.user_table usertable0_
WHERE
lower(trim(BOTH FROM usertable0_.email_id))=lower(trim(BOTH FROM ?))
The same query fails on EclipseLink (2.5.1) in which case it returns nothing (no error, no exception). It however, generates a correct SQL statement as follows.
SELECT enabled
FROM projectdb.user_table
WHERE (LOWER(TRIM(email_id)) = LOWER(TRIM(?)))
bind => [admin]
The corresponding JPQL like so,
SELECT u.enabled
FROM UserTable u
WHERE lower(trim(u.emailId))=lower(trim(:emailId))
also doesn't get the value in question.
It however, works with additional columns as shown below.
CriteriaBuilder criteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaQuery<Object[]>criteriaQuery=criteriaBuilder.createQuery(Object[].class);
Root<UserTable> root = criteriaQuery.from(entityManager.getMetamodel().entity(UserTable.class));
criteriaQuery.multiselect(root.get(UserTable_.enabled), root.get(UserTable_.firstName));
ParameterExpression<String>parameterExpression=criteriaBuilder.parameter(String.class);
criteriaQuery.where(criteriaBuilder.equal(criteriaBuilder.lower(criteriaBuilder.trim(root.get(UserTable_.emailId))), criteriaBuilder.lower(criteriaBuilder.trim(parameterExpression))));
List<Object[]> list = entityManager.createQuery(criteriaQuery).setParameter(parameterExpression, userName).getResultList();
One extra column root.get(UserTable_.firstName)
is added and the return type of CriteriaQuery
is changed from CriteriaQuery<Boolean>
to CriteriaQuery<Object[]>
.
The column is defined as follows in the corresponding entity.
@Basic(optional = false)
@NotNull
@Column(name = "enabled")
private Boolean enabled; //Getter and setter.
Why doesn't it given a Boolean value in EclipseLink?
This is due to EclipseLink bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=340089 which causes EclipseLink to be unable to distinguish the value returned from the SQL query from the construct it uses internally to indicate there were no results. Selecting another value is the only workaround, but it seems simple enough that not many people hit it or just workaround it without commenting or voting for the bug.