HHH-8493 - Implement ConstructorResults handling
This commit is contained in:
parent
312283cb0e
commit
0bf29bc2fd
|
@ -31,6 +31,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.persistence.ColumnResult;
|
||||
import javax.persistence.ConstructorResult;
|
||||
import javax.persistence.EntityResult;
|
||||
import javax.persistence.FieldResult;
|
||||
import javax.persistence.SqlResultSetMapping;
|
||||
|
@ -43,6 +44,7 @@ import org.hibernate.cfg.BinderHelper;
|
|||
import org.hibernate.cfg.Mappings;
|
||||
import org.hibernate.cfg.QuerySecondPass;
|
||||
import org.hibernate.engine.ResultSetMappingDefinition;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryConstructorReturn;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryRootReturn;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryScalarReturn;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
@ -191,6 +193,21 @@ public class ResultsetMappingSecondPass implements QuerySecondPass {
|
|||
);
|
||||
}
|
||||
|
||||
for ( ConstructorResult constructorResult : ann.classes() ) {
|
||||
List<NativeSQLQueryScalarReturn> columnReturns = new ArrayList<NativeSQLQueryScalarReturn>();
|
||||
for ( ColumnResult columnResult : constructorResult.columns() ) {
|
||||
columnReturns.add(
|
||||
new NativeSQLQueryScalarReturn(
|
||||
mappings.getObjectNameNormalizer().normalizeIdentifierQuoting( columnResult.name() ),
|
||||
null
|
||||
)
|
||||
);
|
||||
}
|
||||
definition.addQueryReturn(
|
||||
new NativeSQLQueryConstructorReturn( constructorResult.targetClass(), columnReturns )
|
||||
);
|
||||
}
|
||||
|
||||
if ( isDefault ) {
|
||||
mappings.addDefaultResultSetMapping( definition );
|
||||
}
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, 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.engine.query.spi.sql;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Describes a {@link javax.persistence.ConstructorResult}
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class NativeSQLQueryConstructorReturn implements NativeSQLQueryReturn {
|
||||
private final Class targetClass;
|
||||
private final NativeSQLQueryScalarReturn[] columnReturns;
|
||||
|
||||
public NativeSQLQueryConstructorReturn(Class targetClass, List<NativeSQLQueryScalarReturn> columnReturns) {
|
||||
this.targetClass = targetClass;
|
||||
this.columnReturns = columnReturns.toArray( new NativeSQLQueryScalarReturn[ columnReturns.size() ] );
|
||||
}
|
||||
|
||||
public Class getTargetClass() {
|
||||
return targetClass;
|
||||
}
|
||||
|
||||
public NativeSQLQueryScalarReturn[] getColumnReturns() {
|
||||
return columnReturns;
|
||||
}
|
||||
}
|
|
@ -42,6 +42,7 @@ import org.hibernate.ScrollMode;
|
|||
import org.hibernate.ScrollableResults;
|
||||
import org.hibernate.engine.ResultSetMappingDefinition;
|
||||
import org.hibernate.engine.query.spi.ParameterMetadata;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryConstructorReturn;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryJoinReturn;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryRootReturn;
|
||||
|
@ -205,6 +206,10 @@ public class SQLQueryImpl extends AbstractQueryImpl implements SQLQuery {
|
|||
break;
|
||||
}
|
||||
}
|
||||
else if ( NativeSQLQueryConstructorReturn.class.isInstance( queryReturn ) ) {
|
||||
autoDiscoverTypes = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, 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.loader.custom;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ConstructorReturn implements Return {
|
||||
private final Class targetClass;
|
||||
private final ScalarReturn[] scalars;
|
||||
|
||||
// private final Constructor constructor;
|
||||
|
||||
public ConstructorReturn(Class targetClass, ScalarReturn[] scalars) {
|
||||
this.targetClass = targetClass;
|
||||
this.scalars = scalars;
|
||||
|
||||
// constructor = resolveConstructor( targetClass, scalars );
|
||||
}
|
||||
|
||||
private static Constructor resolveConstructor(Class targetClass, ScalarReturn[] scalars) {
|
||||
for ( Constructor constructor : targetClass.getConstructors() ) {
|
||||
final Class[] argumentTypes = constructor.getParameterTypes();
|
||||
if ( argumentTypes.length != scalars.length ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean allMatched = true;
|
||||
for ( int i = 0; i < argumentTypes.length; i++ ) {
|
||||
if ( areAssignmentCompatible( argumentTypes[i], scalars[i].getType().getReturnedClass() ) ) {
|
||||
allMatched = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !allMatched ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return constructor;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException( "Could not locate appropriate constructor on class : " + targetClass.getName() );
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static boolean areAssignmentCompatible(Class argumentType, Class typeReturnedClass) {
|
||||
// todo : add handling for primitive/wrapper equivalents
|
||||
return argumentType.isAssignableFrom( typeReturnedClass );
|
||||
}
|
||||
|
||||
public Class getTargetClass() {
|
||||
return targetClass;
|
||||
}
|
||||
|
||||
public ScalarReturn[] getScalars() {
|
||||
return scalars;
|
||||
}
|
||||
|
||||
// public Constructor getConstructor() {
|
||||
// return constructor;
|
||||
// }
|
||||
}
|
|
@ -24,6 +24,8 @@
|
|||
package org.hibernate.loader.custom;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.ResultSetMetaData;
|
||||
import java.sql.SQLException;
|
||||
|
@ -139,6 +141,25 @@ public class CustomLoader extends Loader {
|
|||
includeInResultRowList.add( true );
|
||||
hasScalars = true;
|
||||
}
|
||||
else if ( ConstructorReturn.class.isInstance( rtn ) ) {
|
||||
final ConstructorReturn constructorReturn = (ConstructorReturn) rtn;
|
||||
resultTypes.add( null ); // this bit makes me nervous
|
||||
includeInResultRowList.add( true );
|
||||
hasScalars = true;
|
||||
|
||||
ScalarResultColumnProcessor[] scalarProcessors = new ScalarResultColumnProcessor[ constructorReturn.getScalars().length ];
|
||||
int i = 0;
|
||||
for ( ScalarReturn scalarReturn : constructorReturn.getScalars() ) {
|
||||
scalarProcessors[i++] = new ScalarResultColumnProcessor(
|
||||
StringHelper.unquote( scalarReturn.getColumnAlias(), factory.getDialect() ),
|
||||
scalarReturn.getType()
|
||||
);
|
||||
}
|
||||
|
||||
resultColumnProcessors.add(
|
||||
new ConstructorResultColumnProcessor( constructorReturn.getTargetClass(), scalarProcessors )
|
||||
);
|
||||
}
|
||||
else if ( rtn instanceof RootReturn ) {
|
||||
RootReturn rootRtn = ( RootReturn ) rtn;
|
||||
Queryable persister = ( Queryable ) factory.getEntityPersister( rootRtn.getEntityName() );
|
||||
|
@ -601,6 +622,90 @@ public class CustomLoader extends Loader {
|
|||
}
|
||||
}
|
||||
|
||||
public class ConstructorResultColumnProcessor implements ResultColumnProcessor {
|
||||
private final Class targetClass;
|
||||
private final ScalarResultColumnProcessor[] scalarProcessors;
|
||||
|
||||
private Constructor constructor;
|
||||
|
||||
public ConstructorResultColumnProcessor(Class targetClass, ScalarResultColumnProcessor[] scalarProcessors) {
|
||||
this.targetClass = targetClass;
|
||||
this.scalarProcessors = scalarProcessors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object extract(Object[] data, ResultSet resultSet, SessionImplementor session)
|
||||
throws SQLException, HibernateException {
|
||||
if ( constructor == null ) {
|
||||
throw new IllegalStateException( "Constructor to call was null" );
|
||||
}
|
||||
|
||||
final Object[] args = new Object[ scalarProcessors.length ];
|
||||
for ( int i = 0; i < scalarProcessors.length; i++ ) {
|
||||
args[i] = scalarProcessors[i].extract( data, resultSet, session );
|
||||
}
|
||||
|
||||
try {
|
||||
return constructor.newInstance( args );
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
throw new HibernateException(
|
||||
String.format( "Unable to call %s constructor", constructor.getDeclaringClass() ),
|
||||
e
|
||||
);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new HibernateException(
|
||||
String.format( "Unable to call %s constructor", constructor.getDeclaringClass() ),
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performDiscovery(Metadata metadata, List<Type> types, List<String> aliases) throws SQLException {
|
||||
final List<Type> localTypes = new ArrayList<Type>();
|
||||
for ( ScalarResultColumnProcessor scalar : scalarProcessors ) {
|
||||
scalar.performDiscovery( metadata, localTypes, aliases );
|
||||
}
|
||||
|
||||
types.addAll( localTypes );
|
||||
|
||||
constructor = resolveConstructor( targetClass, localTypes );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static Constructor resolveConstructor(Class targetClass, List<Type> types) {
|
||||
for ( Constructor constructor : targetClass.getConstructors() ) {
|
||||
final Class[] argumentTypes = constructor.getParameterTypes();
|
||||
if ( argumentTypes.length != types.size() ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean allMatched = true;
|
||||
for ( int i = 0; i < argumentTypes.length; i++ ) {
|
||||
if ( ! areAssignmentCompatible( argumentTypes[i], types.get( i ).getReturnedClass() ) ) {
|
||||
allMatched = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !allMatched ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return constructor;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException( "Could not locate appropriate constructor on class : " + targetClass.getName() );
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static boolean areAssignmentCompatible(Class argumentType, Class typeReturnedClass) {
|
||||
// todo : add handling for primitive/wrapper equivalents
|
||||
return argumentType.isAssignableFrom( typeReturnedClass );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void autoDiscoverTypes(ResultSet rs) {
|
||||
try {
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.jboss.logging.Logger;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryCollectionReturn;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryConstructorReturn;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryJoinReturn;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryNonScalarReturn;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
|
||||
|
@ -53,6 +54,7 @@ import org.hibernate.loader.GeneratedCollectionAliases;
|
|||
import org.hibernate.loader.custom.CollectionFetchReturn;
|
||||
import org.hibernate.loader.custom.CollectionReturn;
|
||||
import org.hibernate.loader.custom.ColumnCollectionAliases;
|
||||
import org.hibernate.loader.custom.ConstructorReturn;
|
||||
import org.hibernate.loader.custom.EntityFetchReturn;
|
||||
import org.hibernate.loader.custom.FetchReturn;
|
||||
import org.hibernate.loader.custom.NonScalarReturn;
|
||||
|
@ -353,6 +355,20 @@ public class SQLQueryReturnProcessor {
|
|||
customReturns.add( customReturn );
|
||||
customReturnsByAlias.put( alias, customReturn );
|
||||
}
|
||||
else if ( NativeSQLQueryConstructorReturn.class.isInstance( queryReturn ) ) {
|
||||
final NativeSQLQueryConstructorReturn constructorReturn = (NativeSQLQueryConstructorReturn) queryReturn;
|
||||
final ScalarReturn[] scalars = new ScalarReturn[ constructorReturn.getColumnReturns().length ];
|
||||
int i = 0;
|
||||
for ( NativeSQLQueryScalarReturn scalarReturn : constructorReturn.getColumnReturns() ) {
|
||||
scalars[i++] = new ScalarReturn( scalarReturn.getType(), scalarReturn.getColumnAlias() );
|
||||
}
|
||||
customReturns.add( new ConstructorReturn( constructorReturn.getTargetClass(), scalars ) );
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException(
|
||||
"Unrecognized NativeSQLQueryReturn concrete type : " + queryReturn
|
||||
);
|
||||
}
|
||||
}
|
||||
return customReturns;
|
||||
}
|
||||
|
@ -381,11 +397,23 @@ public class SQLQueryReturnProcessor {
|
|||
processRootReturn( ( NativeSQLQueryRootReturn ) rtn );
|
||||
}
|
||||
else if ( rtn instanceof NativeSQLQueryCollectionReturn ) {
|
||||
processCollectionReturn( ( NativeSQLQueryCollectionReturn ) rtn );
|
||||
processCollectionReturn( (NativeSQLQueryCollectionReturn) rtn );
|
||||
}
|
||||
else {
|
||||
else if ( NativeSQLQueryJoinReturn.class.isInstance( rtn ) ) {
|
||||
processJoinReturn( ( NativeSQLQueryJoinReturn ) rtn );
|
||||
}
|
||||
else if ( NativeSQLQueryConstructorReturn.class.isInstance( rtn ) ) {
|
||||
processConstructorReturn( (NativeSQLQueryConstructorReturn) rtn );
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException(
|
||||
"Unrecognized NativeSQLQueryReturn concrete type encountered : " + rtn
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void processConstructorReturn(NativeSQLQueryConstructorReturn rtn) {
|
||||
//To change body of created methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
private void processScalarReturn(NativeSQLQueryScalarReturn typeReturn) {
|
||||
|
|
|
@ -52,6 +52,7 @@ import org.hibernate.testing.RequiresDialect;
|
|||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
import org.hibernate.testing.junit4.ExtraAssertions;
|
||||
|
||||
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
|
@ -87,7 +88,7 @@ public class StoredProcedureResultSetMappingTest extends BaseUnitTestCase {
|
|||
public Employee() {
|
||||
}
|
||||
|
||||
public Employee(int id, String firstName, String lastName) {
|
||||
public Employee(Integer id, String firstName, String lastName) {
|
||||
this.id = id;
|
||||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
|
@ -142,8 +143,9 @@ public class StoredProcedureResultSetMappingTest extends BaseUnitTestCase {
|
|||
|
||||
ProcedureCall call = session.createStoredProcedureCall( "allEmployeeNames", "id-fname-lname" );
|
||||
ProcedureOutputs outputs = call.getOutputs();
|
||||
ResultSetOutput output = ExtraAssertions.assertTyping( ResultSetOutput.class, outputs.getCurrent() );
|
||||
ResultSetOutput output = assertTyping( ResultSetOutput.class, outputs.getCurrent() );
|
||||
assertEquals( 3, output.getResultList().size() );
|
||||
assertTyping( Employee.class, output.getResultList().get( 0 ) );
|
||||
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
|
|
@ -40,22 +40,13 @@ import java.util.List;
|
|||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
import org.hibernate.engine.spi.Mapping;
|
||||
import org.hibernate.jdbc.Work;
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
import org.hibernate.mapping.AuxiliaryDatabaseObject;
|
||||
import org.hibernate.procedure.ProcedureCall;
|
||||
import org.hibernate.procedure.ProcedureOutputs;
|
||||
import org.hibernate.result.ResultSetOutput;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.testing.RequiresDialect;
|
||||
import org.hibernate.testing.junit4.ExtraAssertions;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
|
@ -92,7 +83,7 @@ public class StoredProcedureResultSetMappingTest extends BaseEntityManagerFuncti
|
|||
public Employee() {
|
||||
}
|
||||
|
||||
public Employee(int id, String firstName, String lastName) {
|
||||
public Employee(Integer id, String firstName, String lastName) {
|
||||
this.id = id;
|
||||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, 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 javax.persistence.Column;
|
||||
import javax.persistence.ColumnResult;
|
||||
import javax.persistence.ConstructorResult;
|
||||
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 javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
|
||||
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ConstructorResultNativeQueryTest extends BaseEntityManagerFunctionalTestCase {
|
||||
@Entity( name = "Person" )
|
||||
@SqlResultSetMapping(
|
||||
name = "person-id-and-name",
|
||||
classes = {
|
||||
@ConstructorResult(
|
||||
targetClass = Person.class,
|
||||
columns = {
|
||||
@ColumnResult( name = "id" ),
|
||||
@ColumnResult( name = "p_name" )
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
@NamedNativeQuery(
|
||||
name = "person-id-and-name",
|
||||
query = "select p.id, p.p_name from person p order by p.p_name",
|
||||
resultSetMapping = "person-id-and-name"
|
||||
)
|
||||
public static class Person {
|
||||
@Id
|
||||
private Integer id;
|
||||
@Column( name = "p_name" )
|
||||
private String name;
|
||||
@Temporal( TemporalType.TIMESTAMP )
|
||||
private Date birthDate;
|
||||
|
||||
public Person() {
|
||||
}
|
||||
|
||||
public Person(Integer id, String name, Date birthDate) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.birthDate = birthDate;
|
||||
}
|
||||
|
||||
public Person(Integer id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] { Person.class };
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testConstructorResultNativeQuery() {
|
||||
EntityManager em = getOrCreateEntityManager();
|
||||
em.getTransaction().begin();
|
||||
em.persist( new Person( 1, "John", new Date() ) );
|
||||
em.getTransaction().commit();
|
||||
em.close();
|
||||
|
||||
em = getOrCreateEntityManager();
|
||||
em.getTransaction().begin();
|
||||
List results = em.createNativeQuery(
|
||||
"select p.id, p.p_name from person p order by p.p_name",
|
||||
"person-id-and-name"
|
||||
).getResultList();
|
||||
assertEquals( 1, results.size() );
|
||||
assertTyping( Person.class, results.get( 0 ) );
|
||||
em.getTransaction().commit();
|
||||
em.close();
|
||||
|
||||
em = getOrCreateEntityManager();
|
||||
em.getTransaction().begin();
|
||||
em.createQuery( "delete from Person" ).executeUpdate();
|
||||
em.getTransaction().commit();
|
||||
em.close();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue