java - Hibernate:如何调用返回 varchar 的存储函数?

标签 java oracle hibernate stored-procedures

我正在尝试使用 Hibernate 从 Java 调用 Oracle9i 数据库中的遗留存储函数。该函数声明如下:

create or replace FUNCTION Transferlocation_Fix (mnemonic_code IN VARCHAR2)
   RETURN VARCHAR2

经过几次失败的尝试和广泛的谷歌搜索后,我找到了 this thread在建议这样映射的 Hibernate 论坛上:

<sql-query name="TransferLocationFix" callable="true">
    <return-scalar column="retVal" type="string"/>
    select Transferlocation_Fix(:mnemonic) as retVal from dual
</sql-query>

我执行它的代码是

    Query query = session.getNamedQuery("TransferLocationFix");
    query.setParameter("mnemonic", "FC3");
    String result = (String) query.uniqueResult();

结果日志是

DEBUG (org.hibernate.jdbc.AbstractBatcher:366) -  - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
DEBUG (org.hibernate.SQL:401) -  - select Transferlocation_Fix(?) as retVal from dual
TRACE (org.hibernate.jdbc.AbstractBatcher:484) -  - preparing statement
TRACE (org.hibernate.type.StringType:133) -  - binding 'FC3' to parameter: 2
TRACE (org.hibernate.type.StringType:133) -  - binding 'FC3' to parameter: 2

java.lang.NullPointerException
at oracle.jdbc.ttc7.TTCAdapter.newTTCType(TTCAdapter.java:300)
at oracle.jdbc.ttc7.TTCAdapter.createNonPlsqlTTCColumnArray(TTCAdapter.java:270)
at oracle.jdbc.ttc7.TTCAdapter.createNonPlsqlTTCDataSet(TTCAdapter.java:231)
at oracle.jdbc.ttc7.TTC7Protocol.doOall7(TTC7Protocol.java:1924)
at oracle.jdbc.ttc7.TTC7Protocol.parseExecuteDescribe(TTC7Protocol.java:850)
at oracle.jdbc.driver.OracleStatement.doExecuteQuery(OracleStatement.java:2599)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:2963)
at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:658)
at oracle.jdbc.driver.OraclePreparedStatement.execute(OraclePreparedStatement.java:736)
at com.mchange.v2.c3p0.impl.NewProxyCallableStatement.execute(NewProxyCallableStatement.java:3044)
at org.hibernate.dialect.Oracle8iDialect.getResultSet(Oracle8iDialect.java:379)
at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:193)
at org.hibernate.loader.Loader.getResultSet(Loader.java:1784)
at org.hibernate.loader.Loader.doQuery(Loader.java:674)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236)
at org.hibernate.loader.Loader.doList(Loader.java:2220)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2104)
at org.hibernate.loader.Loader.list(Loader.java:2099)
at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:289)
at org.hibernate.impl.SessionImpl.listCustomQuery(SessionImpl.java:1695)
at org.hibernate.impl.AbstractSessionImpl.list(AbstractSessionImpl.java:142)
at org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:152)
at org.hibernate.impl.AbstractQueryImpl.uniqueResult(AbstractQueryImpl.java:811)
at com.my.project.SomeClass.method(SomeClass.java:202)
...

有什么线索是我做错了什么吗?或者调用此存储函数的任何更好的方法?


更新:在尝试@axtavt 的建议时,我收到以下错误:

ORA-14551: cannot perform a DML operation inside a query

该函数确实进行了大量的插入/更新,所以我想运行它的唯一方法是使用存储过程语法。我只是不知道如何映射返回值:

<sql-query name="TransferLocationFix" callable="true">
    <return-scalar column="???" type="string"/>
    { ? = call Transferlocation_Fix(:mnemonic) }
</sql-query>

应该是什么?我会尝试一个空值...


Update2: 也失败了,出现 SQL 语法异常...所以我按照 Pascal 的建议尝试了 JDBC 方式,它似乎有效!我在下面的答案中添加了代码。

最佳答案

为了进一步引用,这是我的最终解决方案:

CallableStatement statement = session.connection().prepareCall(
        "{ ? = call Transferlocation_Fix(?) }");
statement.registerOutParameter(1, Types.VARCHAR);
statement.setString(2, "FC3");
statement.execute();
String result = statement.getString(1);

关于java - Hibernate:如何调用返回 varchar 的存储函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2942977/

相关文章:

oracle - 如何在oracle中创建函数,我们可以在任何地方使用这个函数的结果

sql - 获取每组预言机的最大值

hibernate - 使用 updatable=false 更新实体将字段设置为 null

Java:避免阶乘溢出

java - 翻转多维数组java

java - 如何在 JAXB(Eclipse MOXy) 中标记第 3 方不可变对象(immutable对象)

java - OneToMany 更新在子类中不起作用

java - 捕获 ANTLR 中的错​​误并查找父级

c# - 检查 Oracle.DataAccess 是否存在

java - IntelliJ "Could not autowire."检查,Spring JPA 存储库的 "[…] more than one bean"