我在 Oracle 中遇到 DBMS_PICKLER 包的问题。创建自定义类型后
create type NUM_ARRAY is varray(100) of NUMBER;
我收到以下异常:
Caused by: oracle.jdbc.OracleDatabaseException: ORA-06550: line 1, column 17:
PLS-00302: component 'DBMS_PICKLER' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
请注意,当我想从 Java 代码调用函数/过程时,就会出现问题。然而,当我直接从 PL/SQL 控制台调用时,一切似乎都是正确的。
CREATE OR REPLACE FUNCTION TEST(P_NUMBER_LIST IN NUM_ARRAY)
RETURN CLOB
IS
RESULT CLOB;
BEGIN
SELECT JSON_ARRAYAGG(COLUMN_VALUE) INTO RESULT FROM TABLE (P_NUMBER_LIST);
RETURN RESULT;
EXCEPTION
WHEN NO_DATA_FOUND THEN RETURN NULL;
END;
SELECT TEST(NUM_ARRAY(1, 2, 3)) FROM DUAL;
下面,我添加了调用 Oracle 函数的 Java 代码。
@Repository
@RequiredArgsConstructor
public class TestDaoImpl implements TestDao {
private final DataSource dataSource;
@Override
public String test(TestRequest request) {
var caller = new SimpleJdbcCall(dataSource);
caller.withSchemaName("DIM")
.withFunctionName("TEST")
.declareParameters(
new SqlParameter("P_NUMBER_LIST", Types.ARRAY, "DIM.NUM_ARRAY"),
new SqlOutParameter("RESULT", Types.CLOB)
);
var params = new MapSqlParameterSource()
.addValue("P_NUMBER_LIST", new OracleNumberArray(request.getNumbers()));
var clob = caller.executeFunction(Clob.class, params); // problem occurs in here
return clobToString(clob);
}
}
并为自定义类型创建了 OracleNumberArray 类:
public class OracleNumberArray extends AbstractSqlTypeValue {
private final List<Long> values;
public OracleNumberArray(List<Long> values) {
this.values = isNull(values) ? List.of() : values;
}
@Override
@Deprecated
public Object createTypeValue(Connection con, int sqlType, String typeName) throws SQLException {
con = con.unwrap(oracle.jdbc.OracleConnection.class);
ArrayDescriptor desc = new ArrayDescriptor(typeName, con);
return new ARRAY(desc, con, values.toArray(new Long[0]));
}
}
pom.xml 文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>io.programming</groupId>
<artifactId>problems</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>problems</name>
<description>Solutions for Programming Problems</description>
<properties>
<java.version>21</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc11</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.oracle.ojdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>19.3.0.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
任何人都可以建议解决这个问题吗?当我尝试使用 DBMS_PICKLER 包时似乎会出现这种情况。
下面我添加了错误的完整堆栈跟踪:https://ctxt.io/2/AACoyLc2EQ
如本博文中所示,如果您连接的用户有一个名为 SYS
的对象,则可能会发生这种情况。这会导致
类似的 PLS-00302 错误发生变化;在这种情况下,用户拥有一个与其自己的架构同名的对象。
这里的对象是一个不同的模式,但由于 JDBC 驱动程序显然正在调用SYS.DBMS_PICKLER.something
,因此发生了相同类型的名称冲突。名称解析
意味着它优先于模式查看当前用户的SYS
对象,因为步骤 1a - “在当前模式中搜索名称与第一部分匹配的对象。”
SYS
对象解析名称的其余部分 - 但它无法做到这一点,因此会导致您看到的错误。
要解决此问题,您需要删除或更改SYS
对象的名称。一般来说,避免拥有与任何模式名称以及关键字、保留字等匹配的任何对象。