java - 如何从 Java 调用具有自定义复杂对象类型作为输入参数的 Oracle PL-SQL 过程

标签 java oracle stored-procedures plsql spring-jdbc

在 Oracle 数据库中,我定义了一个具有嵌套对象类型的对象类型。假设我有一个使用父对象类型作为输入参数的 PL-SQL 过程,我正在寻找一种从 Java 代码调用该过程的高效方法。

CREATE OR REPLACE TYPE STUDENT AS OBJECT ( 
     name         VARCHAR2(35),
     address      HOME_ADDRESS
);

CREATE OR REPLACE TYPE HOME_ADDRESS AS OBJECT ( 
     street    VARCHAR2(35)
);

CREATE OR REPLACE PROCEDURE TEST(
    studentObject IN STUDENT
)
IS
BEGIN
     ... do domething ...
END;

在 Java 端,我有相关的 POJO 保存数据。

我已经尝试将 Spring SimpleJdbcCall 与 StructMapper 一起使用。

StructMapper<Demo> MAPPER = BeanPropertyStructMapper.newInstance(Student.class);
SqlParameter studentIn = new SqlParameter("studentObject", Types.STRUCT, "MY_SCHEMA.STUDENT");
SimpleJdbcCall sjc = new SimpleJdbcCall(datasource).withSchemaName("MY_SCHEMA")
      .withProcedureName("TEST")
      .withoutProcedureColumnMetaDataAccess()
      .useInParameterNames("studentObject")
      .declareParameters(studentIn);
final MapSqlParameterSource inputParameters = new MapSqlParameterSource().addValue("studentObject",
            new SqlStructValue<Student>(studentInstance, MAPPER, "MY_SCHEMA.STUDENT"));
final Map<String, Object> execute = sjc.execute(inputParameters);

以上示例在不使用嵌套对象类型时有效。使用嵌套对象类型时,将抛出 java.sql.SQLException: Fail to convert to internal representation 异常。除此之外,spring-data-oracle 和 spring-data-jdbc-ext 项目似乎不再维护,我想避免使用它们。上面的代码不是我的真实代码,而是问题目的的示例。我的真实对象类型和 Java 中相应的 POJO 可能非常复杂,有许多嵌套对象和数组。

最佳答案

最终,我找到了使用 Java 包装类的解决方案,它扩展了我的普通 POJO 并实现了 java.sql.SQLData 接口(interface)。 readSQL 方法的实现指示如何使用从数据库读取的数据填充对象,而 writeSQL 方法将此对象写入给定的 SQL 数据流。

import java.sql.SQLData;
import java.sql.SQLException;
import java.sql.SQLInput;
import java.sql.SQLOutput;

public class StudentMapper extends Student implements SQLData {

    public StudentMapper(Student student) {
        setName(student.getName());
        setAddress(student.getAddress());
    }

    @Override
    public String getSQLTypeName() throws SQLException {
        return "MY_SCHEMA.STUDENT";
    }

    @Override
    public void readSQL(SQLInput stream, String typeName) throws SQLException {
        setName(stream.readString());
        setAddress((Address) stream.readObject());
    }

    @Override
    public void writeSQL(SQLOutput stream) throws SQLException {
        stream.writeString(getName());
        final AddressMapper addressMapper = new AddressMapper(getAddress());
        stream.writeObject(addressMapper);
    }
}

final StudentMapper mapper = new StudentMapper(studentInstance);
CallableStatement callableStatement = ...
callableStatement.setObject("studentObject", mapper);
callableStatement.execute();

关于java - 如何从 Java 调用具有自定义复杂对象类型作为输入参数的 Oracle PL-SQL 过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57745132/

相关文章:

mysql - 如何使用like运算符编写mysql存储过程

c# - 在 DB 中自动聚合数据的最佳方法

sql - 滚动每日不同计数

java - JPA/Hibernate 似乎将带有 in 子句的查询转换为带有 = 子句的多个查询

sql - Oracle 10 中的本地临时表(用于存储过程的范围)

java - Gradle 测试在本地失败,但在 CI 服务器上成功

java - 在制作按钮的方法之外绘制按钮?

java - 在JTextArea中插入文本

java - java 如何从txt文件中读取字符串并将其存储到字符数组中

oracle - Oracle:如何通过查询获取总数的百分比?