从JDBC使用Oracle COLLECT聚合函数

如何解决从JDBC使用Oracle COLLECT聚合函数

我正在尝试使Oracle COLLECT()聚合函数从JDBC开始工作。

我的模式如下

CREATE TABLE t_warehouse (
  id                NUMBER(5)    NOT NULL PRIMARY KEY,warehouse_name    VARCHAR2(64) NOT NULL
);


CREATE TABLE t_warehouse_detail (
  id              NUMBER(5)     NOT NULL PRIMARY KEY,warehouse_id    NUMBER(5)    NOT NULL,detail_value    VARCHAR2(128) NOT NULL,CONSTRAINT fk_warehouse 
      FOREIGN KEY (warehouse_id)
      REFERENCES  t_warehouse(id)
);

INSERT INTO t_warehouse (id,warehouse_name)
     VALUES             (1,'warehouse 1');

INSERT INTO t_warehouse_detail (id,warehouse_id,detail_value)
     VALUES                    (1,1,'detail 1');

INSERT INTO t_warehouse_detail (id,detail_value)
     VALUES                    (2,'detail 2');


CREATE OR REPLACE TYPE warehouse_detail_t AS TABLE OF VARCHAR2(128);

我的查询如下

SELECT wh.id,CAST(COLLECT(detail_value) AS warehouse_detail_t) AS "Details"
  FROM t_warehouse wh
  JOIN t_warehouse_detail whd ON (wh.id = whd.warehouse_id)
GROUP BY wh.id;

我的代码看起来像这样

String url = ...;
String username = ...;
String password = ...;
OracleDataSource ds = new oracle.jdbc.pool.OracleDataSource();
ds.setURL(url);
ds.setUser(username);
ds.setPassword(password);

try (Connection connection = ds.getConnection()) {

  connection.setTypeMap(Collections.singletonMap("SCHEMA_NAME.WAREHOUSE_DETAIL_T",DetailValues.class));

  try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT wh.id,CAST(COLLECT(detail_value) AS warehouse_detail_t) AS \"Details\""
        + " FROM t_warehouse wh "
        + "  JOIN t_warehouse_detail whd ON (wh.id = whd.warehouse_id) "
        + " GROUP BY wh.id");
       ResultSet resultSet = preparedStatement.executeQuery()) {
    while (resultSet.next()) {
      int id = resultSet.getInt("id");
      Set<String> detailValues = Collections.emptySet();
    }
  }

并且我有以下SQLData类


  public static final class DetailValues implements SQLData {

    private String typeName;

    @Override
    public String getSQLTypeName() throws SQLException {
      return this.typeName;
    }

    @Override
    public void readSQL(SQLInput stream,String typeName) throws SQLException {
      this.typeName = typeName;
      Array array = stream.readArray();
      if (array != null) {
        try {

        } finally {
          array.free();
        }
      }
      System.out.println("readSQL");
    }

    @Override
    public void writeSQL(SQLOutput stream) throws SQLException {
      System.out.println("writeSQL");
    }

  }

我收到以下异常

java.sql.SQLException: Fail to construct descriptor: Unable to resolve type "SCHEMA_NAME.WAREHOUSE_DETAIL_T"
    at oracle.sql.TypeDescriptor.getTypeDescriptor(TypeDescriptor.java:1002)
    at oracle.jdbc.driver.NamedTypeAccessor.otypeFromName(NamedTypeAccessor.java:82)
    at oracle.jdbc.driver.TypeAccessor.initMetadata(TypeAccessor.java:75)
    at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:860)
    at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:983)
    at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1168)
    at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3666)
    at oracle.jdbc.driver.T4CPreparedStatement.executeInternal(T4CPreparedStatement.java:1426)
    at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3713)
    at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1167)
    at com.acme.CollectTests.collect(CollectTests.java:48)

这与ojdbc8-19.7.0.0和Oracle 19.3一起使用。

在Oracle SQL Developer中,查询也会失败,但有相同的例外。

