/*
* 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.EntityManagerFactory;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.NamedStoredProcedureQueries;
import javax.persistence.NamedStoredProcedureQuery;
import javax.persistence.Parameter;
import javax.persistence.ParameterMode;
import javax.persistence.StoredProcedureParameter;
import javax.persistence.StoredProcedureQuery;
import javax.persistence.Table;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Set;
import org.hibernate.dialect.HSQLDialect;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.hibernate.testing.RequiresDialect;
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;
/**
* @author Andrea Boriero
*/
@RequiresDialect(value = HSQLDialect.class)
public class HSQLStoreProcedureTest extends BaseEntityManagerFunctionalTestCase {
EntityManagerFactory entityManagerFactory;
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] {User.class};
}
@Before
public void startUp() {
entityManagerFactory = getOrCreateEntityManager().getEntityManagerFactory();
createProcedures( entityManagerFactory );
}
@After
public void tearDown() {
dropProcedures( entityManagerFactory );
}
@Test
@TestForIssue(jiraKey = "HHH-10515")
public void testNamedStoredProcedureExecution() {
EntityManager em = entityManagerFactory.createEntityManager();
try {
StoredProcedureQuery query = em.createNamedStoredProcedureQuery( "User.inoutproc" );
query.setParameter( "arg1", 1 );
query.execute();
}
finally {
em.close();
}
}
@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) {
final String procedureStatement = "CREATE procedure inoutproc (IN arg1 int, OUT res int) " +
"BEGIN ATOMIC set res = arg1 + 1;" +
"END";
executeStatement( emf, procedureStatement );
}
private void dropProcedures(EntityManagerFactory emf) {
executeStatement( emf, "DROP procedure inoutproc" );
}
public void executeStatement(EntityManagerFactory emf, String toExecute) {
final SessionFactoryImplementor sf = emf.unwrap( SessionFactoryImplementor.class );
final JdbcConnectionAccess connectionAccess = sf.getServiceRegistry()
.getService( JdbcServices.class )
.getBootstrapJdbcConnectionAccess();
final Connection conn;
try {
conn = connectionAccess.obtainConnection();
conn.setAutoCommit( false );
try {
Statement statement = conn.createStatement();
statement.execute( toExecute );
try {
statement.close();
}
catch (SQLException e) {
fail( e.getMessage() );
}
}
finally {
try {
conn.commit();
}
catch (SQLException e) {
fail( e.getMessage() );
}
try {
connectionAccess.releaseConnection( conn );
}
catch (SQLException e) {
fail( e.getMessage() );
}
}
}
catch (SQLException e) {
throw new RuntimeException( "Unable to create stored procedures", e );
}
}
@Entity(name = "User")
@NamedStoredProcedureQueries(value = {
@NamedStoredProcedureQuery(name = "User.inoutproc", procedureName = "inoutproc", parameters = {
@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")
public class User {
@Id
@GeneratedValue
private Integer id;
}
}