Java导入片段:
import oracle.sql.StructDescriptor;
import oracle.sql.ARRAY;
import oracle.sql.ArrayDescriptor;
import oracle.sql.STRUCT;
PLSQL代码段:
one_user_type :
CREATE OR REPLACE TYPE one_user_type ABCD IS OBJECT
(
user_id VARCHAR2(120),
user_name VARCHAR2(120)
)
Java code snippet:
//连接conn;
Object[] userObject1 = new Object[] {
"101", "peter" };
StructDescriptor userDescriptor = StructDescriptor
.createDescriptor("one_user_type", conn);
// The below line takes 2.5 seconds approx to execute.
STRUCT user1 = new STRUCT(userDescriptor, conn, userObject1);
备注:ojdbc6.jar; jdk1.6,Oracle 11g
问题 - 任何想法为什么这需要花费太多时间,以及如何减少它?
编辑1 以回应@Lalit Kumar B评论:“太多时间”与实际查询执行相关。创建STRUCT是为了将记录表/对象表传递给PLSQL过程。实际的查询执行只需要93毫秒,当两个这样的过程被调用时,UI等待大约5秒,两者都采用对象表和我们需要创建STRUCT的位置。 因此2.5秒被认为是如此之多,我喜欢微调它。当我检查其他Java对象构造,转换,查询执行等的执行时间时,与这一个STRUCT创建相比,它们都非常低。 考虑到我的场景,我真的称之为5个存储过程,它将对象表作为参数,我进行了5次不同的调用来为每个创建STRUCT,仅创建STRUCT大约需要7秒。我们的想法是调用程序,获取结果,放入包装器并发回UI。
编辑2:[09/20] 为了最大限度地缩短时间,创建了一个单独的过程,它接受一个对象表并充当内部调用5个过程的包装器。因此,从Java代码,它只是一个存储过程调用。但是,STRUCT必须创建一次才能作为输入提供给包装程序。在多次运行时,它观察到STRUCT创建可以在2秒到8秒之间变化!我在创建STRUCT的方式上做错了吗?我从下面提供的链接检查了Oracle文档,但我无法弄清楚我是否偏离了。
如果您需要更多详细信息,请与我们联系。
更新:创建STRUCT对象和描述符 http://docs.oracle.com/cd/B12037_01/java.101/b10979/oraoot.htm
编辑3:加入解决方案[09/23] 接受的解决方案非常适合存储单个对象。如果要传递的对象表,案例适用如下:
PLSQL:
TYPE one_user_table_type IS TABLE OF one_user_type; // Table of Objects
爪哇:
UserType user = new UserType( "101", "Peter" );
ArrayDescriptor arrayDescriptor = ArrayDescriptor.createDescriptor(
"ONE_USER_TABLE_TYPE", conn);
UserType[] userArray = { user };
Array users = new ARRAY(arrayDescriptor, conn, userArray );
callableStatement.setArray(1, users);
答案 0 :(得分:4)
我遇到了同样的情况:STRUCT构造函数非常慢,因为Oracle在数据库中查询属性和一个完整的依赖关系链,这不仅是一个单独的数据库调用,它会减慢你的速度,而且还会查询一些系统词典。 这在STRUCT-Constructor的JavaDoc中有所暗示,因为约束和有效性在构造时测试,这只能通过整个对象定义的数据库查询来实现。
解决方案是使用自定义java-class并将值直接流入Procedure调用,这将完全消除构造函数时间!
看起来像这样:
public final class MyUserType implements SQLData
{
public String userId;
public String userName;
public MyUserType(){}
public MyUserType( final String userId, final String userName )
{
this.userId = userId;
this.userName = userName;
}
@Override
public String getSQLTypeName() throws SQLException
{
return "one_user_type";
}
@Override
public void readSQL( final SQLInput stream, final String typeName ) throws SQLException
{
userId = stream.readString();
userName = stream.readString();
}
@Override
public void writeSQL( final SQLOutput stream ) throws SQLException
{
stream.writeString( userId );
stream.writeString( userName );
}
}
然后你只需使用:
MyUserType param = new MyUserType( "010", "Peter" );
statement.setInputParameter( 1, param );
答案 1 :(得分:0)
也许您在打开和关闭连接时失去了很多时间,为什么不尝试创建单例连接并将其用于每个数据操作。