Acceso a stored procedure
Ayuda:
Estoy trabajando con mysql y tomcat, necesito acceder a un stored procedure:
BEGIN
select count(*)
into total
from blackberry.orders;
END
Para comprobar que funciona mando la orden:
SELECT @total
y funciona perfectamente.
En java tengo el siguiente codigo:
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
Ya busque y no encuentro la solucion, espero me puedan ayudar.
- Inicie sesión o regístrese para enviar comentarios
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.
edicion de tema
el error me lo da en:
el 0 ya lo corregi, anteriormente trate de solucionarlo poniendole 0, pero tampoco funciono.
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 ponercall
en minúsculas, no mayúsculas (esa no es sentencia SQL, es algo de JDBC y tal vez sea sensible a mayúsculas).El mismo error en la misma
El mismo error en la misma sentencia :s
stacktrace
Para ver el stacktrace completo, cambia el print en el catch por
ex.printStackTrace(System.out)
tal vez encuentres alguna pistaMas info sobre tema.
Pues ya le busque y no encuentro nada:
El web xml:
<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
<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 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 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
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)
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.
JDBC MySQL
Y ya leíste si el driver de JDBC de MySQL soporta parámetros de salida en stored procedures?
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:
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
Como en tu post original y velo funcionar.
Alternativamente, quitase lo a ambos y tambien funcionará.
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.
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í:
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.
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.
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...{?=CALL
Sirve para llamar a una funcion almacenada. Algo que se crea asi:
RETURN CONCAT('Hello, ',s,'!');
http://dev.mysql.com/doc/refman/5.0/es/create-procedure.html
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
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:
~~~
Buenísimos, pero una pasta
Buenísimos, pero una pasta buena, eso sí.