在 JOOQ 中使用 PL/SQL 函数
Use PL/SQL Function in JOOQ
我需要调用 PL/SQL 函数,return 一个 table 形式的对象类型。
基本上像:
select * from TABLE(get_druck_variablen(123456);
到目前为止,我在 JOOQ 中使用本机查询并且有效:
final Result<Record> result = create.fetch("select * from TABLE(myschema.get_druck_variablen(" + id + "))");
但我想在 JOOQ 中正确地完成它。
1) 我来到这里:
final GetDruckVariablen getDruckVariablen = new GetDruckVariablen();
getDruckVariablen.setPId(id);
getDruckVariablen.execute();
但后来我遇到了这个异常
Method threw 'java.lang.NullPointerException' exception. Cannot evaluate de.company.jooq.routines.GetDruckVariablen.toString()
2) 然后我尝试了这个:
final TabOtDruckVariablenRecord getDruckVariablen = Routines.getDruckVariablen(create.configuration(), id).;
然后我得到了这个异常:
Caused by: org.springframework.jdbc.BadSqlGrammarException: jOOQ; bad SQL grammar [select "array_table"."COLUMN_VALUE" from table ("MYSCHEMA"."GET_DRUCK_VARIABLEN"(?)) "array_table"]; nested exception is java.sql.SQLSyntaxErrorException: ORA-00904: "array_table"."COLUMN_VALUE": ungültiger Bezeichner
有关信息,这是我的 PL/SQL 函数:
create or replace FUNCTION get_druck_variablen(p_id IN vk_types.t_id) RETURN myschema.tab_ot_druck_variablen
PIPELINED
IS
....
BEGIN
END get_druck_variablen;
对象类型:
create or replace TYPE ot_druck_variablen FORCE AS OBJECT
(
ob_id NUMBER(9, 0),
ob_txv_name VARCHAR2(100),
ob_txv_wert VARCHAR2(2000)
)
Table类型:
create or replace TYPE tab_ot_druck_variablen AS TABLE OF myschema.ot_druck_variablen
我真的很希望有人能帮助我。
提前致谢。
此致
伊万
为以下问题的答案添加了 Stake 跟踪:
final GetDruckVariablen getDruckVariablen = new GetDruckVariablen();
getDruckVariablen.setPId(id);
getDruckVariablen.execute(dslContext.configuration());
堆栈跟踪:
2017-08-16 22:25:16.039 ERROR 4928 --- [ restartedMain] o.s.boot.SpringApplication : Application startup failed
java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:735)
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:716)
at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:703)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:304)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107)
at de.mycompany.druckauftrag.DruckAuftragApplication.main(DruckAuftragApplication.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: org.springframework.jdbc.BadSqlGrammarException: jOOQ; bad SQL grammar [select "array_table"."COLUMN_VALUE" from table ("MYSCHEMA"."GET_DRUCK_VARIABLEN"(?)) "array_table"]; nested exception is java.sql.SQLSyntaxErrorException: ORA-00904: "array_table"."COLUMN_VALUE": ungültiger Bezeichner
at org.jooq_3.9.3.ORACLE.debug(Unknown Source)
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:231)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73)
at org.springframework.boot.autoconfigure.jooq.JooqExceptionTranslator.translate(JooqExceptionTranslator.java:92)
at org.springframework.boot.autoconfigure.jooq.JooqExceptionTranslator.handle(JooqExceptionTranslator.java:81)
at org.springframework.boot.autoconfigure.jooq.JooqExceptionTranslator.exception(JooqExceptionTranslator.java:54)
at org.jooq.impl.ExecuteListeners.exception(ExecuteListeners.java:245)
at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:364)
at org.jooq.impl.AbstractResultQuery.fetch(AbstractResultQuery.java:315)
at org.jooq.impl.SelectImpl.fetch(SelectImpl.java:2708)
at org.jooq.impl.AbstractRoutine.executeSelectFromOracle(AbstractRoutine.java:362)
at org.jooq.impl.AbstractRoutine.execute(AbstractRoutine.java:318)
at org.jooq.impl.AbstractRoutine.execute(AbstractRoutine.java:287)
at de.mycompany.druckauftrag.container.cask.KfzParam.getDruckVariablen(KfzParam.java:59)
at de.mycompany.druckauftrag.container.cask.KfzParam.befuelleVariablen(KfzParam.java:36)
at de.mycompany.druckauftrag.service.DokumentService.erzeugeDokument(DokumentService.java:55)
at de.mycompany.druckauftrag.service.XmlCreator.createXml(XmlCreator.java:33)
at de.mycompany.druckauftrag.DruckAuftragApplication.run(DruckAuftragApplication.java:46)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:732)
... 11 common frames omitted
Caused by: java.sql.SQLSyntaxErrorException: ORA-00904: "array_table"."COLUMN_VALUE": ungültiger Bezeichner
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:450)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:399)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1059)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:522)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:257)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:587)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:225)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:53)
at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:774)
at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:925)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1111)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:4798)
at oracle.jdbc.driver.OraclePreparedStatement.execute(OraclePreparedStatement.java:4901)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.execute(OraclePreparedStatementWrapper.java:1385)
at sun.reflect.GeneratedMethodAccessor62.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.tomcat.jdbc.pool.StatementFacade$StatementProxy.invoke(StatementFacade.java:114)
at com.sun.proxy.$Proxy94.execute(Unknown Source)
at org.jooq.tools.jdbc.DefaultPreparedStatement.execute(DefaultPreparedStatement.java:195)
at org.jooq.impl.AbstractResultQuery.execute(AbstractResultQuery.java:270)
at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:349)
... 22 common frames omitted
我怀疑您 运行 遇到了错误(现在可能已修复)。一旦我知道您使用的是哪个 jOOQ 版本,我将用 link 更新我对相关 GitHub 问题的回答。
关于 1) 和 NullPointerException
您尝试 1 中出现 NPE 的可能原因:
final GetDruckVariablen getDruckVariablen = new GetDruckVariablen();
getDruckVariablen.setPId(id);
getDruckVariablen.execute();
... 可能是因为您没有将 Configuration
传递给 execute()
方法。 Configuration
less 方法假定您的例程调用以前是 "attached" 到 Configuration
。但最好明确地传递它:
getDruckVariablen.execute(configuration);
关于您的本机查询用法的旁注:
你肯定知道这一点,但我不得不为未来的读者提及它。您对 jOOQ plain SQL API 的使用暴露了一定的 SQL 注入风险,此外还会给游标缓存带来压力:
final Result<Record> result = create.fetch(
"select * from TABLE(myschema.get_druck_variablen(" + id + "))");
最好使用绑定变量,这对于普通 SQL 也是完全可能的:
final Result<Record> result = create.fetch(
"select * from TABLE(myschema.get_druck_variablen(?))", id);
我需要调用 PL/SQL 函数,return 一个 table 形式的对象类型。 基本上像:
select * from TABLE(get_druck_variablen(123456);
到目前为止,我在 JOOQ 中使用本机查询并且有效:
final Result<Record> result = create.fetch("select * from TABLE(myschema.get_druck_variablen(" + id + "))");
但我想在 JOOQ 中正确地完成它。
1) 我来到这里:
final GetDruckVariablen getDruckVariablen = new GetDruckVariablen();
getDruckVariablen.setPId(id);
getDruckVariablen.execute();
但后来我遇到了这个异常
Method threw 'java.lang.NullPointerException' exception. Cannot evaluate de.company.jooq.routines.GetDruckVariablen.toString()
2) 然后我尝试了这个:
final TabOtDruckVariablenRecord getDruckVariablen = Routines.getDruckVariablen(create.configuration(), id).;
然后我得到了这个异常:
Caused by: org.springframework.jdbc.BadSqlGrammarException: jOOQ; bad SQL grammar [select "array_table"."COLUMN_VALUE" from table ("MYSCHEMA"."GET_DRUCK_VARIABLEN"(?)) "array_table"]; nested exception is java.sql.SQLSyntaxErrorException: ORA-00904: "array_table"."COLUMN_VALUE": ungültiger Bezeichner
有关信息,这是我的 PL/SQL 函数:
create or replace FUNCTION get_druck_variablen(p_id IN vk_types.t_id) RETURN myschema.tab_ot_druck_variablen
PIPELINED
IS
....
BEGIN
END get_druck_variablen;
对象类型:
create or replace TYPE ot_druck_variablen FORCE AS OBJECT
(
ob_id NUMBER(9, 0),
ob_txv_name VARCHAR2(100),
ob_txv_wert VARCHAR2(2000)
)
Table类型:
create or replace TYPE tab_ot_druck_variablen AS TABLE OF myschema.ot_druck_variablen
我真的很希望有人能帮助我。
提前致谢。
此致
伊万
为以下问题的答案添加了 Stake 跟踪:
final GetDruckVariablen getDruckVariablen = new GetDruckVariablen();
getDruckVariablen.setPId(id);
getDruckVariablen.execute(dslContext.configuration());
堆栈跟踪:
2017-08-16 22:25:16.039 ERROR 4928 --- [ restartedMain] o.s.boot.SpringApplication : Application startup failed
java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:735)
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:716)
at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:703)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:304)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107)
at de.mycompany.druckauftrag.DruckAuftragApplication.main(DruckAuftragApplication.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: org.springframework.jdbc.BadSqlGrammarException: jOOQ; bad SQL grammar [select "array_table"."COLUMN_VALUE" from table ("MYSCHEMA"."GET_DRUCK_VARIABLEN"(?)) "array_table"]; nested exception is java.sql.SQLSyntaxErrorException: ORA-00904: "array_table"."COLUMN_VALUE": ungültiger Bezeichner
at org.jooq_3.9.3.ORACLE.debug(Unknown Source)
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:231)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73)
at org.springframework.boot.autoconfigure.jooq.JooqExceptionTranslator.translate(JooqExceptionTranslator.java:92)
at org.springframework.boot.autoconfigure.jooq.JooqExceptionTranslator.handle(JooqExceptionTranslator.java:81)
at org.springframework.boot.autoconfigure.jooq.JooqExceptionTranslator.exception(JooqExceptionTranslator.java:54)
at org.jooq.impl.ExecuteListeners.exception(ExecuteListeners.java:245)
at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:364)
at org.jooq.impl.AbstractResultQuery.fetch(AbstractResultQuery.java:315)
at org.jooq.impl.SelectImpl.fetch(SelectImpl.java:2708)
at org.jooq.impl.AbstractRoutine.executeSelectFromOracle(AbstractRoutine.java:362)
at org.jooq.impl.AbstractRoutine.execute(AbstractRoutine.java:318)
at org.jooq.impl.AbstractRoutine.execute(AbstractRoutine.java:287)
at de.mycompany.druckauftrag.container.cask.KfzParam.getDruckVariablen(KfzParam.java:59)
at de.mycompany.druckauftrag.container.cask.KfzParam.befuelleVariablen(KfzParam.java:36)
at de.mycompany.druckauftrag.service.DokumentService.erzeugeDokument(DokumentService.java:55)
at de.mycompany.druckauftrag.service.XmlCreator.createXml(XmlCreator.java:33)
at de.mycompany.druckauftrag.DruckAuftragApplication.run(DruckAuftragApplication.java:46)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:732)
... 11 common frames omitted
Caused by: java.sql.SQLSyntaxErrorException: ORA-00904: "array_table"."COLUMN_VALUE": ungültiger Bezeichner
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:450)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:399)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1059)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:522)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:257)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:587)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:225)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:53)
at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:774)
at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:925)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1111)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:4798)
at oracle.jdbc.driver.OraclePreparedStatement.execute(OraclePreparedStatement.java:4901)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.execute(OraclePreparedStatementWrapper.java:1385)
at sun.reflect.GeneratedMethodAccessor62.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.tomcat.jdbc.pool.StatementFacade$StatementProxy.invoke(StatementFacade.java:114)
at com.sun.proxy.$Proxy94.execute(Unknown Source)
at org.jooq.tools.jdbc.DefaultPreparedStatement.execute(DefaultPreparedStatement.java:195)
at org.jooq.impl.AbstractResultQuery.execute(AbstractResultQuery.java:270)
at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:349)
... 22 common frames omitted
我怀疑您 运行 遇到了错误(现在可能已修复)。一旦我知道您使用的是哪个 jOOQ 版本,我将用 link 更新我对相关 GitHub 问题的回答。
关于 1) 和 NullPointerException
您尝试 1 中出现 NPE 的可能原因:
final GetDruckVariablen getDruckVariablen = new GetDruckVariablen();
getDruckVariablen.setPId(id);
getDruckVariablen.execute();
... 可能是因为您没有将 Configuration
传递给 execute()
方法。 Configuration
less 方法假定您的例程调用以前是 "attached" 到 Configuration
。但最好明确地传递它:
getDruckVariablen.execute(configuration);
关于您的本机查询用法的旁注:
你肯定知道这一点,但我不得不为未来的读者提及它。您对 jOOQ plain SQL API 的使用暴露了一定的 SQL 注入风险,此外还会给游标缓存带来压力:
final Result<Record> result = create.fetch(
"select * from TABLE(myschema.get_druck_variablen(" + id + "))");
最好使用绑定变量,这对于普通 SQL 也是完全可能的:
final Result<Record> result = create.fetch(
"select * from TABLE(myschema.get_druck_variablen(?))", id);