Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用JDBC以用户定义的记录作为IN参数调用PL/SQL过程_Java_Oracle_Exception_Jdbc_Records - Fatal编程技术网

Java 使用JDBC以用户定义的记录作为IN参数调用PL/SQL过程

Java 使用JDBC以用户定义的记录作为IN参数调用PL/SQL过程,java,oracle,exception,jdbc,records,Java,Oracle,Exception,Jdbc,Records,我试图调用以下PL/SQL过程,该过程将用户定义的记录类型作为中的参数 ——用户定义的记录 类型EMP_REC为记录 ( id员工。员工id%类型, 员工姓名。姓氏%type, 部门名称部门。部门名称%type, 作业标题作业。作业标题%type, 薪资员工。薪资%类型, 经理id员工。员工id%类型, 城市位置。城市%类型, 给员工打电话。电话号码%type ); 以下是用户定义记录的定义: --用途:打印员工记录中的所有员工信息 --示例:接受记录类型参数的过程 程序打印员工所有详细信息(

我试图调用以下PL/SQL过程,该过程将用户定义的记录类型作为中的参数

——用户定义的记录
类型EMP_REC为记录
(
id员工。员工id%类型,
员工姓名。姓氏%type,
部门名称部门。部门名称%type,
作业标题作业。作业标题%type,
薪资员工。薪资%类型,
经理id员工。员工id%类型,
城市位置。城市%类型,
给员工打电话。电话号码%type
);
以下是用户定义记录的定义:

--用途:打印员工记录中的所有员工信息
--示例:接受记录类型参数的过程
程序打印员工所有详细信息(员工1 emp记录,emp记录字符串输出VARCHAR2)
我查看了表明JDBC不支持记录之类的复合类型的示例:

在网上搜索使我很快找到了工作

以下是我试图将用户定义的记录传递给PL/SQL过程的代码:

     public String printEmployeeAllDetails()
     {
         Connection conn = null;
         CallableStatement callStmt = null;
         String empDetails = null;

         try 
         {
            // Register the Jdbc Driver
            // Class.forName(JDBC_DRIVER_ORACLE);

            // Create a Database Connection
            conn = DriverManager.getConnection(DB_URL,DB_USER,DB_PWD);

            // Create a query string
            String callProc = "{call HR.EMP_PKG.print_employee_all_details( ? , ?) }";

            // Create a Callable Statement
            callStmt = conn.prepareCall(callProc);


            // Create descriptor for the Oracle Record type "EMP_REC" required
            StructDescriptor recDescriptor = StructDescriptor.createDescriptor("EMP_REC", conn);

            // Stage values for each field in the Oracle record in an array
            Object[] javaEmpRec = new Object[8];


            // Populate those values in the Array
            javaEmpRec[0] = 100;
            javaEmpRec[1] = "Joe Matthew";
            javaEmpRec[2] = "IT";
            javaEmpRec[3] = "Senior Consultant";
            javaEmpRec[4] = 20000;
            javaEmpRec[5] = 101;
            javaEmpRec[6] = "lombard";
            javaEmpRec[7] = "222333444";

            // Cast the java array into the oracle record type
            STRUCT oracleEmpRec = new STRUCT(recDescriptor , conn , javaEmpRec);


            // Bind Values to the IN parameter
            callStmt.setObject(1, oracleEmpRec);

            // Register OUT parameter
            callStmt.registerOutParameter(2, java.sql.Types.VARCHAR);

            // Execute the Callable Statement
            callStmt.execute();

            // Retrieve the value from the OUT parameter
            empDetails = callStmt.getString(2);
            System.out.println("Emp Details: " + empDetails);

         } 
         catch (SQLException se) 
         {
            System.out.println("Exception occured in the database");
            System.out.println("Exception message: "+ se.getMessage());
            System.out.println("Database error code: "+ se.getErrorCode());
            se.printStackTrace();
         }
         finally
         {
            // Clean up
            if(callStmt != null)
            {
                try
                {
                    callStmt.close();
                } 
                catch (SQLException se2) 
                {
                    se2.printStackTrace();
                }
            }

            if(conn != null)
            {
                try
                {
                    conn.close();
                } 
                catch (SQLException se2) 
                {
                    se2.printStackTrace();
                }
            }
         }

         return empDetails;
     }
运行此代码时,我遇到以下异常:

Exception occured in the database
Exception message: invalid name pattern: HR.EMP_REC
java.sql.SQLException: invalid name pattern: HR.EMP_REC
    at oracle.jdbc.oracore.OracleTypeADT.initMetadata(OracleTypeADT.java:554)
    at oracle.jdbc.oracore.OracleTypeADT.init(OracleTypeADT.java:471)
    at oracle.sql.StructDescriptor.initPickler(StructDescriptor.java:324)
    at oracle.sql.StructDescriptor.<init>(StructDescriptor.java:254)
    at oracle.sql.StructDescriptor.createDescriptor(StructDescriptor.java:135)
    at oracle.sql.StructDescriptor.createDescriptor(StructDescriptor.java:103)
Database error code: 17074
    at oracle.sql.StructDescriptor.createDescriptor(StructDescriptor.java:72)
    at com.rolta.HrManager.printEmployeeAllDetails(HrManager.java:1214)
    at com.rolta.HrManager.main(HrManager.java:1334)
数据库中发生异常 异常消息:无效的名称模式:HR.EMP\u REC java.sql.SQLException:无效的名称模式:HR.EMP\u REC 位于oracle.jdbc.oracore.OracleTypeADT.initMetadata(OracleTypeADT.java:554) 位于oracle.jdbc.oracore.OracleTypeADT.init(OracleTypeADT.java:471) 位于oracle.sql.StructDescriptor.initPickler(StructDescriptor.java:324) 位于oracle.sql.StructDescriptor.(StructDescriptor.java:254) 位于oracle.sql.StructDescriptor.createDescriptor(StructDescriptor.java:135) 位于oracle.sql.StructDescriptor.createDescriptor(StructDescriptor.java:103) 数据库错误代码:17074 位于oracle.sql.StructDescriptor.createDescriptor(StructDescriptor.java:72) 位于com.rolta.HrManager.printEmployeeAllDetails(HrManager.java:1214) 位于com.rolta.HrManager.main(HrManager.java:1334) 我正在使用
ojdbc6.jar
标题下的第一个jar
JDBCThin for All Platform
用于
Oracle Database 11g Release 2(11.2.0.4)JDBC驱动程序


我想知道是否允许将用户定义的记录(如参数中所示)传递给PL/SQL过程?是否有人尝试过上述操作?

是的,可以使用JDBC将用户定义的数据类型作为参数传递。但它不能是一个
记录
。它必须是架构级别的对象,例如

创建类型EMP\u REC作为对象
(
id员工。员工id%类型,
员工姓名。姓氏%type,
部门名称部门。部门名称%type,
作业标题作业。作业标题%type,
薪资员工。薪资%类型,
经理id员工。员工id%类型,
城市位置。城市%类型,
给员工打电话。电话号码%type
);

在PL/SQL中,您可以将对记录的引用更改为新的对象类型,或者如果无法更改其余代码,您可以编写一个快速的小翻译器函数将对象类型转换为记录类型。

无法传递记录。因为它必须是要引用的SQL对象,而不是纯粹的
PL/SQL
对象

创建一个对象就像

——用户定义的记录
创建类型EMP_REC作为对象
(
身份证号码,
名称VARCHAR2(100),
部门名称。。。,
职位。。,
薪水
经理。。,
城市
电话。。。
);

但这又是一种痛苦。您不能在此处使用
类型
属性。因为类型不能以这种方式具有依赖关系而是指定确切的数据类型。

如果可以执行匿名PL/SQL块(据我所知,这是可能的),则可以执行以下操作:

declare
  rec EMP_REC;
begin
  rec.id := :ID;
  rec.name:= :NAME;
  -- and so on, rest of fields of record...
  ...
  my_procedure(rec);
end;
/
在这种情况下,您不需要创建新的数据库对象或更改现有的数据库对象。您只需要传递参数值来填充记录。

我想补充一下,这建议您可以通过JDBC使用匿名PL/SQL块,并手动和显式地组合
记录类型。如果您正在为单个存储过程寻找解决方案,那么手动编写该块就可以了。但是,如果您正在寻找一种通用解决方案,为所有具有
IN
OUT
IN-OUT
记录
参数的过程生成代码,那么您可能应该编写一个基于以下查询生成存根的代码生成器

选择
x、 键入\u所有者、x.TYPE\u名称、x.TYPE\u子名称、a.ARGUMENT\u名称属性\u名称、,
a、 序列属性号,a.TYPE属性所有者属性类型所有者,
nvl2(a.TYPE\u子名称,a.TYPE\u名称,NULL)包\u名称,
合并(a.TYPE\u子名称、a.TYPE\u名称、a.DATA\u类型)属性类型\u名称,
a、 数据长度长度,a.数据精度,a.数据刻度
从SYS.ALL_参数a
加入(
挑选
a、 键入\u所有者,a.TYPE\u名称,a.TYPE\u子名称,
MIN(a.OWNER)KEEP(由a.OWNER ASC、a.PACKAGE名称ASC、a.SUBPROGRAM\u ID ASC、a.SEQUENCE ASC排序)OWNER,
MIN(a.PACKAGE\u NAME)KEEP(由a.OWNER ASC、a.PACKAGE\u NAME ASC、a.SUBPROGRAM\u ID ASC、a.SEQUENCE ASC排序的稠密级)PACKAGE\u NAME,
MIN(a.子程序ID)KEEP(a.所有者ASC、a.包名称ASC、a.子程序ID ASC、a.序列ASC的稠密等级一级)子程序ID,
最小(a.SEQUENCE)保持(a.OWNER ASC、a.PACKAGE名称ASC、a.SUBPROGRAM ID ASC、a.SEQUENCE ASC的密集排列第一顺序)序列,
MIN(下一个同级)KEEP(a.OWNER ASC、a.PACKAGE NAME ASC、a.SUBPROGRAM ID ASC、a.SEQUENCE ASC的密集排名第一顺序),
最小(a.DATA\u LEVEL)保持(a.OWNER ASC、a.PACKAGE\u NAME ASC、a.SUBPROGRAM\u ID ASC、a.SEQUENCE ASC的密集排序第一顺序)数据\u LEVEL
从(
挑选
导程(a序列,1,a序列)超过(
按a.OWNER、a.PACKAGE\u NAME、a.SUBPROGRAM\u ID、a.DATA\u级别划分
按a.ASC顺序订购
)下一个兄弟姐妹,
a、 键入\u所有者,a.TYPE\u名称,a.TYPE\u子名称,a.OWNER,a.PACKAGE\u名称,
a、 子程序ID,a.SE