更新

_g JAR的最佳输出是:

[oracle.jdbc.pool.OracleDataSource oracle.jdbc.pool.OracleDataSource        ]          Enter: void 
[oracle.jdbc.pool.OracleDataSource setConnectionProperty                    ] 47542153 Enter: "oracle.jdbc.enableACSupport","false" 
[oracle.jdbc.pool.OracleDataSource setConnectionProperty                    ] 47542153 Return: void 
[oracle.jdbc.pool.OracleDataSource setConnectionProperty                    ] 47542153 Exit: [0.370177 ms] 
[oracle.jdbc.pool.OracleDataSource processFastConnectionFailoverSysProperty ] 47542153 Enter: void 
[oracle.jdbc.pool.OracleDataSource processFastConnectionFailoverSysProperty ] 47542153 Return: void 
[oracle.jdbc.pool.OracleDataSource processFastConnectionFailoverSysProperty ] 47542153 Exit: [0.133466 ms] 
[oracle.jdbc.pool.OracleDataSource oracle.jdbc.pool.OracleDataSource        ]          Return: void 
[oracle.jdbc.pool.OracleDataSource oracle.jdbc.pool.OracleDataSource        ]          Exit: [0.386721 ms] 
[oracle.jdbc.pool.OracleDataSource setURL                                   ] 47542153 Enter: "jdbc:oracle:thin:@localhost:1521/ORCLPDB1?oracle.net.disableOob=true" 
[oracle.jdbc.pool.OracleDataSource setURL                                   ] 47542153 Return: void 
[oracle.jdbc.pool.OracleDataSource setURL                                   ] 47542153 Exit: [0.13673 ms] 
[oracle.jdbc.pool.OracleDataSource setUser                                  ] 47542153 Enter: "schema_name" 
[oracle.jdbc.pool.OracleDataSource setUser                                  ] 47542153 Return: void 
[oracle.jdbc.pool.OracleDataSource setUser                                  ] 47542153 Exit: [0.121062 ms] 
[oracle.jdbc.pool.OracleDataSource setPassword                              ] 47542153 Enter: "*****" 
[oracle.jdbc.pool.OracleDataSource setPassword                              ] 47542153 Enter: oracle.jdbc.internal.OpaqueString@67d0ff08 
[oracle.jdbc.pool.OracleDataSource setPassword                              ] 47542153 Return: void 
[oracle.jdbc.pool.OracleDataSource setPassword                              ] 47542153 Exit: [0.128787 ms] 
[oracle.jdbc.pool.OracleDataSource setPassword                              ] 47542153 Return: void 
[oracle.jdbc.pool.OracleDataSource setPassword                              ] 47542153 Exit: [0.379598 ms] 
[oracle.jdbc.pool.OracleDataSource getConnection                            ] 47542153 Enter: void 
[oracle.jdbc.pool.OracleDataSource getConnection                            ] 47542153 Enter: "schema_name","*****" 
[oracle.jdbc.pool.OracleDataSource getConnection                            ] OracleDataSource.getConnection(user,passwd): URL isjdbc:oracle:thin:@localhost:1521/ORCLPDB1?oracle.net.disableOob=true 
[oracle.jdbc.pool.OracleDataSource createConnectionBuilder                  ] 47542153 Enter: void 
[oracle.jdbc.pool.OracleDataSource createConnectionBuilder                  ] 47542153 Return: oracle.jdbc.pool.OracleDataSource$1@5e316c74 
[oracle.jdbc.pool.OracleDataSource createConnectionBuilder                  ] 47542153 Exit: [2.499096 ms] 
[oracle.jdbc.pool.OracleDataSource getConnection                            ] 47542153 Enter: oracle.jdbc.pool.OracleDataSource$1@5e316c74 
[oracle.jdbc.pool.OracleDataSource makeURL                                  ] 47542153 Enter: void 
[oracle.jdbc.pool.OracleDataSource makeURL                                  ] 47542153 Return: void 
[oracle.jdbc.pool.OracleDataSource makeURL                                  ] 47542153 Exit: [0.10966 ms] 
[oracle.jdbc.pool.OracleDataSource getPhysicalConnection                    ] 47542153 Enter: {password=redacted,oracle.jdbc.enableACSupport=false,connection_url=jdbc:oracle:thin:@localhost:1521/ORCLPDB1?oracle.net.disableOob=true,user=schema_name},null 
[oracle.jdbc.pool.OracleDataSource getPhysicalConnection                    ] OracleDataSource.getPhysicalConnection(prop): URL isjdbc:oracle:thin:@localhost:1521/ORCLPDB1?oracle.net.disableOob=true,user: schema_name,password: ***** 
[oracle.jdbc.driver.HAManager oracle.jdbc.driver.HAManager                  ]          Enter: void 
[oracle.jdbc.driver.HAManager oracle.jdbc.driver.HAManager                  ]          Return: void 
[oracle.jdbc.driver.HAManager oracle.jdbc.driver.HAManager                  ]          Exit: [0.675662 ms] 
[oracle.jdbc.driver.NoSupportHAManager oracle.jdbc.driver.NoSupportHAManager]          Enter: void 
[oracle.jdbc.driver.NoSupportHAManager oracle.jdbc.driver.NoSupportHAManager]          Return: void 
[oracle.jdbc.driver.NoSupportHAManager oracle.jdbc.driver.NoSupportHAManager]          Exit: [0.101079 ms] 
[oracle.jdbc.driver.NoSupportHAManager getInstance                          ]          Enter: void 
[oracle.jdbc.driver.NoSupportHAManager getInstance                          ]          Return: oracle.jdbc.driver.NoSupportHAManager@bccb269 
[oracle.jdbc.driver.NoSupportHAManager getInstance                          ]          Exit: [0.104732 ms] 
[oracle.jdbc.driver.HAManager enableHAIfNecessary                           ]          Enter: "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=ORCLPDB1)))",oracle.jdbc.driver.T4CConnection@3c0be339 
[oracle.jdbc.driver.HAManager enableHAIfNecessary                           ] ========= simplefan.jar or ons.jar is not on the classpath,HA is disabled,java.lang.ClassNotFoundException: oracle.simplefan.FanManager 
[oracle.jdbc.driver.HAManager enableHAIfNecessary                           ] ========= HA is explicitly disabled 
[oracle.jdbc.driver.HAManager enableHAIfNecessary                           ]          Return: void 
[oracle.jdbc.driver.HAManager enableHAIfNecessary                           ]          Exit: [0.660915 ms] 
[oracle.jdbc.pool.OracleDataSource getPhysicalConnection                    ] 47542153 Return: oracle.jdbc.driver.T4CConnection@3c0be339 
[oracle.jdbc.pool.OracleDataSource getPhysicalConnection                    ] 47542153 Exit: [0.946502 ms] 
[oracle.jdbc.pool.OracleDataSource getConnection                            ] 47542153 Return: oracle.jdbc.driver.T4CConnection@3c0be339 
[oracle.jdbc.pool.OracleDataSource getConnection                            ] 47542153 Exit: [1.244383 ms] 
[oracle.jdbc.pool.OracleDataSource getConnection                            ] 47542153 Return: oracle.jdbc.driver.T4CConnection@3c0be339 
[oracle.jdbc.pool.OracleDataSource getConnection                            ] 47542153 Exit: [1.471857 ms] 
[oracle.jdbc.pool.OracleDataSource getConnection                            ] 47542153 Return: oracle.jdbc.driver.T4CConnection@3c0be339 
[oracle.jdbc.pool.OracleDataSource getConnection                            ] 47542153 Exit: [1.732571 ms] 
[oracle.jdbc.driver.NoSupportHAManager dropConnection                       ] BCCB269 Enter: oracle.jdbc.driver.T4CConnection@3c0be339 
[oracle.jdbc.driver.NoSupportHAManager dropConnection                       ] NoSupportHAManager.dropConnection() 
[oracle.jdbc.driver.NoSupportHAManager dropConnection                       ] BCCB269 Return: void 
[oracle.jdbc.driver.NoSupportHAManager dropConnection                       ] BCCB269 Exit: [0.180062 ms] 
Exception in thread "main" java.sql.SQLException: Fail to construct descriptor: Unable to resolve type "SCHEMA_NAME.WAREHOUSE_DETAIL_T"
    at oracle.sql.TypeDescriptor.getTypeDescriptor(TypeDescriptor.java:998)
    at oracle.jdbc.driver.NamedTypeAccessor.otypeFromName(NamedTypeAccessor.java:78)
    at oracle.jdbc.driver.TypeAccessor.initMetadata(TypeAccessor.java:71)
    at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:856)
    at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:979)
    at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1164)
    at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3662)
    at oracle.jdbc.driver.T4CPreparedStatement.executeInternal(T4CPreparedStatement.java:1422)
    at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3709)
    at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1163)

