/*
* 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.test.sql.refcursor;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Arrays;
import org.hibernate.Session;
import org.hibernate.dialect.Oracle8iDialect;
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
import org.hibernate.engine.jdbc.spi.ResultSetReturn;
import org.hibernate.engine.jdbc.spi.StatementPreparer;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.jdbc.Work;
import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
*/
@RequiresDialect( Oracle8iDialect.class )
public class CursorFromCallableTest extends BaseCoreFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { NumValue.class };
}
@Before
public void createRefCursorFunction() {
executeStatement( "CREATE OR REPLACE FUNCTION f_test_return_cursor RETURN SYS_REFCURSOR " +
"IS " +
" l_Cursor SYS_REFCURSOR; " +
"BEGIN " +
" OPEN l_Cursor FOR " +
" SELECT 1 AS BOT_NUM " +
" , 'Line 1' AS BOT_VALUE " +
" FROM DUAL " +
" UNION " +
" SELECT 2 AS BOT_NUM " +
" , 'Line 2' AS BOT_VALUE " +
" FROM DUAL; " +
" RETURN(l_Cursor); " +
"END f_test_return_cursor;" );
}
@After
public void dropRefCursorFunction() {
executeStatement( "DROP FUNCTION f_test_return_cursor" );
}
@Test
@TestForIssue( jiraKey = "HHH-8022" )
public void testReadResultSetFromRefCursor() {
Session session = openSession();
session.getTransaction().begin();
Assert.assertEquals(
Arrays.asList( new NumValue( 1, "Line 1" ), new NumValue( 2, "Line 2" ) ),
session.getNamedQuery( "NumValue.getSomeValues" ).list()
);
session.getTransaction().commit();
session.close();
}
@Test
@TestForIssue( jiraKey = "HHH-7984" )
public void testStatementClosing() {
Session session = openSession();
session.getTransaction().begin();
// Reading maximum number of opened cursors requires SYS privileges.
// Verify statement closing with JdbcCoordinator#hasRegisteredResources() instead.
// BigDecimal maxCursors = (BigDecimal) session.createSQLQuery( "SELECT value FROM v$parameter WHERE name = 'open_cursors'" ).uniqueResult();
// for ( int i = 0; i < maxCursors + 10; ++i ) { named_query_execution }
Assert.assertEquals(
Arrays.asList( new NumValue( 1, "Line 1" ), new NumValue( 2, "Line 2" ) ),
session.getNamedQuery( "NumValue.getSomeValues" ).list()
);
JdbcCoordinator jdbcCoordinator = ( (SessionImplementor) session ).getJdbcCoordinator();
Assert.assertFalse(
"Prepared statement and result set should be released after query execution.",
jdbcCoordinator.getResourceRegistry().hasRegisteredResources()
);
session.getTransaction().commit();
session.close();
}
private void executeStatement(final String sql) {
final Session session = openSession();
session.getTransaction().begin();
session.doWork( new Work() {
@Override
public void execute(Connection connection) throws SQLException {
final JdbcCoordinator jdbcCoordinator = ( (SessionImplementor) session ).getJdbcCoordinator();
final StatementPreparer statementPreparer = jdbcCoordinator.getStatementPreparer();
final ResultSetReturn resultSetReturn = jdbcCoordinator.getResultSetReturn();
PreparedStatement preparedStatement = null;
try {
preparedStatement = statementPreparer.prepareStatement( sql );
resultSetReturn.execute( preparedStatement );
}
finally {
if ( preparedStatement != null ) {
try {
jdbcCoordinator.getResourceRegistry().release( preparedStatement );
}
catch ( Throwable ignore ) {
// ignore...
}
}
}
}
} );
session.getTransaction().commit();
session.close();
}
}