2013-11-21 2 views
4

Я хочу вызвать функцию Oracle с помощью JPA. Я нашел this thread на эту тему.Как вызвать функцию Oracle, которая возвращает строку, используя Hibernate/JPA?

Но моя функция Oracle возвращает только строку. Не результат для какой-то сущности. Я пытался что-то вроде этого:

@NamedNativeQuery(name = "myFuncCall", 
     resultSetMapping = "myResultSetMapping", 
     query = "{ ? = call schema.mypkg.somefunc(:id) }", 
     hints = { @javax.persistence.QueryHint(name = "org.hibernate.callable", value = "true") } 
) 

@SqlResultSetMapping(name = "myResultSetMapping", 
    columns = { @ColumnResult(name="somename") } 
) 

Когда я звоню запрос как этот

Query query = em.createNamedQuery("myFuncCall", String.class).setParameter("id", "42"); 
     String res = (String) query.getSingleResult(); 

я

Hibernate: { ? = call schema.somefunc(?) } 
18:21:11.222 [main] WARN o.h.util.JDBCExceptionReporter - SQL Error: 6550, SQLState: 65000 
18:21:11.222 [main] ERROR o.h.util.JDBCExceptionReporter - ORA-06550: Row 1, Column 13: 
PLS-00382: This expression has the wrong type 
ORA-06550: Row 1, Column 7: 
PL/SQL: Statement ignored 

javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not execute query 
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1389) 
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1317) 
at org.hibernate.ejb.QueryImpl.getSingleResult(QueryImpl.java:307) 

Любые идеи?

+0

Вы когда-нибудь нашли что-нибудь хорошее для этого, я взломал все вместе вместе – NimChimpsky

+0

Нет, это все равно то же самое, что и ниже, к сожалению. – Stefan

ответ

2

В итоге мы использовали CallableStatement. Это работает, но скажите, есть ли лучшее решение!

String funcCall = "{? = call schema.mypkg.somefunc(?)}"; 
Connection conn = ((SessionImpl)em.getDelegate()).connection(); 
CallableStatement stmt = conn.prepareCall(funcCall); 
stmt.setInt(2, 42); 
stmt.registerOutParameter(1, Types.CHAR); 
stmt.executeUpdate(); 
String result = stmt.getString(1); 
0

Я делаю это довольно хакерским способом, вы должны вернуть refcursor. Поэтому убедитесь, что ваша функция возвращает реф курсоры и делает что-то, как показано ниже:

result_string := doSoemthing 
    open l_refcursor for select result_string as str from dual; 
    return l_refcursor; 

затем создать «фиктивный» объект

@Entity 
public class NativeString { 
    private String str; 

    @Id 
    @Column(name = "str") 
    public String getStr() { 
     return str; 
    } 

    public void setStr(String str) { 
     this.str = str; 
    } 
} 

, и вы можете использовать встроенную функциональность запроса

@NamedNativeQueries({ 
     @javax.persistence.NamedNativeQuery(name = "whatevs", query = "" + 
       "{? = call myfunction(:id)}", resultClass = NativeString.class, 
       hints = { 
         @javax.persistence.QueryHint(name = "org.hibernate.callable", value = "true") 
       } 

     ) 

}) 

Это примерно так же безобразно, как и получается ... нет приятного способа афаик с иероглифами и хранимыми процедурами и функциями.

Смежные вопросы