解决方法

您的代码可以在SQL中完美运行。也许,我认为您的代码中缺少的唯一想法是该类型末尾的斜杠。请记住,类型与过程,包或函数相同,您需要/来创建对象

SQL> CREATE TABLE t_warehouse (
  id                NUMBER(5)    NOT NULL PRIMARY KEY,warehouse_name    VARCHAR2(64) NOT NULL
);  2    3    4

Table created.

SQL> CREATE TABLE t_warehouse_detail (
  id              NUMBER(5)     NOT NULL PRIMARY KEY,warehouse_id    NUMBER(5)    NOT NULL,detail_value    VARCHAR2(128) NOT NULL,2    CONSTRAINT fk_warehouse
      FOREIGN KEY (ware  3  house_id)
      REFERENCES  t_warehouse(id)
  4    5    6    7    8  );

Table created.

SQL> INSERT INTO t_warehouse (id,warehouse_name)
  2       VALUES             (1,'warehouse 1');

INSERT INTO t_warehouse_detail (id,warehouse_id,detail_value)
     VALUES                    (1,1,'detail 1');

INSERT INTO t_warehouse_detail (id,detail_value)
     VALUES                    (2,'detail 2');
1 row created.

SQL> SQL>   2
1 row created.

SQL> SQL>   2

