Skip Criteria result type validation when JPA query compliance is enabled

This commit is contained in:
Andrea Boriero 2022-01-25 17:30:41 +01:00 committed by Steve Ebersole
parent cb6be7dc81
commit da00adf0da
2 changed files with 134 additions and 10 deletions

View File

@ -354,10 +354,13 @@ public class QuerySqmImpl<R>
// todo (6.0) : implement
}
else {
final boolean jpaQueryComplianceEnabled = sessionFactory.getSessionFactoryOptions()
.getJpaCompliance()
.isJpaQueryComplianceEnabled();
if ( selections.size() != 1 ) {
final String errorMessage = "Query result-type error - multiple selections: use Tuple or array";
if ( sessionFactory.getSessionFactoryOptions().getJpaCompliance().isJpaQueryComplianceEnabled() ) {
if ( jpaQueryComplianceEnabled ) {
throw new IllegalArgumentException( errorMessage );
}
else {
@ -377,6 +380,9 @@ public class QuerySqmImpl<R>
}
}
if ( jpaQueryComplianceEnabled ) {
return;
}
verifyResultType( resultClass, sqmSelection.getNodeType(), sessionFactory );
}
}
@ -387,9 +393,8 @@ public class QuerySqmImpl<R>
SessionFactoryImplementor sessionFactory) {
assert sqmExpressible != null;
assert sqmExpressible.getExpressibleJavaType() != null;
final Class<?> javaTypeClass = sqmExpressible.getExpressibleJavaType().getJavaTypeClass();
if ( ! resultClass.isAssignableFrom( javaTypeClass ) ) {
if ( !resultClass.isAssignableFrom( javaTypeClass ) ) {
// Special case for date because we always report java.util.Date as expression type
// But the expected resultClass could be a subtype of that, so we need to check the JdbcType
if ( javaTypeClass == Date.class ) {
@ -428,13 +433,7 @@ public class QuerySqmImpl<R>
resultClass.getName(),
sqmExpressible.getExpressibleJavaType().getJavaType().getTypeName()
);
if ( sessionFactory.getSessionFactoryOptions().getJpaCompliance().isJpaQueryComplianceEnabled() ) {
throw new IllegalArgumentException( errorMessage );
}
else {
throw new QueryTypeMismatchException( errorMessage );
}
throw new QueryTypeMismatchException( errorMessage );
}
}

View File

@ -0,0 +1,125 @@
/*
* 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.orm.test.jpa.compliance;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.hibernate.testing.orm.junit.Jpa;
import org.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.MapKey;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.From;
@Jpa(
annotatedClasses = {
CriteriaWrongResultClassTest.Department.class,
CriteriaWrongResultClassTest.Person.class
},
properties = @Setting(name = AvailableSettings.JPA_QUERY_COMPLIANCE, value = "true")
)
public class CriteriaWrongResultClassTest {
@Test
public void getMapAttributeTest(EntityManagerFactoryScope scope) {
scope.inEntityManager(
entityManager -> {
final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
final CriteriaQuery query = criteriaBuilder.createQuery( Expression.class );
final From<Department, Department> department = query.from( Department.class );
query.where( criteriaBuilder.equal( department.get( "id" ), 1 ) );
query.select( department.get( "people" ) );
List<Person> people = entityManager.createQuery( query ).getResultList();
}
);
}
@Entity
@Table(name = "DEPARTMENT_TABLE")
public static class Department {
@Id
private int id;
private String name;
@OneToMany
@MapKey(name = "nickname")
private Map<String, Person> people = new HashMap<>();
public Department() {
}
public Department(
int id,
String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public Map<String, Person> getPeople() {
return people;
}
public void addPerson(Person person){
people.put( person.getNickname(), person );
}
}
@Entity
@Table(name = "EMPLOYEE_TABLE")
public static class Person {
@Id
private int id;
private String name;
private String nickname;
public Person() {
}
public Person(int id, String name, String nickname) {
this.id = id;
this.name = name;
this.nickname = nickname;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getNickname() {
return nickname;
}
}
}