Chamada de function oracle pelo hibernate

Pessoal estou com problemas para chamar uma função pelo hibernate. Eu consigo chamar uma procedure que retorna um cursor, mas não consigo chamar uma function. Não sei o pq do erro.

Eis as minhas chamadas e meus mapeamentos:

Função no Oracle:


 FUNCTION INC_TIPO_LOCAL RETURN NUMBER IS
    WINCVALUE NUMBER;
  BEGIN
    SELECT NVL(MAX(CD_TIPO_LOCAL),0) +1
      INTO WINCVALUE
	  FROM BOP_TIPO_LOCAL;

	RETURN WINCVALUE;
  END;

Mapeamento no hibernate:



<hibernate-mapping>

    <sql-query name="incTipoLocal" callable="true">
        <return-scalar column="INC_TIPO_LOCAL" type="long"/>
        { ? = call PA_TIPO_LOCAL.INC_TIPO_LOCAL() }
    </sql-query> 

</hibernate-mapping>

Chamada na classe:


    public void incTipoLocal() {
        
        Query q = ManageDAO.getSession().getNamedQuery("incTipoLocal");
        
        List i = q.list() ;
        
        System.out.println( i.get(1) );
        
    }
    
    public static void main(String[] args) {
        
        new TipoLocalDAO().incTipoLocal();
        
    }

Erro:

Hibernate:
{ ? = call PA_TIPO_LOCAL.INC_TIPO_LOCAL() }
13:01:48,687 WARN JDBCExceptionReporter:100 - SQL Error: 6550, SQLState: 65000
13:01:48,687 ERROR JDBCExceptionReporter:101 - ORA-06550: line 1, column 13:
PLS-00382: expression is of wrong type
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

Exception in thread “main” org.hibernate.exception.SQLGrammarException: could not execute query
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:90)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.loader.Loader.doList(Loader.java:2231)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2125)
at org.hibernate.loader.Loader.list(Loader.java:2120)
at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:312)
at org.hibernate.impl.SessionImpl.listCustomQuery(SessionImpl.java:1722)
at org.hibernate.impl.AbstractSessionImpl.list(AbstractSessionImpl.java:165)
at org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:175)
at br.es.csi.cad.dao.TipoLocalDAO.incTipoLocal(TipoLocalDAO.java:27)
at br.es.csi.cad.dao.TipoLocalDAO.main(TipoLocalDAO.java:35)
Caused by: java.sql.SQLException: ORA-06550: line 1, column 13:
PLS-00382: expression is of wrong type
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

Desde já agradeço a colaboração de todos.

Bom… Como ninguém respondeu…após algum tempo de pesquisa achei na documentação do hibernate o seguinte:

For Oracle the following rules apply:

*  A function must return a result set. The first parameter of a procedure must be an OUT that returns a result set. This is done by using a SYS_REFCURSOR type in Oracle 9 or 10. In Oracle you need to define a REF CURSOR type. See Oracle literature for further information.

Lendo isso eu entendi que, eu não consigo chamar uma função ( por mapeamento em XML, não sei se funciona com annotations ) que retorna um valor, a não se que esse retorno seja um cursor.

Com isso eu consegui chamar uma procedure que retorna um cursor.

Abaixo segue a implementação:

Stored Procedure:
PROCEDURE CONSULTA_TIPO_LOCAL (RTIPO_LOCAL IN OUT TIPO_LOCAL_C, PCD_TIPO_LOCAL IN BOP_TIPO_LOCAL.CD_TIPO_LOCAL%TYPE ) IS
  BEGIN
   OPEN RTIPO_LOCAL FOR
   		SELECT *
     		FROM BOP_TIPO_LOCAL
   		 WHERE CD_TIPO_LOCAL = DECODE (PCD_TIPO_LOCAL, NULL, CD_TIPO_LOCAL, PCD_TIPO_LOCAL)
	  ORDER BY DS_TIPO_LOCAL;
  END CONSULTA_TIPO_LOCAL ;
Mapeamento da Procedure:
* Obs: a chamada é PA_TIPO_LOCAL.CONSULTA_TIPO_LOCAL, pois a minha procudure está armazenada em uma package do banco oracle.
<sql-query name="consultaTipoLocal" callable="true">
        <return class="br..entity.TipoLocalEntity">
        </return>
        { call PA_TIPO_LOCAL.CONSULTA_TIPO_LOCAL( ?, :cdTpLocal ) }
    </sql-query>
No meu DAO:
    public List<TipoLocalEntity> consultaTipoLocal() throws Exception {
        
        // HibernateUtil é a minha classe que retorna a session
        HibernateUtil hibUtil = null;
        List<TipoLocalEntity> result = null;
        
        try {
            
            hibUtil = new HibernateUtil();
            
            Query q = hibUtil.getSession().getNamedQuery("consultaTipoLocal");
            q.setParameter("cdTpLocal","");
                    
            result = q.list();
            
        } catch ( Exception e ) {
        
            e.printStackTrace();
            throw new Exception( e.getMessage() );
            
        } finally {
            
            HibernateUtil.closeSession( hibUtil );
            
        }
        
        return result;
        
    }

Para eu chamar uma function armazenada no banco eu preciso fazer o seguinte:

    public long incTipoLocal() throws Exception {
        
        // HibernateUtil é a minha classe que retorna a session
        HibernateUtil hibUtil = null;
        
        long ultimoId = 0;
        
        try {
            
            hibUtil = new HibernateUtil();
            
            //Para retornar outros tipos de valores eu mudo minha chamada do método addScalar
            // Ex.: Hibernate.STRING no lugar do Hibernate.LONG
            Query q = hibUtil.getSession().createSQLQuery("SELECT PA_TIPO_LOCAL.INC_TIPO_LOCAL AS ID FROM DUAL").addScalar("ID", Hibernate.LONG);

            ultimoId = (Long)q.uniqueResult();
         
        } catch( Exception e ) {
            
            e.printStackTrace();
            throw new Exception( e.getMessage() );
            
        } finally {
            
            HibernateUtil.closeSession( hibUtil );
            
        }
        
        return ultimoId;
        
    }

Espero ter ajudado. Caso alguém saiba algum jeito melhor de fazer, por favor postem aqui.
Abraço.

olá pessoal!

estou com um problema sobre isso, a diferença que o SGBD que estou usando é o PostgresSQL…

é o seguinte:
no banco tenho uma função, e tenho no java um método que a chama através do Hibernate.
essa função não retorna nada.
no java ela esta sendo chamada, mas não esta sendo executada pelo hibernate.

este é o método.

public void updateItensChecklist( PfjCheckList pfjCheckList ) { Query query = getSession().createSQLQuery("SELECT cadastro.atualizar_pfj_itens_checklist(" + pfjCheckList.getId() + " )"); }

este é o meu arquivo de mapeamento.
<sql-query name="atualizar_pfj_itens_checklist" callable="true"> <return alias="update_item" class="br...." /> { ? = call atualizar_pfj_itens_checklist(?) } </sql-query>

então, como que eu poderia fazer para o hibernate mapear isso?!?

Att Murilo Moreira

valeu!