Acceso a stored procedure

Ayuda:

Estoy trabajando con mysql y tomcat, necesito acceder a un stored procedure:

CREATE PROCEDURE count_orders(OUT total INT)
BEGIN
    select count(*)
    into total
    from blackberry.orders;
END

Para comprobar que funciona mando la orden:

CALL  count_orders(@total);
SELECT @total

y funciona perfectamente.

En java tengo el siguiente codigo:

        public int setStatement(Connection conn) throws SQLException{

                CallableStatement cs = null;
            int count = 0;
           
            try {
              cs = conn.prepareCall("{CALL count_orders(?)}");
              cs.registerOutParameter(1, Types.INTEGER);
              cs.execute();
              count = cs.getInt(1);

            } catch (Exception e) {
              System.out.println(e.toString());
            } finally {
              cs.close();
            }
               
                return count;
        }

pero me marca el error:

java.sql.SQLException: Parameter index of 1 is out of range (1, 0)

en la setencia

              cs.registerOutParameter(1, Types.INTEGER);

Ya busque y no encuentro la solucion, espero me puedan ayudar.

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

javadoc

Lee la documentación de JDBC... en los Statements las columnas comienzan desde 1, no 0. getInt(1) es lo que necesitas; getInt(0) es inválido. Igual cuando tienes un PreparedStatement con parámetros, el primer valor que le pasas debe ser al índice 1, no 0.

Imagen de beto.bateria

edicion de tema

el error me lo da en:

cs.registerOutParameter(1, Types.INTEGER);

el 0 ya lo corregi, anteriormente trate de solucionarlo poniendole 0, pero tampoco funciono.

Imagen de ezamudio

raro

Los parámetros deben empezar en 1, eso es un hecho, no tiene caso que los empieces en 0. Si te dice que está fuera de rango es que no reconoció el ? en la llamada. No debería importar pero... intenta poner call en minúsculas, no mayúsculas (esa no es sentencia SQL, es algo de JDBC y tal vez sea sensible a mayúsculas).

Imagen de beto.bateria

El mismo error en la misma

El mismo error en la misma sentencia :s

Imagen de ezamudio

stacktrace

Para ver el stacktrace completo, cambia el print en el catch por ex.printStackTrace(System.out) tal vez encuentres alguna pista

Imagen de beto.bateria

Mas info sobre tema.

Pues ya le busque y no encuentro nada:

El web xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee <a href="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"" title="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"">http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"</a> id="WebApp_ID" version="2.5">
  <display-name>Server</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
  <resource-ref>
    <description>MySQLSource</description>
    <res-ref-name>jdbc/hsqldb</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
  </resource-ref>
  <servlet>
    <description></description>
    <display-name>Products</display-name>
    <servlet-name>Products</servlet-name>
    <servlet-class>com.app.view.Products</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>Products</servlet-name>
    <url-pattern>/Products</url-pattern>
  </servlet-mapping>
</web-app>

el context.xml

<?xml version="1.0" encoding="UTF-8"?>

<Context path="/PrePangea" docBase="PrePangea">
    <Resource
        name="jdbc/hsqldb"
        auth="Container"
        type="javax.sql.DataSource"
        username="root"
        password="password"
        driverClassName="com.mysql.jdbc.Driver"
        url="jdbc:mysql://localhost:3306/Blackberry"
        maxActive="8"
        maxIdle="4"
        />
</Context>

el DataBaseConnection

public class DataBaseConnection extends DatabaseConnectable{

    public Connection getConnection() throws NamingException, SQLException {
                InitialContext ctx = new InitialContext();
                Context envCtx = (Context) ctx.lookup("java:comp/env");
                DataSource ds = (DataSource) envCtx.lookup("jdbc/hsqldb");
        this.conn = ds.getConnection();
        return conn;
    }

    public void close() throws SQLException {
        if( conn != null  ){
                try {
                        conn.close();
                        this.conn = null;
                } catch (Exception e) {
                        e.printStackTrace();
                }
        }
    }
}

El StatementProcedure:

public class StatementProcedure{

        public int setStatement(Connection conn) throws SQLException{

                CallableStatement cs = null;
            int count = 0;
           
            try {
              cs = conn.prepareCall("{call count_orders(@total)}");
              cs.registerOutParameter(1, Types.INTEGER);
              //cs.registerOutParameter("total", Types.INTEGER);

              cs.execute();

              count = cs.getInt(1);

            } catch (Exception e) {
              System.out.println(e.toString());
              e.printStackTrace(System.out);
            } finally {
              cs.close();
            }
               
                return count;
        }
}

Y el codigo para ejecutarlo

        Connection conn = null;
        StatementProcedure sp = null;
        DatabaseConnectable databaseConnectable = new DataBaseConnection();
       
        try {
                        conn = databaseConnectable.getConnection();
                        sp = new StatementProcedure();
                        int count = sp.setStatement(conn);
                       
                } catch (NamingException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                } catch (SQLException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                }

Y el dichoso error:

java.sql.SQLException: Parameter index of 1 is out of range (1, 0)
java.sql.SQLException: Parameter index of 1 is out of range (1, 0)
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1075)
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:989)
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:984)
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:929)
        at com.mysql.jdbc.CallableStatement$CallableStatementParamInfo.checkBounds(CallableStatement.java:274)
        at com.mysql.jdbc.CallableStatement.checkParameterIndexBounds(CallableStatement.java:710)
        at com.mysql.jdbc.CallableStatement.checkIsOutputParam(CallableStatement.java:672)
        at com.mysql.jdbc.CallableStatement.registerOutParameter(CallableStatement.java:1846)
        at org.apache.tomcat.dbcp.dbcp.DelegatingCallableStatement.registerOutParameter(DelegatingCallableStatement.java:95)
        at org.apache.tomcat.dbcp.dbcp.DelegatingCallableStatement.registerOutParameter(DelegatingCallableStatement.java:95)
        at com.app.model.dbfactory.statment.statementable.StatementProcedure.setStatement(StatementProcedure.java:18)
        at com.app.view.Products.processRequest(Products.java:52)
        at com.app.view.Products.doGet(Products.java:99)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
        at java.lang.Thread.run(Unknown Source)

