通过Spring调用一个带有对象集合的过程(oracle ARRAY STRUCT)

时间:2012-08-22 11:55:38

标签: oracle spring hibernate

我试图执行一个程序,其中包含一个参数,它是一个对象集合(oracle)。我在没有春天的情况下管理了很多次,但我有点失去了试图用春天来做,虽然在互联网上有一些信息,我找不到一个完整的例子来比较我的代码。 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;
   }

我得到sais的例外

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

我一直在阅读有关此主题的更多内容,我发现,如果使用Oracle Arrays,您还必须将连接转换为oracle连接。

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

非常感谢。

2 个答案:

答案 0 :(得分:1)

我最终解决了这个问题,我编辑了帖子,以便为寻找一段代码来解决这个问题的人提供一个示例。

要记住两件重要的事情:

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

2)当使用这个提取器时,ojdbc和JRE版本必须相同,任何其他情况下你都会得到一个abstractmethodinvocation异常。

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

答案 1 :(得分: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;
        }
    }

}