Chamada de function oracle pelo hibernate

2 respostas
T

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.

2 Respostas

T

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.

M

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!

Criado 9 de julho de 2009
Ultima resposta 10 de out. de 2009
Respostas 2
Participantes 2