Upgrade to 6.3 RC1 - Cannot compare left expression of type 'java.sql.Timestamp' with right expression of type 'com.model.entity.impl.User'

Hi,

I recently tested upgrading to 6.3.0.CR1 from 6.1.7.Final to test and received the below exception:

Caused by: org.hibernate.query.SemanticException: Cannot compare left expression of type 'java.sql.Timestamp' with right expression of type 'com.model.entity.impl.User'
	at org.hibernate.query.sqm.internal.TypecheckUtil.assertComparable(TypecheckUtil.java:325) ~[hibernate-core-6.3.0.CR1.jar:6.3.0.CR1]
	at org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder.greaterThanOrEqualTo(SqmCriteriaNodeBuilder.java:2148) ~[hibernate-core-6.3.0.CR1.jar:6.3.0.CR1]
	at org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder.greaterThanOrEqualTo(SqmCriteriaNodeBuilder.java:185) ~[hibernate-core-6.3.0.CR1.jar:6.3.0.CR1]
	at com.service.impl.UserServiceImpl$1.toPredicate(UserServiceImpl.java:277) ~[app-services-1.1.0.jar:1.1.0]
	at com.repository.specifications.query.QueryBuilderSpecificationAnd.toPredicate(QueryBuilderSpecificationAnd.java:51) ~[repository-1.1.0.jar:1.1.0]
	at com.repository.specifications.VisibilityProfileSpecification.toPredicate(VisibilityProfileSpecification.java:143) ~[epository-1.1.0.jar:1.1.0]
	at org.springframework.data.jpa.repository.support.SimpleJpaRepository.applySpecificationToCriteria(SimpleJpaRepository.java:829) ~[spring-data-jpa-3.1.2.jar:3.1.2]
	at org.springframework.data.jpa.repository.support.SimpleJpaRepository.getQuery(SimpleJpaRepository.java:748) ~[spring-data-jpa-3.1.2.jar:3.1.2]
	at org.springframework.data.jpa.repository.support.SimpleJpaRepository.getQuery(SimpleJpaRepository.java:733) ~[spring-data-jpa-3.1.2.jar:3.1.2]
	at com.repository.stream.impl.StreamRepositoryImpl.scrollableResults(StreamRepositoryImpl.java:121) ~[repository-1.1.0.jar:1.1.0]
	at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
	at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
	at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
	at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
	at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new$0(RepositoryMethodInvoker.java:288) ~[spring-data-commons-3.1.2.jar:3.1.2]
	at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:136) ~[spring-data-commons-3.1.2.jar:3.1.2]
	at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:120) ~[spring-data-commons-3.1.2.jar:3.1.2]
	at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:516) ~[spring-data-commons-3.1.2.jar:3.1.2]
	at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:285) ~[spring-data-commons-3.1.2.jar:3.1.2]
	at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:628) ~[spring-data-commons-3.1.2.jar:3.1.2]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.0.11.jar:6.0.11]
	at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:168) ~[spring-data-commons-3.1.2.jar:3.1.2]
	at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:143) ~[spring-data-commons-3.1.2.jar:3.1.2]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.0.11.jar:6.0.11]
	at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:72) ~[spring-data-commons-3.1.2.jar:3.1.2]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.0.11.jar:6.0.11]
	at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) ~[spring-tx-6.0.11.jar:6.0.11]
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:391) ~[spring-tx-6.0.11.jar:6.0.11]
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-6.0.11.jar:6.0.11]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.0.11.jar:6.0.11]
	at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) ~[spring-tx-6.0.11.jar:6.0.11]
	... 21 more

It is caused by this which was working in 6.1.7:

Subquery subquery = query.subquery(User.class);
Root ua = subquery.from(User.class);
subquery.select(ua.get("userDts"));
subquery.where(cb.equal(ua.get("id"), callingUser.getId()));
	
String propertyName = "myDate";
Predicate searchCriteria = cb.greaterThanOrEqualTo(root.get(propertyName), subquery);

The root entity (which is a view) contains:

@Column(name = "MY_DATE")
@Temporal(TemporalType.TIMESTAMP)
private Date myDate;

Sub query entity:

@Column(name = "USER_DTS", length = 11)
private Date userDts;

Is this a bug or some new change to the api usage?

The bug is in your code

Subquery subquery = query.subquery(User.class);

should be

Subquery subquery = query.subquery(Date.class);
1 Like

Cheers for the reply that fixed it.

Do you know why that worked in previous versions?

Because previous versions didn’t care to validate comparability of expressions and so ended up producing invalid SQL instead. Newer Hibernate versions do validate. Now the problem in your case is two fold actually and IMO you should have seen an error already in the line subquery.select( ua.get("userDts") ) because selecting something of type Date is not assignable to the result type User which you specified with query.subquery(User.class)