9

私はこれをしばらくグーグルで調べてきましたが、本当の答えが見つからないようです。

テーブルの行タイプのテーブルであるタイプを持つ多くの in パラメータを持つ Oracle ストアド プロシージャがあります。たとえば、次のようになります。

パッケージで宣言:

TYPE param1_type_t IS TABLE OF table1%ROWTYPE;
TYPE param2_type_t IS TABLE OF table2%ROWTYPE;
TYPE param3_type_t IS TABLE OF table3%ROWTYPE;

オラクルの手順:

PROCEDURE my_proc
(
   parameter1    IN param1_type_t,
   parameter2    IN param2_type_t,
   parameter3    IN param3_type_t
)

Java 側では、Java で設定された各パラメーターを表す 3 つの対応するオブジェクトのリストがあります。このシナリオで MyBatis を使用して Oracle プロシージャを呼び出すことは可能ですか?

<update id="callOracleSP" statementType="CALLABLE">
    {CALL my_proc( #{param1, mode=IN},
                   #{param2, mode=IN},
                   #{param3, mode=IN}
                 )
    }
</update>

オブジェクト自体は、String プロパティと Integer プロパティ、およびそれぞれの getter と setter を持つ単純な VO です。

どのように進めればよいかよくわかりません。Java オブジェクト リストを Oracle 型にマップする必要はありますか?

4

2 に答える 2

12

すでに行っているかどうかはわかりませんが、Oracle オブジェクトを定義する必要があります。

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;
/

次に、型ハンドラを記述して、Java オブジェクトを Oracle オブジェクトにマップできます。

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);
    }
}

次に、プロシージャを呼び出します。

call your_proc
(
#{yourObjects, javaType=Object, jdbcType=ARRAY, jdbcTypeName=YOUR_OBJECT_ARRAY, mode=IN, typeHandler=YourObjectArrayTypeHandler}
)
于 2012-11-27T04:27:57.507 に答える
1

Andy Pryor の答えは非常に良いです。私はそれをテストしましたが、実際に機能します。しかし、typeHandler にエラーがあります。

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

次のようにする必要があります。

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

TypeHandler にもエラーがあります: (「パック」はなく、私のバージョンではメソッド パラメータに違いがあります)

@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);
}

xml マッピングの例を次に示します。

  <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>  

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) {
    }
}

そして、私の手順は次のようになります(テストテーブルに行を挿入するだけです):

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;
于 2016-02-19T11:27:05.130 に答える