mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-17 16:44:57 +00:00
[HHH-17416] Add new inheritor JavaObjectType for specifying unresolved query parameter
This commit is contained in:
parent
71c95f1699
commit
67cdd0b28a
@ -27,6 +27,7 @@
|
||||
import org.hibernate.query.sqm.tree.expression.SqmLiteralNull;
|
||||
import org.hibernate.type.BasicPluralType;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.QueryParameterJavaObjectType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
|
||||
import java.time.temporal.Temporal;
|
||||
@ -107,6 +108,12 @@ public static boolean areTypesComparable(
|
||||
return true;
|
||||
}
|
||||
|
||||
// for query with parameters we are unable to resolve the correct JavaType, especially for tuple of parameters
|
||||
|
||||
if ( lhsType instanceof QueryParameterJavaObjectType || rhsType instanceof QueryParameterJavaObjectType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// since we can't so anything meaningful here, just allow
|
||||
// any comparison with multivalued parameters
|
||||
|
||||
|
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.type;
|
||||
|
||||
public class QueryParameterJavaObjectType extends JavaObjectType {
|
||||
|
||||
public static final QueryParameterJavaObjectType INSTANCE = new QueryParameterJavaObjectType();
|
||||
|
||||
public QueryParameterJavaObjectType() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "QUERY_PARAMETER_JAVA_OBJECT";
|
||||
}
|
||||
}
|
@ -57,12 +57,14 @@
|
||||
import org.hibernate.query.sqm.IntervalType;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||
import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer;
|
||||
import org.hibernate.resource.beans.spi.ManagedBean;
|
||||
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.BasicTypeRegistry;
|
||||
import org.hibernate.type.QueryParameterJavaObjectType;
|
||||
import org.hibernate.type.SqlTypes;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
@ -591,10 +593,17 @@ private Class<?> entityClassForEntityName(String entityName) {
|
||||
public SqmExpressible<?> resolveTupleType(List<? extends SqmTypedNode<?>> typedNodes) {
|
||||
final SqmExpressible<?>[] components = new SqmExpressible<?>[typedNodes.size()];
|
||||
for ( int i = 0; i < typedNodes.size(); i++ ) {
|
||||
final SqmExpressible<?> sqmExpressible = typedNodes.get( i ).getNodeType();
|
||||
components[i] = sqmExpressible != null
|
||||
? sqmExpressible
|
||||
: getBasicTypeForJavaType( Object.class );
|
||||
SqmTypedNode<?> tupleElement = typedNodes.get(i);
|
||||
final SqmExpressible<?> sqmExpressible = tupleElement.getNodeType();
|
||||
// keep null value for Named Parameters
|
||||
if (tupleElement instanceof SqmParameter<?> && sqmExpressible == null) {
|
||||
components[i] = QueryParameterJavaObjectType.INSTANCE;
|
||||
}
|
||||
else {
|
||||
components[i] = sqmExpressible != null
|
||||
? sqmExpressible
|
||||
: getBasicTypeForJavaType( Object.class );
|
||||
}
|
||||
}
|
||||
return arrayTuples.computeIfAbsent(
|
||||
new ArrayCacheKey( components ),
|
||||
|
@ -0,0 +1,77 @@
|
||||
package org.hibernate.orm.test.query.hql;
|
||||
|
||||
import jakarta.persistence.TypedQuery;
|
||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||
import jakarta.persistence.criteria.CriteriaQuery;
|
||||
import jakarta.persistence.criteria.Root;
|
||||
import org.hibernate.orm.test.query.sqm.domain.Person;
|
||||
import org.hibernate.orm.test.query.sqm.domain.Person_;
|
||||
import org.hibernate.query.SelectionQuery;
|
||||
import org.hibernate.query.SemanticException;
|
||||
import org.hibernate.testing.orm.junit.BaseSessionFactoryFunctionalTest;
|
||||
import org.hibernate.testing.orm.junit.JiraKey;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@JiraKey(value = "HHH-17416")
|
||||
public class HHH17416Test extends BaseSessionFactoryFunctionalTest {
|
||||
|
||||
private static final Person person = new Person();
|
||||
static {
|
||||
person.setPk(7);
|
||||
person.setNickName("Tadpole");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] {Person.class};
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
inTransaction(session -> session.persist(person));
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void teardown() {
|
||||
inTransaction(session -> session.createMutationQuery("delete from Person").executeUpdate());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWhereClauseWithTuple() {
|
||||
sessionFactoryScope().inTransaction(
|
||||
entityManager -> {
|
||||
SelectionQuery<Person> selectionQuery = entityManager.createSelectionQuery("from Person p where (p.id, p.nickName) = (:val1, :val2)", Person.class);
|
||||
selectionQuery = selectionQuery.setParameter("val1", person.getPk()).setParameter("val2", person.getNickName());
|
||||
Person retrievedPerson = selectionQuery.getSingleResult();
|
||||
Assertions.assertEquals(person.getPk(), retrievedPerson.getPk());
|
||||
Assertions.assertEquals(person.getNickName(), retrievedPerson.getNickName());
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWhereClauseWithInvalidObjectType() {
|
||||
sessionFactoryScope().inTransaction(
|
||||
entityManager -> {
|
||||
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
|
||||
|
||||
CriteriaQuery<Person> criteria = builder.createQuery(Person.class);
|
||||
Root<Person> root = criteria.from(Person.class);
|
||||
criteria.select(root);
|
||||
|
||||
try {
|
||||
criteria.where(builder.equal(root.get(Person_.nickName), builder.literal(new Object())));
|
||||
TypedQuery<Person> ignored = entityManager.createQuery(criteria);
|
||||
Assertions.fail("Should have failed with 'Cannot compare left expression of type' of type `org.hibernate.query.SemanticException'");
|
||||
}
|
||||
catch (Exception e) {
|
||||
Assertions.assertTrue(e instanceof SemanticException);
|
||||
Assertions.assertTrue(e.getMessage().startsWith("Cannot compare left expression of type"));
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user