diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/ResultsetMappingSecondPass.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/ResultsetMappingSecondPass.java index bba126e120..e2c3c2d771 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/ResultsetMappingSecondPass.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/ResultsetMappingSecondPass.java @@ -30,6 +30,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; + import javax.persistence.ColumnResult; import javax.persistence.ConstructorResult; import javax.persistence.EntityResult; @@ -52,7 +53,6 @@ import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; import org.hibernate.mapping.ToOne; import org.hibernate.mapping.Value; - import org.jboss.logging.Logger; /** @@ -62,9 +62,9 @@ public class ResultsetMappingSecondPass implements QuerySecondPass { private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, ResultsetMappingSecondPass.class.getName()); - private SqlResultSetMapping ann; - private Mappings mappings; - private boolean isDefault; + private final SqlResultSetMapping ann; + private final Mappings mappings; + private final boolean isDefault; public ResultsetMappingSecondPass(SqlResultSetMapping ann, Mappings mappings, boolean isDefault) { this.ann = ann; @@ -72,6 +72,7 @@ public class ResultsetMappingSecondPass implements QuerySecondPass { this.isDefault = isDefault; } + @Override public void doSecondPass(Map persistentClasses) throws MappingException { //TODO add parameters checkings if ( ann == null ) return; @@ -188,7 +189,7 @@ public class ResultsetMappingSecondPass implements QuerySecondPass { mappings.getObjectNameNormalizer().normalizeIdentifierQuoting( column.name() ), - null + column.type() != null ? mappings.getTypeResolver().heuristicType( column.type().getName() ) : null ) ); } diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/query/ScalarResultNativeQueryTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/query/ScalarResultNativeQueryTest.java new file mode 100644 index 0000000000..04e6543237 --- /dev/null +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/query/ScalarResultNativeQueryTest.java @@ -0,0 +1,96 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.test.query; + +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import javax.persistence.ColumnResult; +import javax.persistence.Entity; +import javax.persistence.EntityManager; +import javax.persistence.Id; +import javax.persistence.NamedNativeQuery; +import javax.persistence.SqlResultSetMapping; +import javax.persistence.Table; + +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; +import org.junit.Test; + +/** + * Tests for selecting scalar value from native queries. + * + * @author Gunnar Morling + */ +public class ScalarResultNativeQueryTest extends BaseEntityManagerFunctionalTestCase { + + @Entity(name="Person") + @Table(name="PERSON") + @NamedNativeQuery(name = "personAge", query = "select p.age from person p", resultSetMapping = "ageStringMapping") + @SqlResultSetMapping(name = "ageStringMapping", columns = { @ColumnResult(name = "age", type = String.class) }) + public static class Person { + + @Id + private Integer id; + + @SuppressWarnings("unused") + private int age; + + public Person() { + } + + public Person(Integer id, int age) { + this.id = id; + this.age = age; + } + } + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { Person.class }; + } + + @Test + public void shouldApplyConfiguredTypeForProjectionOfScalarValue() { + EntityManager em = getOrCreateEntityManager(); + em.getTransaction().begin(); + em.persist( new Person( 1, 29 ) ); + em.getTransaction().commit(); + em.close(); + + em = getOrCreateEntityManager(); + em.getTransaction().begin(); + List results = em.createNamedQuery( "personAge", String.class ).getResultList(); + assertEquals( 1, results.size() ); + assertEquals( "29", results.get( 0 ) ); + em.getTransaction().commit(); + em.close(); + + em = getOrCreateEntityManager(); + em.getTransaction().begin(); + em.createQuery( "delete from Person" ).executeUpdate(); + em.getTransaction().commit(); + em.close(); + } +}