1 row created.

SQL> commit ;

Commit complete.

SQL> CREATE OR REPLACE TYPE warehouse_detail_t AS TABLE OF VARCHAR2(128);
  2
  3  /

Type created.

SQL> SELECT wh.id,CAST(COLLECT(detail_value) AS warehouse_detail_t) AS "Details"
  FROM t_warehouse wh
  JOIN t_warehouse_detail whd ON (wh.id = whd.warehouse_id)
GROUP BY wh.id;  2    3    4

        ID
----------
Details
--------------------------------------------------------------------------------
         1
WAREHOUSE_DETAIL_T('detail 1','detail 2')
,

问题在于在数据类中实现SQLData。 Oracles JDBC Developer's Guide声明以下内容:

用于集合的定制Java类称为定制集合类。定制集合类必须实现Oracle oracle.jdbc.OracleData接口。另外,定制类或伴随类必须实现oracle.jdbc.OracleDataFactory。 标准的java.sql.SQLData接口仅用于映射SQL对象类型。

一个工作示例:

public static final class DetailValues implements OracleData,OracleDataFactory {

  private List<String> details;

  @Override
  public Object toJDBCObject(Connection connection) throws SQLException {
    // TODO implement when type also used in PreparedStatement.setObject
    return null;
  }

  @Override
  public OracleData create(Object o,int i) throws SQLException {
    String[] details = (String[]) ((OracleArray) o).getArray();
    this.details = List.of(details);
    return this;
  }
}

,然后在遍历ResultSet的示例中使用ResultSet.getObject():

DetailValues detailValues = resultSet.getObject("details",DetailValues.class);

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-