Я пытаюсь вызвать унаследованную сохраненную функцию в Oracle9i DB с Java, используя Hibernate. Функция объявлена так:Hibernate: как вызвать сохраненную функцию, возвращающую varchar?
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)
...
Любые подсказки, что я делаю неправильно? Или какие-либо лучшие способы вызова этой хранимой функции?
Update: при попытке @ предложение 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>
Каким должен быть column
? Я попробую пустое значение ...
UPDATE2: что не удалось, а также, с исключением SQL Grammar ... Так что я попытался, как JDBC, как предложил Паскаль, и это, кажется, работает! Я добавил код в ответ ниже.
Я тоже это читал, но я тоже не уверен, поскольку в другой части книги (глава 8.2.2) есть раздел о вызове хранимых функций (однако нет простого примера :-(). я нашел вывод, что это действительно возможно с помощью 'getNamedQuery()' ... –
@ Péter В самом деле, и ответ axtavt идет в том же направлении. Я очень хочу посмотреть, работает ли это. –
FYI, в конце концов, оказалось, что в этом случае документация Hibernate подходит, поэтому мне пришлось использовать JDBC. –