How to Pass Java List of Objects to Oracle Stored Procedure Using MyBatis?

后端 未结 2 578
死守一世寂寞
死守一世寂寞 2020-12-05 08:46

I have been googling this for a while and cannot seem to find any real answers.

I have an Oracle stored procedure that has a number of in parameters that have a type

相关标签:
2条回答
  • 2020-12-05 09:17

    Andy Pryor's answer is very good I tested it and it really works. But it has an error at typeHandler:

    call your_proc
    (
    #{yourObjects, javaType=Object, jdbcType=ARRAY, jdbcTypeName=YOUR_OBJECT_ARRAY, mode=IN, typeHandler=YourObjectArrayTypeHandler}
    )
    

    should be:

    call your_proc
    (
    #{yourObjects, javaType=Object, jdbcType=ARRAY, jdbcTypeName=YOUR_OBJECT_ARRAY, mode=IN, typeHandler=YourTypeHandler}
    )
    

    The TypeHandler has an error as well: (there is no "packs" and there is some difference in the method parameters in my version)

    @Override
    public void setParameter(PreparedStatement ps, int i, Object parameter, String arg3) throws SQLException {
        List<YourObject> objects = (List<YourObject>) parameter;
    
        StructDescriptor structDescriptor = StructDescriptor.createDescriptor("YOUR_OBJECT", ps.getConnection());
    
        STRUCT[] structs = new STRUCT[objects.size()];
        for (int index = 0; index < objects.size(); index++)
        {
            YourObject pack = objects.get(index);
            Object[] params = new Object[2];
            params[0] = pack.getFieldOne();
            params[1] = pack.getFieldTwo();
            STRUCT struct = new STRUCT(structDescriptor, ps.getConnection(), params);
            structs[index] = struct;
        }
    
        ArrayDescriptor desc = ArrayDescriptor.createDescriptor("YOUR_OBJECT_ARRAY", ps.getConnection());
        ARRAY oracleArray = new ARRAY(desc, ps.getConnection(), structs);
        ps.setArray(i, oracleArray);
    }
    

    And here is an example for xml mapping:

      <parameterMap id="updateHierPersonAssignMap" class="java.util.Map" >                      
        <parameter property="p_array" jdbcType="ARRAY" javaType="Object" mode="IN" typeHandler="com.aamtech.ria.model.domain.typehandler.YourTypeHandler"/>
      </parameterMap>
      <procedure id="updateHierPersonAssign" parameterMap="updateHierPersonAssignMap" >
        <![CDATA[ 
            { call ria_am_util_pkg.j_update_hier_person_assign( ? ) }
        ]]>
      </procedure>  
    

    And here is how you can call it from the DAO:

    public void update(List array) {
        Map<String, Object> queryParams = new HashMap<String, Object>();
        queryParams.put("p_array", array);
        try {
            client.update("HashMapResult.updateHierPersonAssign", queryParams);
        } catch (SQLException e) {
        }
    }
    

    And my procedure looks like this (it just inserts a row into a test table):

    Procedure j_update_hier_person_assign (p_array IN YOUR_OBJECT_ARRAY) is
      begin
         FOR i IN 1..p_array.count LOOP
           --dbms_output.put_line();
           insert into test (a) values (p_array(i).field_one);
         END LOOP;
      end;
    
    0 讨论(0)
  • 2020-12-05 09:19

    I can't tell if you do already or not, but you'll need Oracle objects defined.

    CREATE OR REPLACE TYPE SCHEMA."YOUR_OBJECT" AS OBJECT
    (
        field_one    varchar2(50),
        field_two    varchar2(100)
    );
    /
    CREATE OR REPLACE TYPE SCHEMA."YOUR_OBJECT_ARRAY" AS TABLE OF YOUR_OBJECT;
    /
    

    Then you can write type handlers to map the Java objects to the Oracle objects.

    import oracle.sql.ARRAY;
    import oracle.sql.ArrayDescriptor;
    import oracle.sql.STRUCT;
    import oracle.sql.StructDescriptor;
    ....
    public class YourTypeHandler implements TypeHandler
    {
    ....
        public void setParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException
        {
            List<YourObject> objects = (List<YourObject>) parameter;
    
            StructDescriptor structDescriptor = StructDescriptor.createDescriptor("YOUR_OBJECT", ps.getConnection());
    
            STRUCT[] structs = new STRUCT[objects.size()];
            for (int index = 0; index < objects.size(); index++)
            {
                YourObject pack = packs.get(index);
                Object[] params = new Object[2];
                params[0] = pack.getFieldOne();
                params[1] = pack.getFieldTwo();
                STRUCT struct = new STRUCT(structDescriptor, ps.getConnection(), params);
                structs[index] = struct;
            }
    
            ArrayDescriptor desc = ArrayDescriptor.createDescriptor("YOUR_OBJECT_ARRAY", ps.getConnection());
            ARRAY oracleArray = new ARRAY(desc, ps.getConnection(), structs);
            ps.setArray(i, oracleArray);
        }
    }
    

    Then invoke the procedure,

    call your_proc
    (
    #{yourObjects, javaType=Object, jdbcType=ARRAY, jdbcTypeName=YOUR_OBJECT_ARRAY, mode=IN, typeHandler=YourObjectArrayTypeHandler}
    )
    
    0 讨论(0)
提交回复
热议问题