列表作为存储过程的参数

List as parameter to stored procedure

嘿,我正在开发 JSF/PF5/Mybatis/Oracle 应用程序。

我正在努力想办法。

我正在尝试发送一个整数列表作为存储过程的参数。

我在 运行 测试时收到此错误:

Caused by: java.sql.SQLException: invalid name pattern: SSLS_WMS.INT_ARRAY

有人可以帮我解决这个问题吗?

(我已经浏览了几个问题,例如 this

我创建了一个测试包:

CREATE OR REPLACE PACKAGE SSLS_WMS.pkg_test
as
C_PKG_NAME                    CONSTANT tracer.T_CALL_NAME :=     sys_context('USERENV','CURRENT_SCHEMA') || '.pkg_test.';
TYPE INT_ARRAY is table of SSLS_WMS.ORDERS.ORDER_ID%type;
procedure pMergeOrders(
    pMergeType      INTEGER,
    pToMerge     IN INT_ARRAY,
    pParentOrderId        orders.order_id%type,
    pParentOrderNo        orders.order_no%type,
    p_do_it            pls_integer default 1
);
end pkg_test;
/

CREATE OR REPLACE PACKAGE body SSLS_WMS.pkg_test
as
procedure pMergeOrders(
    pMergeType      INTEGER,
    pToMerge              INT_ARRAY,
    pParentOrderId        orders.order_id%type,
    pParentOrderNo        orders.order_no%type,
    p_do_it            pls_integer default 1
)
AS
v_prog_name         tracer.t_call_name := C_PKG_NAME||'pMergeOrders';
v_prog_params       tracer.t_params :=  'pParentOrderId='||pParentOrderId||
                                        'p_do_it='||p_do_it;
BEGIN
insert into ssls_wms.TEST_THEO2(ORDER_ID) values (pParentOrderId);
for currOrderId in (select column_value FROM TABLE(pToMerge))
loop
  insert into ssls_wms.TEST_THEO2(ORDER_ID) values (currOrderId.column_value);
end loop;
COMMIT;
end pMergeOrders;
end pkg_test;

映射器更新语句:

    <update id="mergeOrders" parameterType="java.util.Map"
    statementType="CALLABLE">
    {CALL SSLS_WMS.PKG_TEST.PMERGEORDERS(
    #{p_mergeType,
    jdbcType=INTEGER},
    #{p_toMerge, javaType=java.util.List,
    jdbcType=ARRAY,
    jdbcTypeName=INT_ARRAY, mode=IN,
    typeHandler=com.mybatis.thandlers.IntArrayTypeHandler},
    #{p_parentOrdId,
    jdbcType=INTEGER},
    #{p_parentOrdNo,jdbcType=VARCHAR},
    #{p_do_it,
    jdbcType=VARCHAR}
    )
    }
</update>

这就是我调用的过程:

  @Test
   public void _testOrderMerger() {
     OrderMergerService service = new OrderMergerService();
     List<Integer> orders = new ArrayList<Integer>();
     orders.add(13648);
     orders.add(136500);
     Map<String, Object> params = new HashMap<String, Object>();
     params.put("p_mergeType", 1);
     params.put("p_toMerge", orders);
     params.put("p_parentOrdId", 13652);
     params.put("p_do_it", 1);
     SQLResult result = service.merge(params);
     if (result.isOk()) {
       System.out.println("SUCCES");
     } else
       System.out.println("NOT GOOD");
   }

我很确定问题与我的类型处理程序实现有关:

public class IntArrayTypeHandler implements TypeHandler<Object> {
  @SuppressWarnings("unchecked")
  @Override
  public void setParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
    List<Integer> objects = (List<Integer>) parameter;

    ArrayDescriptor desc = ArrayDescriptor.createDescriptor("SSLS_WMS.PKG_TEST.INT_ARRAY", ps.getConnection());
    ARRAY oracleArray = new ARRAY(desc, ps.getConnection(), objects);
    ps.setArray(i, oracleArray);
  }
    ... etc

使用JDBC,您无法访问打包类型。 This answer 可能会有帮助。

您可以在架构级别定义您的类型(通过提供列类型,因为您不能在此处使用 %type):

CREATE OR REPLACE TYPE TA_ORDER_ID AS TABLE OF NUMBER(15);

然后将其用作,

ArrayDescriptor desc = ArrayDescriptor.createDescriptor("SSLS_WMS.TA_ORDER_ID", ps.getConnection());

或者,您可以为您的类型创建一个 public 同义词,授予授权,然后在您的 TypeHandler 中使用该同义词。

CREATE OR REPLACE PUBLIC SYNONYM S_INT_ARRAY FOR SSLS_WMS.PKG_TEST.INT_ARRAY;