HHH-10915 - NullPointerException from AbstractProducedQuery.getParameters()

This commit is contained in:
Andrea Boriero 2016-07-02 09:36:36 +02:00 committed by Vlad Mihalcea
parent 26df5d9e11
commit 5e69823b79
5 changed files with 318 additions and 26 deletions

View File

@ -51,6 +51,8 @@ import org.hibernate.procedure.spi.ParameterStrategy;
import org.hibernate.procedure.spi.ProcedureCallImplementor; import org.hibernate.procedure.spi.ProcedureCallImplementor;
import org.hibernate.query.QueryParameter; import org.hibernate.query.QueryParameter;
import org.hibernate.query.internal.AbstractProducedQuery; import org.hibernate.query.internal.AbstractProducedQuery;
import org.hibernate.query.procedure.internal.ProcedureParameterImpl;
import org.hibernate.query.procedure.internal.ProcedureParameterMetadata;
import org.hibernate.result.NoMoreReturnsException; import org.hibernate.result.NoMoreReturnsException;
import org.hibernate.result.Output; import org.hibernate.result.Output;
import org.hibernate.result.ResultSetOutput; import org.hibernate.result.ResultSetOutput;
@ -94,7 +96,7 @@ public class ProcedureCallImpl<R>
* @param procedureName The name of the procedure to call * @param procedureName The name of the procedure to call
*/ */
public ProcedureCallImpl(SharedSessionContractImplementor session, String procedureName) { public ProcedureCallImpl(SharedSessionContractImplementor session, String procedureName) {
super( session, null ); super( session, new ProcedureParameterMetadata() );
this.procedureName = procedureName; this.procedureName = procedureName;
this.globalParameterPassNullsSetting = session.getFactory().getSessionFactoryOptions().isProcedureParameterNullPassingEnabled(); this.globalParameterPassNullsSetting = session.getFactory().getSessionFactoryOptions().isProcedureParameterNullPassingEnabled();
@ -109,7 +111,7 @@ public class ProcedureCallImpl<R>
* @param resultClasses The classes making up the result * @param resultClasses The classes making up the result
*/ */
public ProcedureCallImpl(final SharedSessionContractImplementor session, String procedureName, Class... resultClasses) { public ProcedureCallImpl(final SharedSessionContractImplementor session, String procedureName, Class... resultClasses) {
super( session, null ); super( session, new ProcedureParameterMetadata() );
this.procedureName = procedureName; this.procedureName = procedureName;
this.globalParameterPassNullsSetting = session.getFactory().getSessionFactoryOptions().isProcedureParameterNullPassingEnabled(); this.globalParameterPassNullsSetting = session.getFactory().getSessionFactoryOptions().isProcedureParameterNullPassingEnabled();
@ -148,7 +150,7 @@ public class ProcedureCallImpl<R>
* @param resultSetMappings The names of the result set mappings making up the result * @param resultSetMappings The names of the result set mappings making up the result
*/ */
public ProcedureCallImpl(final SharedSessionContractImplementor session, String procedureName, String... resultSetMappings) { public ProcedureCallImpl(final SharedSessionContractImplementor session, String procedureName, String... resultSetMappings) {
super( session, null ); super( session, new ProcedureParameterMetadata() );
this.procedureName = procedureName; this.procedureName = procedureName;
this.globalParameterPassNullsSetting = session.getFactory().getSessionFactoryOptions().isProcedureParameterNullPassingEnabled(); this.globalParameterPassNullsSetting = session.getFactory().getSessionFactoryOptions().isProcedureParameterNullPassingEnabled();
@ -192,7 +194,7 @@ public class ProcedureCallImpl<R>
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
ProcedureCallImpl(SharedSessionContractImplementor session, ProcedureCallMementoImpl memento) { ProcedureCallImpl(SharedSessionContractImplementor session, ProcedureCallMementoImpl memento) {
super( session, null ); super( session, new ProcedureParameterMetadata() );
this.procedureName = memento.getProcedureName(); this.procedureName = memento.getProcedureName();
this.globalParameterPassNullsSetting = session.getFactory().getSessionFactoryOptions().isProcedureParameterNullPassingEnabled(); this.globalParameterPassNullsSetting = session.getFactory().getSessionFactoryOptions().isProcedureParameterNullPassingEnabled();
@ -250,6 +252,7 @@ public class ProcedureCallImpl<R>
storedRegistration.isPassNullsEnabled() storedRegistration.isPassNullsEnabled()
); );
} }
getParameterMetadata().registerParameter( new ProcedureParameterImpl( registration ) );
parameterRegistrations.add( registration ); parameterRegistrations.add( registration );
} }
this.registeredParameters = parameterRegistrations; this.registeredParameters = parameterRegistrations;
@ -259,6 +262,11 @@ public class ProcedureCallImpl<R>
} }
} }
@Override
public ProcedureParameterMetadata getParameterMetadata() {
return (ProcedureParameterMetadata) super.getParameterMetadata();
}
@Override @Override
public SharedSessionContractImplementor getSession() { public SharedSessionContractImplementor getSession() {
return getProducer(); return getProducer();
@ -286,6 +294,7 @@ public class ProcedureCallImpl<R>
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> ParameterRegistration<T> registerParameter(int position, Class<T> type, ParameterMode mode) { public <T> ParameterRegistration<T> registerParameter(int position, Class<T> type, ParameterMode mode) {
final PositionalParameterRegistration parameterRegistration = final PositionalParameterRegistration parameterRegistration =
new PositionalParameterRegistration( this, position, mode, type, globalParameterPassNullsSetting ); new PositionalParameterRegistration( this, position, mode, type, globalParameterPassNullsSetting );
registerParameter( parameterRegistration ); registerParameter( parameterRegistration );
@ -309,6 +318,8 @@ public class ProcedureCallImpl<R>
else { else {
throw new IllegalArgumentException( "Given parameter did not define name or position [" + parameter + "]" ); throw new IllegalArgumentException( "Given parameter did not define name or position [" + parameter + "]" );
} }
((ProcedureParameterMetadata)getParameterMetadata()).registerParameter( new ProcedureParameterImpl( parameter ) );
registeredParameters.add( parameter ); registeredParameters.add( parameter );
} }

View File

@ -44,6 +44,7 @@ import org.hibernate.LockMode;
import org.hibernate.LockOptions; import org.hibernate.LockOptions;
import org.hibernate.NonUniqueResultException; import org.hibernate.NonUniqueResultException;
import org.hibernate.PropertyNotFoundException; import org.hibernate.PropertyNotFoundException;
import org.hibernate.QueryParameterException;
import org.hibernate.ScrollMode; import org.hibernate.ScrollMode;
import org.hibernate.TypeMismatchException; import org.hibernate.TypeMismatchException;
import org.hibernate.engine.query.spi.EntityGraphQueryHint; import org.hibernate.engine.query.spi.EntityGraphQueryHint;
@ -617,13 +618,13 @@ public abstract class AbstractProducedQuery<R> implements QueryImplementor<R> {
@Override @Override
public Set<Parameter<?>> getParameters() { public Set<Parameter<?>> getParameters() {
return parameterMetadata.collectAllParametersJpa(); return getParameterMetadata().collectAllParametersJpa();
} }
@Override @Override
public Parameter<?> getParameter(String name) { public Parameter<?> getParameter(String name) {
try { try {
return parameterMetadata.getQueryParameter( name ); return getParameterMetadata().getQueryParameter( name );
} }
catch ( HibernateException e ) { catch ( HibernateException e ) {
throw getExceptionConverter().convert( e ); throw getExceptionConverter().convert( e );
@ -634,7 +635,7 @@ public abstract class AbstractProducedQuery<R> implements QueryImplementor<R> {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> Parameter<T> getParameter(String name, Class<T> type) { public <T> Parameter<T> getParameter(String name, Class<T> type) {
try { try {
final QueryParameter parameter = parameterMetadata.getQueryParameter( name ); final QueryParameter parameter = getParameterMetadata().getQueryParameter( name );
if ( !parameter.getParameterType().isAssignableFrom( type ) ) { if ( !parameter.getParameterType().isAssignableFrom( type ) ) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"The type [" + parameter.getParameterType().getName() + "The type [" + parameter.getParameterType().getName() +
@ -657,20 +658,25 @@ public abstract class AbstractProducedQuery<R> implements QueryImplementor<R> {
// deprecated since 5.x. These are numbered starting from 0 and kept in the // deprecated since 5.x. These are numbered starting from 0 and kept in the
// ParameterMetadata positional-parameter array keyed by this zero-based position // ParameterMetadata positional-parameter array keyed by this zero-based position
// 2) JPA's definition is really just a named parameter, but expected to explicitly be // 2) JPA's definition is really just a named parameter, but expected to explicitly be
// sequential intergers starting from 0 (ZERO); they can repeat. // sequential integers starting from 1 (ONE); they can repeat.
// //
// It is considered illegal to mix positional-parameter with named parameters of any kind. So therefore. // It is considered illegal to mix positional-parameter with named parameters of any kind. So therefore.
// if ParameterMetadata reports that it has any positional-parameters it is talking about the // if ParameterMetadata reports that it has any positional-parameters it is talking about the
// legacy Hibernate concept. // legacy Hibernate concept.
// lookup jpa-based positional parameters first by name. // lookup jpa-based positional parameters first by name.
try { try {
if ( parameterMetadata.getPositionalParameterCount() == 0 ) { if ( getParameterMetadata().getPositionalParameterCount() == 0 ) {
return parameterMetadata.getQueryParameter( Integer.toString( position ) ); try {
return getParameterMetadata().getQueryParameter( Integer.toString( position ) );
}
catch (HibernateException e) {
throw new QueryParameterException( "could not locate parameter at position [" + position + "]" );
}
} }
// fallback to oridinal lookup // fallback to ordinal lookup
return parameterMetadata.getQueryParameter( position ); return getParameterMetadata().getQueryParameter( position );
} }
catch ( HibernateException e ) { catch (HibernateException e) {
throw getExceptionConverter().convert( e ); throw getExceptionConverter().convert( e );
} }
} }
@ -679,7 +685,7 @@ public abstract class AbstractProducedQuery<R> implements QueryImplementor<R> {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> Parameter<T> getParameter(int position, Class<T> type) { public <T> Parameter<T> getParameter(int position, Class<T> type) {
try { try {
final QueryParameter parameter = parameterMetadata.getQueryParameter( position ); final QueryParameter parameter = getParameterMetadata().getQueryParameter( position );
if ( !parameter.getParameterType().isAssignableFrom( type ) ) { if ( !parameter.getParameterType().isAssignableFrom( type ) ) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"The type [" + parameter.getParameterType().getName() + "The type [" + parameter.getParameterType().getName() +
@ -750,7 +756,7 @@ public abstract class AbstractProducedQuery<R> implements QueryImplementor<R> {
protected Type determineType(String namedParam, Class retType) { protected Type determineType(String namedParam, Class retType) {
Type type = queryParameterBindings.getBinding( namedParam ).getBindType(); Type type = queryParameterBindings.getBinding( namedParam ).getBindType();
if ( type == null ) { if ( type == null ) {
type = parameterMetadata.getQueryParameter( namedParam ).getType(); type = getParameterMetadata().getQueryParameter( namedParam ).getType();
} }
if ( type == null ) { if ( type == null ) {
type = getProducer().getFactory().resolveParameterBindType( retType ); type = getProducer().getFactory().resolveParameterBindType( retType );

View File

@ -13,6 +13,7 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import javax.persistence.Parameter; import javax.persistence.Parameter;
import org.hibernate.QueryParameterException;
import org.hibernate.query.ParameterMetadata; import org.hibernate.query.ParameterMetadata;
import org.hibernate.query.QueryParameter; import org.hibernate.query.QueryParameter;
import org.hibernate.query.procedure.ProcedureParameter; import org.hibernate.query.procedure.ProcedureParameter;
@ -27,6 +28,10 @@ public class ProcedureParameterMetadata implements ParameterMetadata {
private boolean hasNamed; private boolean hasNamed;
private int ordinalParamCount; private int ordinalParamCount;
public ProcedureParameterMetadata() {
parameters = new ArrayList<>( );
}
public void registerParameter(ProcedureParameterImplementor parameter) { public void registerParameter(ProcedureParameterImplementor parameter) {
if ( parameters == null ) { if ( parameters == null ) {
parameters = new ArrayList<>(); parameters = new ArrayList<>();
@ -91,16 +96,19 @@ public class ProcedureParameterMetadata implements ParameterMetadata {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> QueryParameter<T> getQueryParameter(String name) { public <T> QueryParameter<T> getQueryParameter(String name) {
assert name != null; assert name != null;
QueryParameter<T> result = null;
if ( hasNamed ) { if ( hasNamed ) {
for ( ProcedureParameter parameter : parameters ) { for ( ProcedureParameter parameter : parameters ) {
if ( name.equals( parameter.getName() ) ) { if ( name.equals( parameter.getName() ) ) {
return parameter; result = parameter;
break;
} }
} }
} }
if ( result != null ) {
return null; return result;
}
throw new QueryParameterException( "could not locate named parameter [" + name + "]" );
} }
@Override @Override
@ -115,8 +123,7 @@ public class ProcedureParameterMetadata implements ParameterMetadata {
} }
} }
} }
throw new QueryParameterException( "could not locate parameter at position [" + position + "]" );
return null;
} }
@Override @Override

View File

@ -0,0 +1,159 @@
/*
* 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.jpa.test.procedure;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.Id;
import javax.persistence.Parameter;
import javax.persistence.ParameterMode;
import javax.persistence.StoredProcedureQuery;
import javax.persistence.Table;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Set;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.hibernate.testing.RequiresDialect;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNot.not;
import static org.hamcrest.core.IsNull.nullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
/**
* @author Andrea Boriero
*/
@RequiresDialect(H2Dialect.class)
public class H2StoreProcedureTest extends BaseEntityManagerFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] {MyEntity.class};
}
@Before
public void setUp() {
final EntityManager entityManager = getOrCreateEntityManager();
try {
entityManager.getTransaction().begin();
entityManager.createNativeQuery( "CREATE ALIAS get_all_entities FOR \"" + H2StoreProcedureTest.class.getCanonicalName() + ".getAllEntities\";" )
.executeUpdate();
entityManager.createNativeQuery( "CREATE ALIAS by_id FOR \"" + H2StoreProcedureTest.class.getCanonicalName() + ".entityById\";" )
.executeUpdate();
MyEntity entity = new MyEntity();
entity.id = 1;
entity.name = "entity1";
entityManager.persist( entity );
entityManager.getTransaction().commit();
}
catch (Exception e) {
if ( entityManager.getTransaction().isActive() ) {
entityManager.getTransaction().rollback();
}
throw e;
}
finally {
entityManager.close();
}
}
@After
public void tearDown() {
final EntityManager entityManager = getOrCreateEntityManager();
try {
entityManager.getTransaction().begin();
entityManager.createNativeQuery( "DROP ALIAS IF EXISTS get_all_entities" ).executeUpdate();
entityManager.createNativeQuery( "DROP ALIAS IF EXISTS by_id" ).executeUpdate();
entityManager.getTransaction().commit();
}
catch (Exception e) {
if ( entityManager.getTransaction().isActive() ) {
entityManager.getTransaction().rollback();
}
throw e;
}
finally {
entityManager.close();
}
}
public static ResultSet getAllEntities(Connection conn) throws SQLException {
return conn.createStatement().executeQuery( "select * from MY_ENTITY" );
}
public static ResultSet entityById(Connection conn, long id) throws SQLException {
return conn.createStatement().executeQuery( "select * from MY_ENTITY where id = " + Long.toString( id ) );
}
@Test
public void testStoreProcedureGetParameters() {
final EntityManager entityManager = getOrCreateEntityManager();
try {
StoredProcedureQuery query = entityManager.createStoredProcedureQuery( "get_all_entities", MyEntity.class );
final Set<Parameter<?>> parameters = query.getParameters();
assertThat( parameters.size(), is( 0 ) );
final List resultList = query.getResultList();
assertThat( resultList.size(), is( 1 ) );
}
finally {
entityManager.close();
}
}
@Test
public void testStoreProcedureGetParameterByPosition() {
final EntityManager entityManager = getOrCreateEntityManager();
try {
StoredProcedureQuery query = entityManager.createStoredProcedureQuery( "by_Id", MyEntity.class );
query.registerStoredProcedureParameter( 1, Long.class, ParameterMode.IN );
query.setParameter( 1, 1L );
final List resultList = query.getResultList();
assertThat( resultList.size(), is( 1 ) );
final Set<Parameter<?>> parameters = query.getParameters();
assertThat( parameters.size(), is( 1 ) );
final Parameter<?> parameter = query.getParameter( 1 );
assertThat( parameter, not( nullValue() ) );
try {
query.getParameter( 2 );
fail( "IllegalArgumentException expected, parameter at position 2 does not exist" );
}
catch (IllegalArgumentException iae) {
//expected
}
}
finally {
entityManager.close();
}
}
@Entity(name = "MyEntity")
@Table(name = "MY_ENTITY")
public static class MyEntity {
@Id
long id;
String name;
}
}

View File

@ -11,7 +11,9 @@ import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory; import javax.persistence.EntityManagerFactory;
import javax.persistence.GeneratedValue; import javax.persistence.GeneratedValue;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.NamedStoredProcedureQueries;
import javax.persistence.NamedStoredProcedureQuery; import javax.persistence.NamedStoredProcedureQuery;
import javax.persistence.Parameter;
import javax.persistence.ParameterMode; import javax.persistence.ParameterMode;
import javax.persistence.StoredProcedureParameter; import javax.persistence.StoredProcedureParameter;
import javax.persistence.StoredProcedureQuery; import javax.persistence.StoredProcedureQuery;
@ -19,6 +21,7 @@ import javax.persistence.Table;
import java.sql.Connection; import java.sql.Connection;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import java.util.Set;
import org.hibernate.dialect.HSQLDialect; import org.hibernate.dialect.HSQLDialect;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess; import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
@ -27,18 +30,22 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.junit.After; import org.junit.After;
import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNot.not;
import static org.hamcrest.core.IsNull.nullValue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
/** /**
* @author Andrea Boriero * @author Andrea Boriero
*/ */
@TestForIssue(jiraKey = "HHH-10515")
@RequiresDialect(value = HSQLDialect.class) @RequiresDialect(value = HSQLDialect.class)
public class HSQLStoreProcedureTest extends BaseEntityManagerFunctionalTestCase { public class HSQLStoreProcedureTest extends BaseEntityManagerFunctionalTestCase {
EntityManagerFactory entityManagerFactory; EntityManagerFactory entityManagerFactory;
@ -61,6 +68,7 @@ public class HSQLStoreProcedureTest extends BaseEntityManagerFunctionalTestCase
} }
@Test @Test
@TestForIssue(jiraKey = "HHH-10515")
public void testNamedStoredProcedureExecution() { public void testNamedStoredProcedureExecution() {
EntityManager em = entityManagerFactory.createEntityManager(); EntityManager em = entityManagerFactory.createEntityManager();
try { try {
@ -73,6 +81,99 @@ public class HSQLStoreProcedureTest extends BaseEntityManagerFunctionalTestCase
} }
} }
@Test
@TestForIssue(jiraKey = "HHH-10915")
public void testGetNamedParameters() {
EntityManager em = entityManagerFactory.createEntityManager();
try {
StoredProcedureQuery query = em.createNamedStoredProcedureQuery( "User.inoutproc" );
final Set<Parameter<?>> parameters = query.getParameters();
assertThat( parameters.size(), is( 2 ) );
assertThat( query.getParameter( "arg1" ), not( nullValue() ) );
assertThat( query.getParameter( "res" ), not( nullValue() ) );
assertThat( query.getParameter( "arg1", Integer.class ), not( nullValue() ) );
try {
query.getParameter( "arg1", String.class );
fail( "An IllegalArgumentException is expected, A parameter with name arg1 and type String does not exist" );
}
catch (IllegalArgumentException iae) {
//expected
}
try {
query.getParameter( "arg2" );
fail( "An IllegalArgumentException is expected, A parameter with name arg2 does not exist" );
}
catch (IllegalArgumentException iae) {
//expected
}
}
finally {
em.close();
}
}
@Test
@TestForIssue(jiraKey = "HHH-10915")
public void testGetPositionalParameters() {
EntityManager em = entityManagerFactory.createEntityManager();
try {
StoredProcedureQuery query = em.createNamedStoredProcedureQuery( "User.inoutproc" );
final Set<Parameter<?>> parameters = query.getParameters();
assertThat( parameters.size(), is( 2 ) );
try {
query.getParameter( 1 );
fail( "An IllegalArgumentException is expected, The stored procedure has named parameters not positional" );
}
catch (IllegalArgumentException iae) {
//expected
}
try {
query.getParameter( 1, String.class );
fail( "An IllegalArgumentException is expected, The stored procedure has named parameters not positional" );
}
catch (IllegalArgumentException iae) {
//expected
}
}
finally {
em.close();
}
}
@Test
@TestForIssue(jiraKey = "HHH-10915")
public void testGetPositionalParameters2() {
EntityManager em = entityManagerFactory.createEntityManager();
try {
StoredProcedureQuery query = em.createNamedStoredProcedureQuery( "User.inoutprocpositional" );
final Set<Parameter<?>> parameters = query.getParameters();
assertThat( parameters.size(), is( 2 ) );
assertThat( query.getParameter( 1 ), not( nullValue() ) );
assertThat( query.getParameter( 2 ), not( nullValue() ) );
assertThat( query.getParameter( 1, Integer.class ), not( nullValue() ) );
try {
query.getParameter( 3 );
fail( "An IllegalArgumentException is expected, A parameter at position 3 does not exist" );
}
catch (IllegalArgumentException iae) {
//expected
}
try {
query.getParameter( 1, String.class );
fail( "An IllegalArgumentException is expected, The parameter at position 1 is of type Integer not String" );
}
catch (IllegalArgumentException iae) {
//expected
}
}
finally {
em.close();
}
}
private void createProcedures(EntityManagerFactory emf) { private void createProcedures(EntityManagerFactory emf) {
final String procedureStatement = "CREATE procedure inoutproc (IN arg1 int, OUT res int) " + final String procedureStatement = "CREATE procedure inoutproc (IN arg1 int, OUT res int) " +
"BEGIN ATOMIC set res = arg1 + 1;" + "BEGIN ATOMIC set res = arg1 + 1;" +
@ -127,10 +228,18 @@ public class HSQLStoreProcedureTest extends BaseEntityManagerFunctionalTestCase
} }
@Entity(name = "User") @Entity(name = "User")
@NamedStoredProcedureQuery(name = "User.inoutproc", procedureName = "inoutproc", parameters = { @NamedStoredProcedureQueries(value = {
@StoredProcedureParameter(mode = ParameterMode.IN, name = "arg1", type = Integer.class), @NamedStoredProcedureQuery(name = "User.inoutproc", procedureName = "inoutproc", parameters = {
@StoredProcedureParameter(mode = ParameterMode.OUT, name = "res", type = Integer.class) @StoredProcedureParameter(mode = ParameterMode.IN, name = "arg1", type = Integer.class),
}) @StoredProcedureParameter(mode = ParameterMode.OUT, name = "res", type = Integer.class)
})
,
@NamedStoredProcedureQuery(name = "User.inoutprocpositional", procedureName = "inoutproc", parameters = {
@StoredProcedureParameter(mode = ParameterMode.IN, type = Integer.class),
@StoredProcedureParameter(mode = ParameterMode.OUT, type = Integer.class)
})
}
)
@Table(name = "USERS") @Table(name = "USERS")
public class User { public class User {