Ich versuche, eine ältere gespeicherte Funktion in einer Oracle9i DB von Java mit Hibernate aufzurufen. Die Funktion wird wie folgt erklärt:Hibernate: Wie eine gespeicherte Funktion aufgerufen wird, die ein Varchar zurückgibt?
create or replace FUNCTION Transferlocation_Fix (mnemonic_code IN VARCHAR2)
RETURN VARCHAR2
Nach mehreren gescheiterten Versuchen und umfangreiche googeln, ich this thread auf den Hibernate-Foren gefunden, die eine Zuordnung wie folgt vorgeschlagen:
<sql-query name="TransferLocationFix" callable="true">
<return-scalar column="retVal" type="string"/>
select Transferlocation_Fix(:mnemonic) as retVal from dual
</sql-query>
Mein Code auszuführen ist
Query query = session.getNamedQuery("TransferLocationFix");
query.setParameter("mnemonic", "FC3");
String result = (String) query.uniqueResult();
und das resultierende Protokoll ist
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)
...
Irgendwelche Hinweise was mache ich falsch? Oder gibt es bessere Möglichkeiten, diese gespeicherte Funktion aufzurufen?
Update: auf @ axtavt Vorschlag versucht, bekomme ich folgende Fehlermeldung:
ORA-14551: cannot perform a DML operation inside a query
Die Funktion hat in der Tat umfangreiche Einsätze/Updates, so dass ich denke, der einzige Weg, um es auszuführen wäre Verwenden der Syntax der gespeicherten Prozedur. Ich habe keine Ahnung, wie der Rückgabewert auf der Karte:
<sql-query name="TransferLocationFix" callable="true">
<return-scalar column="???" type="string"/>
{ ? = call Transferlocation_Fix(:mnemonic) }
</sql-query>
Was sollte die column
sein? Ich werde einen leeren Wert versuchen ...
Update2:, die als gut ausgefallen, mit einem SQL-Grammatik Exception ... Also habe ich versucht, den JDBC-Weg, wie Pascal vorgeschlagen, und es scheint zu funktionieren! Ich habe den Code in einer Antwort unten hinzugefügt.
Ich lese das auch, aber ich bin mir auch nicht sicher, da es in einem anderen Teil des Buches (Kap. 8.2.2) einen Abschnitt über den Aufruf gespeicherter Funktionen gibt (allerdings gibt es kein einfaches Beispiel :-() Forum-Thread, den ich gefunden habe, legt nahe, dass es tatsächlich möglich ist, 'getNamedQuery()' ... zu verwenden. –
@ Péter In der Tat, und axtavts Antwort geht in die gleiche Richtung. Ich bin gespannt, ob es funktioniert. –
FYI, am Ende stellte sich heraus, dass die Hibernate-Dokumentation in diesem Fall richtig war, also musste ich JDBC verwenden. –