diff --git a/hibernate-core/src/main/java/org/hibernate/query/results/complete/CompleteResultBuilderBasicValuedStandard.java b/hibernate-core/src/main/java/org/hibernate/query/results/complete/CompleteResultBuilderBasicValuedStandard.java
index 3dc5a58363aa..ffd03f3596a1 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/results/complete/CompleteResultBuilderBasicValuedStandard.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/results/complete/CompleteResultBuilderBasicValuedStandard.java
@@ -27,7 +27,7 @@
/**
* ResultBuilder for scalar results defined via:
* - JPA {@link jakarta.persistence.ColumnResult}
- * - `` as part of a `` stanza in `hbm.xml`
+ * - `<return-scalar/>` as part of a `<resultset/>` stanza in `hbm.xml`
*
*
* @author Steve Ebersole
@@ -60,7 +60,7 @@ public ResultBuilder cacheKeyInstance() {
@Override
public Class> getJavaType() {
- return explicitJavaType.getJavaTypeClass();
+ return explicitJavaType == null ? null : explicitJavaType.getJavaTypeClass();
}
@Override
@@ -157,23 +157,14 @@ public boolean equals(Object o) {
if ( o == null || getClass() != o.getClass() ) {
return false;
}
-
CompleteResultBuilderBasicValuedStandard that = (CompleteResultBuilderBasicValuedStandard) o;
-
- if ( !Objects.equals( explicitColumnName, that.explicitColumnName ) ) {
- return false;
- }
- if ( !Objects.equals( explicitType, that.explicitType ) ) {
- return false;
- }
- return explicitJavaType.equals( that.explicitJavaType );
+ return Objects.equals( explicitColumnName, that.explicitColumnName )
+ && Objects.equals( explicitType, that.explicitType )
+ && Objects.equals( explicitJavaType, that.explicitJavaType );
}
@Override
public int hashCode() {
- int result = explicitColumnName != null ? explicitColumnName.hashCode() : 0;
- result = 31 * result + ( explicitType != null ? explicitType.hashCode() : 0 );
- result = 31 * result + explicitJavaType.hashCode();
- return result;
+ return Objects.hash( explicitColumnName, explicitType, explicitJavaType );
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/query/sql/internal/NativeQueryImpl.java b/hibernate-core/src/main/java/org/hibernate/query/sql/internal/NativeQueryImpl.java
index 3ec4fbadc85d..f2964773024c 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/sql/internal/NativeQueryImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/sql/internal/NativeQueryImpl.java
@@ -278,7 +278,7 @@ else if ( resultJavaType != null && resultJavaType != Object[].class ) {
throw new IllegalArgumentException( "Named query exists but its result type is not compatible" );
case 1:
final Class> actualResultJavaType = resultSetMapping.getResultBuilders().get( 0 ).getJavaType();
- if ( !resultJavaType.isAssignableFrom( actualResultJavaType ) ) {
+ if ( actualResultJavaType != null && !resultJavaType.isAssignableFrom( actualResultJavaType ) ) {
throw buildIncompatibleException( resultJavaType, actualResultJavaType );
}
break;
diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/resultmapping/NamedNativeQueryWithCountColumnTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/resultmapping/NamedNativeQueryWithCountColumnTest.java
new file mode 100644
index 000000000000..4e50bf90bf58
--- /dev/null
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/resultmapping/NamedNativeQueryWithCountColumnTest.java
@@ -0,0 +1,105 @@
+/*
+ * 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.query.resultmapping;
+
+import org.hibernate.cfg.AvailableSettings;
+import org.hibernate.dialect.H2Dialect;
+
+import org.hibernate.testing.TestForIssue;
+import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
+import org.hibernate.testing.orm.junit.Jpa;
+import org.hibernate.testing.orm.junit.RequiresDialect;
+import org.hibernate.testing.orm.junit.Setting;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import jakarta.persistence.ColumnResult;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.NamedNativeQuery;
+import jakarta.persistence.SqlResultSetMapping;
+import jakarta.persistence.Table;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * @author Nathan Xu
+ */
+@Jpa(
+ annotatedClasses = NamedNativeQueryWithCountColumnTest.Sample.class,
+ properties = @Setting(name = AvailableSettings.GLOBALLY_QUOTED_IDENTIFIERS, value = "true")
+)
+@TestForIssue(jiraKey = "HHH-15070")
+class NamedNativeQueryWithCountColumnTest {
+
+ @BeforeEach
+ public void setUp(EntityManagerFactoryScope scope) {
+ scope.inTransaction(
+ entityManager -> {
+ for ( int i = 0; i < 3; i++ ) {
+ Sample sample = new Sample( i, String.valueOf( i ) );
+ entityManager.persist( sample );
+ }
+ }
+ );
+ }
+
+ @AfterEach
+ public void tearDown(EntityManagerFactoryScope scope) {
+ scope.inTransaction(
+ entityManager ->
+ entityManager.createQuery( "delete from Sample" ).executeUpdate()
+ );
+ }
+
+ @Test
+ void testNamedNativeQuery(EntityManagerFactoryScope scope) {
+ scope.inTransaction(
+ entityManager ->
+ entityManager.createNamedQuery( "sample.count", Long.class )
+ );
+ }
+
+ @Test
+ @RequiresDialect(H2Dialect.class)
+ void testNamedNativeQueryExecution(EntityManagerFactoryScope scope) {
+ scope.inTransaction(
+ entityManager -> {
+ Long count = entityManager.createNamedQuery( "sample.count", Long.class ).getSingleResult();
+ assertThat( count, is( 3L ) );
+ } );
+ }
+
+ @SqlResultSetMapping(
+ name = "mapping",
+ columns = @ColumnResult(name = "cnt")
+ )
+ @NamedNativeQuery(
+ name = "sample.count",
+ resultSetMapping = "mapping",
+ query = "SELECT count(*) AS cnt FROM SAMPLE_TABLE"
+ )
+ @Entity(name = "Sample")
+ @Table(name = "SAMPLE_TABLE")
+ static class Sample {
+
+ @Id
+ Integer id;
+
+ String name;
+
+ public Sample() {
+ }
+
+ public Sample(Integer id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+ }
+}