You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在实现SQLData的Java类Country中映射嵌套表CITY UDT?

实现Oracle嵌套表UDT到Java SQLData类的映射

首先明确数据库端的UDT定义(请确保与你的实际定义一致):

-- 定义CITY对象类型
CREATE TYPE CITY AS OBJECT (
    city_id NUMBER,
    city_name VARCHAR2(100)
);
/
-- 定义嵌套表类型,用于存储多个CITY
CREATE TYPE CITY_LIST AS TABLE OF CITY;
/
-- 定义COUNTRY对象类型,包含嵌套表属性
CREATE TYPE COUNTRY AS OBJECT (
    country_id NUMBER,
    country_name VARCHAR2(100),
    cities CITY_LIST
);
/

接下来分两步实现Java类的映射:

1. 实现CITY UDT对应的Java类

嵌套表的元素是CITY UDT,需先创建实现SQLData接口的City类,用于单个城市对象的映射:

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

public class City implements SQLData {
    private Integer cityId;
    private String cityName;
    // 必须和数据库中CITY UDT的名称完全一致
    private static final String SQL_TYPE = "CITY";

    @Override
    public String getSQLTypeName() throws SQLException {
        return SQL_TYPE;
    }

    @Override
    public void readSQL(SQLInput stream, String typeName) throws SQLException {
        // 严格按照数据库UDT定义的属性顺序读取
        cityId = stream.readInt();
        cityName = stream.readString();
    }

    @Override
    public void writeSQL(SQLOutput stream) throws SQLException {
        // 严格按照数据库UDT定义的属性顺序写入
        stream.writeInt(cityId);
        stream.writeString(cityName);
    }

    // 构造方法、Getter/Setter
    public City() {}
    public City(Integer cityId, String cityName) {
        this.cityId = cityId;
        this.cityName = cityName;
    }

    public Integer getCityId() { return cityId; }
    public void setCityId(Integer cityId) { this.cityId = cityId; }
    public String getCityName() { return cityName; }
    public void setCityName(String cityName) { this.cityName = cityName; }
}

2. 实现COUNTRY UDT对应的Java类,处理嵌套表属性

在Country类中用List<City>存储嵌套的城市数据,通过java.sql.Array完成与数据库嵌套表的转换:

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class Country implements SQLData {
    private Integer countryId;
    private String countryName;
    // 存储嵌套城市的List
    private List<City> cities;
    // 数据库中COUNTRY UDT的名称
    private static final String SQL_TYPE = "COUNTRY";
    // 数据库中嵌套表类型CITY_LIST的名称
    private static final String CITY_LIST_TYPE = "CITY_LIST";

    @Override
    public String getSQLTypeName() throws SQLException {
        return SQL_TYPE;
    }

    @Override
    public void readSQL(SQLInput stream, String typeName) throws SQLException {
        // 按UDT属性顺序读取
        countryId = stream.readInt();
        countryName = stream.readString();
        // 读取嵌套表为Array对象
        Array cityArray = stream.readArray();
        if (cityArray != null) {
            // 将Array转换为City数组,再转为List
            Object[] cityObjs = (Object[]) cityArray.getArray();
            cities = new ArrayList<>();
            for (Object obj : cityObjs) {
                cities.add((City) obj);
            }
            // 释放Array资源
            cityArray.free();
        } else {
            cities = new ArrayList<>();
        }
    }

    @Override
    public void writeSQL(SQLOutput stream) throws SQLException {
        // 按UDT属性顺序写入
        stream.writeInt(countryId);
        stream.writeString(countryName);
        if (cities != null && !cities.isEmpty()) {
            // 获取数据库连接(若使用连接池,应从池获取并归还,不要直接关闭)
            Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@//your-host:port/your-service", "user", "password");
            // 将List<City>转为Oracle Array,指定嵌套表类型名称
            Array cityArray = conn.createArrayOf(CITY_LIST_TYPE, cities.toArray());
            stream.writeArray(cityArray);
            // 释放资源
            cityArray.free();
            conn.close();
        } else {
            // 写入空嵌套表
            stream.writeArray(null);
        }
    }

    // 构造方法、Getter/Setter
    public Country() {}
    public Country(Integer countryId, String countryName, List<City> cities) {
        this.countryId = countryId;
        this.countryName = countryName;
        this.cities = cities;
    }

    public Integer getCountryId() { return countryId; }
    public void setCountryId(Integer countryId) { this.countryId = countryId; }
    public String getCountryName() { return countryName; }
    public void setCountryName(String countryName) { this.countryName = countryName; }
    public List<City> getCities() { return cities; }
    public void setCities(List<City> cities) { this.cities = cities; }
}

关键注意事项

  • UDT名称匹配:Java类中定义的SQL_TYPE必须和数据库中UDT的名称完全一致,大小写敏感(若数据库用双引号创建了区分大小写的UDT,需严格对应)。
  • 属性顺序一致:readSQL和writeSQL中读写属性的顺序必须和数据库UDT定义的属性顺序完全相同,否则会导致数据错位。
  • 连接管理:写入嵌套表时获取Connection,若使用连接池,不要直接调用close(),应将连接归还到池子里,避免资源泄漏。
  • 驱动兼容性:确保使用的Oracle JDBC驱动(ojdbc8及以上版本)和数据库版本兼容,避免出现类型转换异常。

内容的提问来源于stack exchange,提问作者errorrelativo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 21:40:59