Передача и возврат настраиваемого объекта массива в ibatis и oracle в java

Я поискал хороший пример, но пока не встречал. Я хочу передать настраиваемый массив строк из java в oracle и обратно, используя структуру IBATIS. У кого-нибудь есть хорошая ссылка на пример? Я вызываю хранимые процедуры от IBATIS.

Спасибо

что вы имеете в виду под строковым массивом обычай, он чем-то отличается от String []?

Dónal 26.09.2008 04:36
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
7
1
28 476
4

Ответы 4

Вам нужно начать с кастомного экземпляра TypeHandler. Мы бы предпочли реализовать более простой TypeHandlerCallback, но в этом сценарии нам нужен доступ к базовому Connection.

public class ArrayTypeHandler implements TypeHandler {

    public void setParameter(PreparedStatement ps, int i, Object param, String jdbcType)
            throws SQLException {
        if (param == null) {
            ps.setNull(i, Types.ARRAY);
        } else {
            Connection conn = ps.getConnection();
            Array loc = conn.createArrayOf("myArrayType", (Object[]) param);
            ps.setArray(i, loc);
        }
    }

    public Object getResult(CallableStatement statement, int i)
            throws SQLException {
        return statement.getArray(i).getArray();
    }
    ...
}

Затем, чтобы подключить его в конфигурации iBATIS:

<?xml version = "1.0"?>
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">

<sqlMap namespace = "arrayTest">

    <parameterMap id = "storedprocParams" class = "map">
        <parameter property = "result" mode = "OUT" jdbcType = "ARRAY" typeHandler = "ArrayTypeHandler"/>
        <parameter property = "argument" mode = "IN" jdbcType = "ARRAY" typeHandler = "ArrayTypeHandler"/>
    </parameterMap>

    <procedure id = "storedproc" parameterMap = "arrayTest.storedprocParams">
        {? = call My_Array_Function( ? )}
    </procedure>

</sqlMap>

Надеюсь это поможет!

Это было хорошей отправной точкой - мне нужно было получить собственное соединение от RAD, добавить дескриптор, описывающий мой настраиваемый массив, и убедиться, что объект в базе данных доступен. Посмотрите, что я сделал в ответ.

Justin 30.09.2008 00:39

bsanders дал мне хорошую отправную точку - вот что мне нужно было сделать, чтобы заставить его работать в среде RAD (websphere 6.2).

public Object getResult(CallableStatement statement, int i) throws SQLException {
    return statement.getArray(i).getArray(); //getting null pointer exception here
}

public void setParameter(PreparedStatement ps, int i, Object param, String jdbcType) throws SQLException {
    if (param == null) {
        ps.setNull(i, Types.ARRAY);

    } else {
        String[] a = (String[]) param;
        //ARRAY aOracle = ARRAY.toARRAY(a, (OracleConnection)ps.getConnection());

        //com.ibm.ws.rsadapter.jdbc.WSJdbcConnection
        w = (com.ibm.ws.rsadapter.jdbc.WSJdbcConnection)ps.getConnection());

        //com.ibm.ws.rsadapter.jdbc.WSJdbcObject x;
        Connection nativeConnection = Connection)WSJdbcUtil.getNativeConnection((WSJdbcConnection)ps.getConnection());

        ArrayDescriptor descriptor = ArrayDescriptor.createDescriptor("F2_LIST", nativeConnection);
        ARRAY dataArray = new ARRAY(descriptor, nativeConnection, a);
        ps.setArray(i, dataArray);
    }
}

Обратите внимание на nativeConnection, который мне нужно было получить, дескриптор, который мне нужно было создать, и так далее. Однако, хотя я могу передавать данные в базу данных в виде массива строк, я не мог понять, почему я ничего не получаю обратно. Мой параметр OUT (getResult (CallableStatement statment, int i) выдает исключение с нулевым указателем, хотя я устанавливаю параметр out в plsql в базе данных.

--stored procedure to take a | delimited ids
   PROCEDURE array_test (argument IN f2_list, result OUT f2_list) 
   AS
      l_procname_v   VARCHAR2 (50)                 := 'array_test';
      l_param_list   VARCHAR2 (2000)
                   := l_procname_v || ' param_values: p_string: ';

      p_status_n     NUMBER;
      p_message_v    VARCHAR2 (2000);
      ret_list f2_list := new f2_list();
      l_count_v varchar2(200);
   BEGIN

      l_count_v := argument.COUNT;
      for x in 1..argument.count
      LOOP
          pkg_az_common_util.az_debug (package_nm,
                                   l_procname_v,
                                   pkg_az_data_type_def.debug_num,
                                   argument(x)
                                  );
      end loop;

      pkg_az_common_util.az_debug (package_nm,
                                   l_procname_v,
                                   pkg_az_data_type_def.debug_num,
                                   l_count_v
                                  );
      ret_list.extend();
      ret_list(1) := 'W';
      ret_list.extend();
      ret_list(2) := 'X';
      ret_list.extend();
      ret_list(3) := 'Y';
      ret_list.extend();
      ret_list(4) := 'Z';

      result := ret_list;


   EXCEPTION
      WHEN OTHERS
      THEN
         p_status_n := pkg_az_common_util.get_error_code;
         p_message_v :=
               TO_CHAR (p_status_n)
            || '|'
            || 'Oracle Internal Exception('
            || l_procname_v
            || ')'
            || '|'
            || TO_CHAR (SQLCODE)
            || '|'
            || SQLERRM
            || l_param_list;
         standard_pkg.log_error (package_nm,
                                 l_procname_v,
                                 SQLCODE,
                                 p_message_v
                                );

         IF p_status_n = 1
         THEN
            RAISE;
         END IF;
   END array_test;

Вот как я получаю к нему доступ:

Map queryParamsTest = new HashMap();

        String[] testArray = {"A", "B", "C"};

        queryParamsTest.put("argument", testArray);



        DaoUtils.executeQuery(super.getSqlMapClientTemplate(),
                "arrayTest", queryParamsTest, queryParamsTest
                .toString());  //just executes query


        String[] resultArray = (String[])queryParamsTest.get("result");

        for(int x = 0; x< resultArray.length; x++)
        {
            System.out.println("Result: " + resultArray[x]);
        }



<parameterMap id = "storedprocParams" class = "map">        
        <parameter property = "argument" mode = "IN" jdbcType = "ARRAY" typeHandler = "ArrayTypeHandler"/>    
        <parameter property = "result" mode = "OUT" jdbcType = "ARRAY" typeHandler = "ArrayTypeHandler"/>        
    </parameterMap>    
    <procedure id = "arrayTest" parameterMap = "storedprocParams">        
        {call pkg_az_basic_dev.array_test(?, ? )}    
    </procedure>

Есть идеи?

Попробуйте использовать statement.getObject(i), а затем выполнить приведение к массиву.

Что ж, ребята в компании обнаружили решение: вам необходимо реализовать метод (ы) getResult в вашем typeHandler и предоставить дополнительный атрибут jdbcTypeName = ORACLE_REAL_ARRAY_TYPE в вашем картографе

я заметил, что тип ARRAY не поддерживается в документации batis, я обнаружил, что это дезинформативно

tomasb 20.10.2011 14:15

Другие вопросы по теме