[英]Java SQLData - Cast to user object with a list/array?
I'm learning on how to use SQLData and having an issue with casting back to my object. 我正在学习如何使用SQLData,并且在投射回我的对象时遇到问题。
My Oracle Types looks something like this: 我的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;
);
And my Java looks like this: 我的Java看起来像这样:
public class Activities implements SQLData {
private String sqlType = "ACTIVITIES_T";
List<Activity> 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);
}
}
I've tried a few things in readSQL but I am not having much success - what am I missing? 我已经在readSQL中尝试了几件事,但没有取得太大的成功-我缺少什么?
I am calling a PLSQL stored procedure which has an OUT parameter of "activities_t" using JDBC: 我正在使用JDBC调用一个OUT参数为“ activities_t”的PLSQL存储过程:
Map map = connection.getTypeMap();
map.put("ACTIVITIES_T", Class.forName("Activities"));
connection.setTypeMap(map);
callableStatement = connection.prepareCall("{call GET_ACTIVITIES(?)}");
callableStatement.execute();
Thanks! 谢谢! Steve
史蒂夫
(most of the above is from memory as the code is at work...) (以上大部分内容都来自内存,因为代码正在起作用...)
You'll need to add a type mapping for the type ACTIVITY_T
as well as the one for ACTIVITIES_T
. 您需要为
ACTIVITY_T
和ACTIVITIES_T
类型添加一个类型映射。 It's not clear from your question whether you've already done this. 从您的问题尚不清楚您是否已经完成此操作。
Let's assume you've done this and created a class called Activity
which implements SQLData
as well. 假设您已完成此操作,并创建了一个名为
Activity
的类,该类也实现了SQLData
。 Once you've done that, the following should suffice to read the activity list within Activities
: 一旦你这样做了,下面应该足以阅读中的活动列表
Activities
:
public void readSQL(SQLInput stream, String typeName) throws SQLException {
Array array = stream.readArray();
this.list = new ArrayList<Activity>();
for (Object obj : (Object[])array.getArray()) {
list.add((Activity)obj);
}
}
Tips: 提示:
Unable to resolve type
error if your type name does not exactly match. Unable to resolve type
错误。 Oracle will uppercase your type name unless you double-quoted the name in its create statement. SCHEMA.TYPE_NAME
if the type isn't in your default schema. SCHEMA.TYPE_NAME
。 grant execute
on types if the user you are connecting with is not the owner. grant execute
对类型的grant execute
。 getArray()
will throw an exception when it tries to look for type metadata. getArray()
在尝试查找类型元数据时将引发异常。 getArray() getArray()
My solution is essentially the same as Luke's. 我的解决方案与Luke的解决方案基本相同。 However, I needed to provide a type mapping when getting the array:
array.getArray(typeMap)
You can also set a default type map on the Connection, but this didn't work for me. 但是,我需要在获取数组时提供类型映射:
array.getArray(typeMap)
您还可以在Connection上设置默认的类型映射,但这对我不起作用。
When calling getArray()
you get an array of the object type, ie the SQLData
implementation you created that represents activity_t
调用
getArray()
将获得对象类型的数组,即创建的代表activity_t
的SQLData
实现。
Here is a generic function you might find useful: 这是一个通用函数,您可能会发现它有用:
public static <T> List<T> listFromArray(Array array, Class<T> 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<T> list = new ArrayList<>(objectArray.length);
for (Object o : objectArray) {
list.add(typeClass.cast(o));
}
return list;
}
writeArray() writeArray()
Figuring out how to write an array was frustrating, Oracle APIs require a Connection to create an Array, but you don't have an obvious Connection in the context of writeSQL(SQLOutput sqlOutput)
. 弄清楚如何编写数组令人沮丧,Oracle API需要使用Connection才能创建数组,但是在
writeSQL(SQLOutput sqlOutput)
上下文中没有明显的Connection。 Fortunately, this blog has a trick/hack to get the OracleConnection
, which I've used here. 幸运的是, 此博客有一个技巧/技巧来获取
OracleConnection
,我在这里使用了它。
When you create an array with createOracleArray()
you specify the list type for the type name, NOT the object type. 当使用
createOracleArray()
创建数组时,请为类型名称而不是对象类型指定列表类型。 ie activity_list_t
即
activity_list_t
Here's a generic function for writing arrays. 这是用于编写数组的通用函数。 In your case,
listType
would be "activity_list_t"
and you would pass in a List<Activity>
在您的情况下,
listType
将为"activity_list_t"
并且您将传递List<Activity>
public static <T> void writeArrayFromList(SQLOutput sqlOutput, String listType, @Nullable List<T> 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);
}
Note: at one point I thought setTypeMap
was required, but now when I remove that line my code still works, so I'm not sure if it's necessary. 注意:曾经我以为
setTypeMap
是必需的,但是现在当我删除该行时,我的代码仍然有效,所以我不确定是否有必要。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.