在 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/