Java SQLData – 使用列表/数组转换为用户对象?

我正在学习如何使用SQLData并且在回送到我的对象时遇到问题。

我的Oracle类型看起来像这样:

CREATE OR REPLACE TYPE activities_t AS OBJECT ( list activity_list_t; ); CREATE OR REPLACE TYPE activity_list_t AS TABLE OF activity_t; CREATE OR REPLACE TYPE activity_t AS OBJECT ( startDate DATE; endDate DATE; ); 

我的Java看起来像这样:

 public class Activities implements SQLData { private String sqlType = "ACTIVITIES_T"; List list; // must have default ctor! public Activities() { } public String getSQLTypeName() throws SQLException { return sqlType; } public List getList() { return list; } public void setList(List list) { this.list = list; } public void readSQL(SQLInput stream, String typeName) throws SQLException { Array a = stream.readArray(); // :( } public void writeSQL(SQLOutput stream) throws SQLException { // stream.writeArray(this.list); } } 

我在readSQL中尝试过一些东西但是我没有取得多大成功 – 我错过了什么?

我正在使用JDBC调用一个PLSQL存储过程,其OUT参数为“activities_t”:

 Map map = connection.getTypeMap(); map.put("ACTIVITIES_T", Class.forName("Activities")); connection.setTypeMap(map); callableStatement = connection.prepareCall("{call GET_ACTIVITIES(?)}"); callableStatement.execute(); 

谢谢! 史蒂夫

(以上大部分都来自内存,因为代码在工作……)

您需要为ACTIVITY_T类型添加类型映射,并为ACTIVITIES_T添加类型映射。 你的问题不清楚你是否已经这样做了。

让我们假设你已经完成了这个并创建了一个名为Activity的类,它也实现了SQLData 。 完成后,以下内容应足以阅读活动中的活动列表:

  public void readSQL(SQLInput stream, String typeName) throws SQLException { Array array = stream.readArray(); this.list = new ArrayList(); for (Object obj : (Object[])array.getArray()) { list.add((Activity)obj); } } 

提示:

  • JDBC API在类型名称方面区分大小写; 如果您的类型名称不完全匹配,您将看到Unable to resolve type错误。 除非在其create语句中双引号,否则Oracle将大写您的类型名称。
  • 如果类型不在默认架构中,则可能需要指定SCHEMA.TYPE_NAME
  • 如果您要连接的用户不是所有者,请记住在类型上grant execute
    如果您对包执行了而不是类型,则getArray()在尝试查找类型元数据时会抛出exception。

的getArray()

我的解决方案与Luke的解决方案基本相同。 但是,我需要在获取数组时提供类型映射: array.getArray(typeMap)您还可以在Connection上设置默认类型映射,但这对我不起作用。

调用getArray()您将获得一个对象类型的数组,即您创建的表示activity_tSQLData实现

这是一个您可能会觉得有用的通用函数:

 public static  List listFromArray(Array array, Class typeClass) throws SQLException { if (array == null) { return Collections.emptyList(); } // Java does not allow casting Object[] to T[] final Object[] objectArray = (Object[]) array.getArray(getTypeMap()); List list = new ArrayList<>(objectArray.length); for (Object o : objectArray) { list.add(typeClass.cast(o)); } return list; } 

writeArray()

弄清楚如何编写数组是令人沮丧的,Oracle API需要一个Connection来创建一个Array,但是在writeSQL(SQLOutput sqlOutput)的上下文中没有明显的Connection。 幸运的是, 这个博客有一个技巧/黑客来获取我在这里使用过的OracleConnection

使用createOracleArray()创建数组时,请指定类型名称的列表类型 ,而不是对象类型。 即activity_list_t

这是编写数组的通用函数。 在您的情况下, listType将是"activity_list_t" ,您将传入List

 public static  void writeArrayFromList(SQLOutput sqlOutput, String listType, @Nullable List list) throws SQLException { final OracleSQLOutput out = (OracleSQLOutput) sqlOutput; OracleConnection conn = (OracleConnection) out.getSTRUCT().getJavaSqlConnection(); conn.setTypeMap(getTypeMap()); // not needed? if (list == null) { list = Collections.emptyList(); } final Array array = conn.createOracleArray(listType, list.toArray()); out.writeArray(array); } 

注意:有一点我认为setTypeMap是必需的,但现在当我删除该行时,我的代码仍然有效,所以我不确定是否有必要。