3535import org .junit .jupiter .api .BeforeEach ;
3636import org .junit .jupiter .api .Test ;
3737
38+ import jakarta .persistence .Column ;
3839import jakarta .persistence .Entity ;
3940import jakarta .persistence .Id ;
4041import jakarta .persistence .NamedStoredProcedureQueries ;
4142import jakarta .persistence .NamedStoredProcedureQuery ;
4243import jakarta .persistence .ParameterMode ;
4344import jakarta .persistence .StoredProcedureParameter ;
4445import jakarta .persistence .StoredProcedureQuery ;
46+ import jakarta .persistence .Table ;
4547import org .assertj .core .api .Assertions ;
4648
4749import static org .hamcrest .MatcherAssert .assertThat ;
50+ import static org .hamcrest .core .Is .is ;
4851import static org .junit .jupiter .api .Assertions .assertEquals ;
4952import static org .junit .jupiter .api .Assertions .assertFalse ;
5053import static org .junit .jupiter .api .Assertions .assertNotNull ;
54+ import static org .junit .jupiter .api .Assertions .assertTrue ;
5155import static org .junit .jupiter .api .Assertions .fail ;
5256
5357
5963 Person .class ,
6064 Phone .class ,
6165 OracleStoredProcedureTest .IdHolder .class ,
62- Vote .class
66+ Vote .class ,
67+ OracleStoredProcedureTest .Address .class
6368 }
6469)
6570@ RequiresDialect (value = OracleDialect .class )
@@ -86,6 +91,43 @@ public void testUnRegisteredParameter(EntityManagerFactoryScope scope) {
8691 } );
8792 }
8893
94+ @ Test
95+ @ TestForIssue (jiraKey = "HHH-15542" )
96+ public void testStoredProcedureInAndOutAndRefCursorParameters (EntityManagerFactoryScope scope ) {
97+ String city = "London" ;
98+ String street = "Lollard Street" ;
99+ String zip = "SE116UG" ;
100+ scope .inTransaction (
101+ entityManager -> {
102+ Address address = new Address ( 1l , street , city , zip );
103+ entityManager .persist ( address );
104+ }
105+ );
106+ scope .inTransaction (
107+ entityManager -> {
108+ StoredProcedureQuery query = entityManager .createStoredProcedureQuery ( "GET_ADDRESS_BY_NAME" );
109+ query .registerStoredProcedureParameter ( "street_in" , String .class , ParameterMode .IN );
110+ query .registerStoredProcedureParameter ( "city_in" , String .class , ParameterMode .IN );
111+ query .registerStoredProcedureParameter ( "rec_out" , ResultSet .class , ParameterMode .REF_CURSOR );
112+ query .registerStoredProcedureParameter ( "err_out" , String .class , ParameterMode .OUT );
113+
114+ query .setParameter ( "street_in" , street )
115+ .setParameter ( "city_in" , city );
116+ query .execute ();
117+ ResultSet rs = (ResultSet ) query .getOutputParameterValue ( "rec_out" );
118+ try {
119+ assertTrue ( rs .next () );
120+ assertThat ( rs .getString ( "street" ), is ( street ) );
121+ assertThat ( rs .getString ( "city" ), is ( city ) );
122+ assertThat ( rs .getString ( "zip" ), is ( zip ) );
123+ }
124+ catch (SQLException e ) {
125+ throw new RuntimeException ( e );
126+ }
127+ }
128+ );
129+ }
130+
89131
90132 @ Test
91133 public void testStoredProcedureOutParameter (EntityManagerFactoryScope scope ) {
@@ -422,6 +464,25 @@ public void prepareSchema(EntityManagerFactoryScope scope) {
422464 " RETURN pos; " +
423465 "END;"
424466 );
467+
468+ statement .execute (
469+ "CREATE OR REPLACE PROCEDURE GET_ADDRESS_BY_NAME (" +
470+ " street_in IN ADDRESS_TABLE.STREET%TYPE," +
471+ " city_in IN ADDRESS_TABLE.CITY%TYPE," +
472+ " rec_out OUT SYS_REFCURSOR," +
473+ " err_out OUT VARCHAR)" +
474+ " AS" +
475+ " BEGIN" +
476+ " OPEN rec_out FOR" +
477+ " SELECT A.STREET, A.CITY, A.zip" +
478+ " FROM ADDRESS_TABLE A " +
479+ " WHERE " +
480+ " A.STREET = street_in" +
481+ " AND A.CITY = city_in;" +
482+ " EXCEPTION " +
483+ " WHEN OTHERS THEN " +
484+ " err_out := SQLCODE || ' ' || SQLERRM;" +
485+ " END;" );
425486 }
426487 catch (SQLException e ) {
427488 System .err .println ( "Error exporting procedure and function definitions to Oracle database : " + e .getMessage () );
@@ -504,4 +565,44 @@ public static class IdHolder {
504565 Long id ;
505566 String name ;
506567 }
568+
569+ @ Entity
570+ @ Table (name ="ADDRESS_TABLE" )
571+ public static class Address {
572+ @ Id
573+ @ Column (name ="ID" )
574+ private long id ;
575+ @ Column (name ="STREET" )
576+ private String street ;
577+ @ Column (name ="CITY" )
578+ private String city ;
579+ @ Column (name ="ZIP" )
580+ private String zip ;
581+
582+ public Address () {
583+ }
584+
585+ public Address (long id , String street , String city , String zip ) {
586+ this .id = id ;
587+ this .street = street ;
588+ this .city = city ;
589+ this .zip = zip ;
590+ }
591+
592+ public long getId () {
593+ return id ;
594+ }
595+
596+ public String getStreet () {
597+ return street ;
598+ }
599+
600+ public String getCity () {
601+ return city ;
602+ }
603+
604+ public String getZip () {
605+ return zip ;
606+ }
607+ }
507608}
0 commit comments