Hernan (
https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=62fba63...
) *created* an issue
Hibernate ORM (
https://hibernate.atlassian.net/browse/HHH?atlOrigin=eyJpIjoiZWZhNjk2NDcz...
) / Bug (
https://hibernate.atlassian.net/browse/HHH-15725?atlOrigin=eyJpIjoiZWZhNj...
) HHH-15725 (
https://hibernate.atlassian.net/browse/HHH-15725?atlOrigin=eyJpIjoiZWZhNj...
) Criteria API Expression.as adds cast to sql string negatively affecting performance (
https://hibernate.atlassian.net/browse/HHH-15725?atlOrigin=eyJpIjoiZWZhNj...
)
Issue Type: Bug Affects Versions: 6.1.5 Assignee: Unassigned Components: hibernate-core
Created: 15/Nov/2022 11:34 AM Environment: Hibernate ORM core version 6.1.5.Final, openjdk
version "11" 2018-09-25, Ubuntu 20.04.4 LTS, SQL Server 2008 R2 (SP3) Priority:
Major Reporter: Hernan (
https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=62fba63...
)
When calling method jakarta.persistence.criteria.Expression.as (
http://jakarta.persistence.criteria.Expression.as ) , in all cases, the code is adding
"cast" to predicate even if the expression type is the same as the resulting
type
This affect negatively the query performance as the resulting query plan is not using
indexes in the correct way
As an example, using SQLServer2005Dialect, a simple string “equals” predicate on field
named "empresa" with sql type char(4) results in:
cast(a1_0.empresa as varchar(max))=?
as this field is part of the primary key the resulting query plan performs a scan over the
associated clustered index instead of a seek.
The code is located in the class
org.hibernate.query.sqm.tree.expression.AbstractSqmExpression :
public <X> SqmExpression<X> as(Class<X> type) {
return nodeBuilder().cast(this, type);
}
and then org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder :
public <X, T> SqmExpression<X> cast(JpaExpression<T> expression,
Class<X> castTargetJavaType) {
final BasicDomainType<X> type =
getTypeConfiguration().standardBasicTypeForJavaType( castTargetJavaType );
return getFunctionDescriptor( "cast" ).generateSqmExpression(
asList( (SqmTypedNode<?>) expression, new SqmCastTarget<>( type, this )
),
type,
queryEngine,
getJpaMetamodel().getTypeConfiguration()
);
}
Equivalent code in HB 5.0.12 (org.hibernate.jpa.criteria.expression.ExpressionImpl) first
evaluates types, and only adds cast when needed:
public <X> Expression<X> as(Class<X> type) {
return type.equals( getJavaType() )
? (Expression<X>) this
: new CastFunction<X, T>( criteriaBuilder(), type, this );
}
But also from JPA documentation I undestand that even on different types the cast must not
be done (from
https://jakarta.ee/specifications/persistence/3.1/apidocs/jakarta.persist...
(
https://jakarta.ee/specifications/persistence/3.1/apidocs/jakarta.persist...
) )
" Perform a typecast upon the expression, returning a new expression object. This
method *does not cause type conversion: the runtime type is not changed*. Warning: may
result in a runtime failure. "
Thanks in advance
(
https://hibernate.atlassian.net/browse/HHH-15725#add-comment?atlOrigin=ey...
) Add Comment (
https://hibernate.atlassian.net/browse/HHH-15725#add-comment?atlOrigin=ey...
)
Get Jira notifications on your phone! Download the Jira Cloud app for Android (
https://play.google.com/store/apps/details?id=com.atlassian.android.jira....
) or iOS (
https://itunes.apple.com/app/apple-store/id1006972087?pt=696495&ct=Em...
) This message was sent by Atlassian Jira (v1001.0.0-SNAPSHOT#100210- sha1:28a3636 )