1

我试图执行一个过程,该过程在其他过程中包含一个参数,该参数是对象(oracle)的集合。我已经在没有 spring 的情况下管理了很多次,但是我在尝试使用 spring 时有点迷失,尽管互联网上有一些信息,但我找不到完整的示例来比较我的代码。Spring doc 只有片段。可能我的代码是错误的,但我忽略了为什么,你能帮我吗?我正在运行更简单的程序而没有问题。我的 DAO 看起来像这样:

//[EDITED]
private SimpleJdbcCall pActualizaDia;

....

@Autowired
public void setDataSource(DataSource dataSource) {
  pActualizaDia = new SimpleJdbcCall(dataSource).withCatalogName("PTR_GRUPOS_TRABAJO").withProcedureName("UPDATE_DIA");
  pActualizaDia.getJdbcTemplate().setNativeJdbcExtractor(new OracleJdbc4NativeJdbcExtractor());
}
...

 public Calendario updateSingle(final Calendario calendario) {

    SqlTypeValue cambiosEmpresa = new AbstractSqlTypeValue() {

    protected Object createTypeValue(Connection conn, int sqlType, String typeName) throws SQLException {

    ArrayDescriptor arrayDescriptor = new ArrayDescriptor("TTPTR_CAMBIO_EMPRESA", conn);

    Object[] collection = new Object[calendario.getCambiosEmpresa().size()];
    int i = 0;
    for (CeAnoEmp ce : calendario.getCambiosEmpresa()) {
        collection[i++] = new STRUCT(new StructDescriptor("TPTR_CAMBIO_EMPRESA", conn), conn, new Object[] {
            ce.getSQLParam1(),
            //...more parameters here in order to fit your type.
            ce.getSQLparamn() });
    }

    ARRAY idArray = new ARRAY(arrayDescriptor, conn, collection);

    return idArray;

    }

};

     MapSqlParameterSource mapIn = new MapSqlParameterSource();
 mapIn.addValue("P_ID_ESCALA", calendario.getEscala().getIdEscala());
     //more simple params here

     //Here it is the Oracle ARRAY working properly
 pActualizaDia.declareParameters(new SqlParameter("P_CAMBIOS_EMPRESA",
 OracleTypes.STRUCT, "TTPR_CAMBIO_EMPRESA"));
 mapIn.addValue("P_CAMBIOS_EMPRESA",cambiosEmpresa);

     //When executing the procedure it just work :)
     pActualizaDia.execute(mapIn);
     return null;
   }

我得到的例外是

java.lang.ClassCastException: $Proxy91 cannot be cast to oracle.jdbc.OracleConnection

我一直在阅读有关此主题的更多信息,我发现如果使用 Oracle 阵列,您似乎还必须将连接强制转换为 oracle 连接。

但是,大多数 Spring jdbc 框架类(如 SimpleJDBCTemplate 和 StoredProcedure)对您隐藏了连接访问。我是否需要对其中一个进行子类化并在某处覆盖一个方法以获取 dbcp 连接,然后将其转换为 Oracle 连接?

非常感谢你。

4

2 回答 2

1

我终于解决了它,我编辑了这篇文章,以便为任何寻找一段代码来解决这个问题的人提供一个示例。

有两个重要的事情要记住:

1) 必须在 jdbctemplate 中设置 oracle 提取器才能正确转换连接以获得 oracle 功能。

2) 使用此提取器时,ojdbc 和 JRE 版本必须相同,否则会出现 abstractmethodinvocation 异常。

感谢任何试图解决它并希望它有所帮助的人。

于 2012-08-23T08:50:54.727 回答
1

您可以使用 spring 调用带有 oracle 结构集合数组的过程:下面是一个简单的示例来执行此操作

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.sql.DataSource;

import oracle.jdbc.driver.OracleConnection;
import oracle.jdbc.driver.OracleTypes;
import oracle.sql.ARRAY;
import oracle.sql.ArrayDescriptor;
import oracle.sql.STRUCT;
import oracle.sql.StructDescriptor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.object.StoredProcedure;



public class SpringObjectMapper {

    public static class SaveObjectFunction extends StoredProcedure {
        final static Logger logger = LoggerFactory.getLogger(SavePackInterFunction.class);

        private static final String PROC_NAME = "schema.proc_name";
        private final static String ARRAY_OF_VALUE_PARAM_NAME = "ARRAY_OF_VALUE";
        private final static String OUT_PARAM_NAME = "out";

        public SaveObjectFunction(DataSource dataSource) {
            super(dataSource, PROC_NAME);
            declareParameter(new SqlParameter(ARRAY_OF_VALUE_PARAM_NAME, OracleTypes.ARRAY, "schema.array_object_type"));
            compile();
        }

        public String execute(Collection<Model> values) {
            logger.info("------------------------EnregInterlocuteurPrcedure::execute : begin----------------------------");
            String message = null;
            try {

                OracleConnection connection = getJdbcTemplate().getDataSource().getConnection().unwrap(OracleConnection.class);
                ArrayDescriptor arrayValueDescriptor = new ArrayDescriptor("schema.array_object_type", connection);
                StructDescriptor typeObjeDescriptor = new StructDescriptor("schema.object_type", connection);

                Object[] valueStructArray = new Object[values.size()];
                int i = 0;  
                for (Iterator<Model> iterator = values.iterator(); iterator.hasNext();) {
                    Model model = (Model) iterator.next();
                    STRUCT s = new STRUCT(typeObjeDescriptor, connection, new Object[] {model.getAttribute1(), model.getAttribute2(), model.getAttribute3(),
                            model.getAttribute4(), model.getAttribute5(), model.getAttribute6(), model.getAttribute7()});
                    valueStructArray[i++] = s;
                }
                ARRAY inZoneStructArray = new ARRAY(arrayValueDescriptor, connection, valueStructArray);
                Map<String, Object> inputs = new HashMap<String, Object>();
                inputs.put(ARRAY_OF_VALUE_PARAM_NAME, inZoneStructArray);
                Map<String, Object> out = super.execute(inputs);
                message = (String) out.get(OUT_PARAM_NAME);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            return message;
        }
    }

}
于 2015-11-09T15:54:44.750 回答