En realidad no encuentro ninguna pista del error, ya estuve buscando la tarde de ayer y hoy desde temprano.

Imagen de ezamudio

JDBC MySQL

Y ya leíste si el driver de JDBC de MySQL soporta parámetros de salida en stored procedures?

Imagen de beto.bateria

Estudie un capitulo que habla

Estudie un capitulo que habla sobre el tema en el sitio de mysql, solo que ahi manejan un parametro in/out. No creo que exista algun problema.

Gracias por el apoyo ezamudio.

A ver a ver a ver... tu

A ver a ver a ver... tu llamada dice:

cs = conn.prepareCall("{call count_orders(@total)}");

No tiene ningún signo de interrogación, luego tu llamada recibe 0 parametros, al intentar llamarla le pasas 1 y por eso truena.

Reemplaza por

cs = conn.prepareCall("{call count_orders(?)}");

Como en tu post original y velo funcionar.

Alternativamente, quitase lo a ambos y tambien funcionará.

Imagen de beto.bateria

Al principio asi lo puse :( y

Al principio asi lo puse :( y presenta el error. Ya he tratado de varias formas pero no ha funcionado.

Imagen de beto.bateria

La unica opcion que veo hasta

La unica opcion que veo hasta este momento es tener que instalar de nuevo el mysql.

Pero ya no. Intenta

Pero ya no.

Intenta agregandole un enter para ver si el número de línea cambia.

Intenta quitandole el parametro.

Intenta llamando otro sp ( aunque no existe )

El caso es que logres verificar, si lo que está sucediendo es que no estás actualizando la clase ( quizá olvidaste copiar el jar/war/ear o lo que uses? )

Por que ese error sale cuando no tienes "?"

Intenta aislar el problema.

Crea una aplicación chiquititita y prueba desde ahí:

import java.sql.*;
class Test {
   public static void main( String .. args ) {
        Connection c = DriverManager.getConnection("blabalbal");
       CallableStatement cs = c.prepareCall() ... etc.
    }
}

Para que veas que es lo que está sucediendo. Estoy casi seguro que la clase que estás ejecutando no es la que estás viendo.

Imagen de beto.bateria

Otros errores

Ya hice algunos cambios Oscar, me dieron mas informacion acerca del problema, a la mejor el error esta en:

cs.registerOutParameter(1, Types.INTEGER);

o de plano en el Stored Procedure.

Ahora si, que la suerte me acompañe.

¿Qué fue de este asunto?

Tiene tiempo que no trabajo con JDBC, así que corríjanme si estoy mal, pero me parece que si en la declaración llamamos algo como:
{CALL count_orders(?)}
estamos entonces indicando un parámetro de entrada o entrada/salida.
Creo que para hacer explícito que es un parámetro de salida, deberíamos tener algo como
{? = CALL count_orders()}
Me parece que como no especificamos el parámetro de salida al inicio de la llamada, al querer registrar el parámetro nos marca la excepción.

Imagen de ezamudio

parámetros de salida

Sí se pueden especificar parámetros de salida como lo está haciendo beto.bateria, porque puedes tener varios parámetros de salida. Al menos Oracle sí los puede manejar así; no sé si MySQL. Por eso mencioné que hay que leer los docs de esa base de datos, en particular del driver JDBC.

Pero no es muy complicado probar la opción de {?=CALL count_orders()} a ver si así funciona...

Imagen de beto.bateria

{?=CALL

{?=CALL count_orders()}

Sirve para llamar a una funcion almacenada. Algo que se crea asi:

CREATE FUNCTION hello (s CHAR(20)) RETURNS CHAR(50)
RETURN CONCAT('Hello, ',s,'!');

http://dev.mysql.com/doc/refman/5.0/es/create-procedure.html

Imagen de beto.bateria

Estuve investigando y al

Estuve investigando y al parecer esta bien el codigo que les mostre :(, este fin de semana instale de nuevo el SO y demas, debido al tiempo invertido en resolver este problema tuve que dejarlo y seguir con otras cosas, despues lo pruebo y les comento.

Que version de mysql tienes

Que version de mysql tienes ???

http://bugs.mysql.com/bug.php?id=9319

Imagen de Mike060987

SP POSIBLE SOLUCION ESO CREO

POR LO QUE VEO ES DE QUE TU SP GENERA UN PARAMETRO SALIDA
EN ESE CASO SEGUN RECUERDO PRIMERO LO TIENES QUE EJECUTAR Y DESPUES
RECOJER EL VALOR QUE REGRESO UNA VEZ QUE LO EJECUTO JAVA
SALUDOS

Google es tu mejor amigo... =)

 

Google es tu mejor amigo. ¿Le has pedido ayuda? =)

~~~

La mejor referencia de JDBC para MySQL al respecto la puedes encontrar en Using JDBC CallableStatements to Execute Stored Procedures.

También te recomiendo muy ampliamente los siguiente libros:

 

~~~

Imagen de Ziklónico

Buenísimos, pero una pasta

Buenísimos, pero una pasta buena, eso sí.