简体   繁体   中英

Calling a PL SQL Function with object parameter in java

In Oracle SQL I have a type:

CREATE OR REPLACE type address_type
AS
OBJECT
(
Street VARCHAR2(100),
Road   VARCHAR2(100),
Town   VARCHAR2(100),
County VARCHAR2(100) );

This is used for a function, the function uses the ADDRESS_TYPE to take an answer as a parameter and returns an integer:

create or replace FUNCTION ADD_ADDRESS_FUNC(
    New_Address IN Address_Type )
  RETURN INTEGER
AS
  AddressID INTEGER;
BEGIN
  AddressID := ADDRESS_SEQ.NEXTVAL;
  INSERT
  INTO Address VALUES
    (
      AddressID,
      New_Address.Street,
      New_Address.Road,
      New_Address.Town,
      New_Address.County
    );
  DBMS_OUTPUT.PUT_LINE(AddressID);
  RETURN AddressID;
END;

In my Java classes I have all connections etc & I can access other procs & functions but not this one which takes the Address object. In Java I create an Address object a with 4 strings, surely I can just pass this as second argument below:

Address a = new Address("Address 1", "Address 2", "Town", "County");
CallableStatement stmt = conn.prepareCall( "begin ? := ADD_ADDRESS_FUNC(?);end;" );
stmt.registerOutParameter(1, Types.CHAR);
stmt.setObject(2, a);
stmt.execute ();
int memberID = stmt.getInt(1);`

The error message says invalid column index and it is breaking down at the setObject call. If it were a string it would be fine but the Address object isn't working. Any help appreciated, thanks in advance

Create the type in the anonymous PL/SQL block (rather than in Java) and pass in the values:

CallableStatement st = con.prepareCall("BEGIN ? := ADD_ADDRESS_FUNC( Address_Type(?,?,?,?)); END;");

st.registerOutParameter( 1, Types.INTEGER );
st.setString( 2, "Address 1" );
st.setString( 3, "Address 2" );
st.setString( 4, "Town" );
st.setString( 5, "County" );

st.execute();
int id = st.getInt(1);

The alternative is that you can use JPublisher to generate the Address class so that it can be passed to/from the database.

For Oracle Functions, you can use the native sql query with Hibernate as such:

Query query = session.createSqlQuery("select PACKAGE.AddAdress(:STREET, :ROAD, :TOWN, :COUNTRY) as ADDRESS_ID from DUAL")
             .addScalar("ADDRESS_ID", java.sql.integer);

  query.setParameter(":STREET", "Street name")
  query.setParameter(":ROAD", "Road name")
  etc... ;

int addrId = (int) query.UniqueResult();

The addScalar method is necessary for retrieving the ResultSet . If your function returns an Oracle defined Type, you can say:

.addScalar("ADDRESS_ID", new CustomType(new OracleType()))

And this OracleType would be the type matching the Oracle Type. So create a class OracleType which implements UserType , and override the method

nullSafeGet(ResultSet rs, Sting name..){
   Object[] result = (java.sql.STRUCT) rs.getObject(names[0]).getAttributes()
}

This result will then be the object returned by query.uniqueResult as such: Object[] result = query.uniqueResult() in your query method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM