HHH-8022 - Reading REF CURSOR
This commit is contained in:
parent
9edc30f9f0
commit
c69fde0c6d
|
@ -44,6 +44,11 @@ public class ResultSetReturnImpl implements ResultSetReturn {
|
|||
@Override
|
||||
public ResultSet extract(PreparedStatement statement) {
|
||||
// sql logged by StatementPreparerImpl
|
||||
if ( statement instanceof CallableStatement ) {
|
||||
// we actually need to extract from callable statement
|
||||
CallableStatement callableStatement = (CallableStatement) statement;
|
||||
return extract( callableStatement );
|
||||
}
|
||||
try {
|
||||
ResultSet rs = statement.executeQuery();
|
||||
postExtract( rs );
|
||||
|
|
|
@ -40,7 +40,8 @@ import java.sql.Statement;
|
|||
public interface ResultSetReturn {
|
||||
|
||||
/**
|
||||
* Extract the ResultSet from the statement.
|
||||
* Extract the ResultSet from the statement. If user passes {@link CallableStatement}
|
||||
* reference, method calls {@link #extract(CallableStatement)} internally.
|
||||
*
|
||||
* @param statement
|
||||
*
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
package org.hibernate.test.sql.refcursor;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* @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();
|
||||
}
|
||||
|
||||
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 ).getTransactionCoordinator().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.release( preparedStatement );
|
||||
}
|
||||
catch ( Throwable ignore ) {
|
||||
// ignore...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
package org.hibernate.test.sql.refcursor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.NamedNativeQueries;
|
||||
import javax.persistence.NamedNativeQuery;
|
||||
import javax.persistence.QueryHint;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "BOT_NUMVALUE")
|
||||
@NamedNativeQueries({
|
||||
@NamedNativeQuery(name = "NumValue.getSomeValues",
|
||||
query = "{ ? = call f_test_return_cursor() }",
|
||||
resultClass = NumValue.class, hints = { @QueryHint(name = "org.hibernate.callable", value = "true") })
|
||||
})
|
||||
public class NumValue implements Serializable {
|
||||
@Id
|
||||
@Column(name = "BOT_NUM", nullable = false)
|
||||
private long num;
|
||||
|
||||
@Column(name = "BOT_VALUE")
|
||||
private String value;
|
||||
|
||||
public NumValue() {
|
||||
}
|
||||
|
||||
public NumValue(long num, String value) {
|
||||
this.num = num;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) return true;
|
||||
if ( !( o instanceof NumValue ) ) return false;
|
||||
|
||||
NumValue numValue = (NumValue) o;
|
||||
|
||||
if ( num != numValue.num ) return false;
|
||||
if ( value != null ? !value.equals( numValue.value ) : numValue.value != null ) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = (int) ( num ^ ( num >>> 32 ) );
|
||||
result = 31 * result + ( value != null ? value.hashCode() : 0 );
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NumValue(num = " + num + ", value = " + value + ")";
|
||||
}
|
||||
|
||||
public long getNum() {
|
||||
return num;
|
||||
}
|
||||
|
||||
public void setNum(long num) {
|
||||
this.num = num;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue