2012-05-03 18 views
7

Situación
Tengo una aplicación web Java (Tomcat) que utiliza jTDS para conectarse a una base de datos MSSQL 2008. Esta aplicación Java ejecuta el 99% de sus procedimientos almacenados MSSQL utilizando la entrada del usuario.jTDS + procedimientos almacenados + prepareSQL = error de nivel de anidamiento?

Problema
El conductor responde jTDS veces (en diferentes lugares de la aplicación) con el error:

Maximum stored procedure, function, trigger, or view nesting level exceeded (limit 32).

Podemos evitar esto mediante la adición prepareSQL=0 a la cadena de conexión jTDS. Entonces el error desaparece en todas partes, pero con todos los demás valores de prepareSQL, el error permanece. No sé cuántos niveles de anidación de procedimientos almacenados jTDS agrega, pero aparentemente es demasiado para nuestra aplicación.

Preguntas

  1. Con procedimientos sólo almacenados para ejecutar, por supuesto, el uso de sentencias preparadas en el código Java, cuánto efecto tiene prepareSQL=3 (o prepareSQL=0) tienen para nosotros? En otras palabras: en cada sitio web encuentro personas que dicen "Nunca use prepareSQL=0 en entornos de producción", ¿eso también es aplicable a esta situación?

  2. Si prepareSQL=0 no es una solución recomendada, un problema de seguridad, etc., quizás deberíamos buscar otro controlador. jTDS no se ha actualizado en los últimos 2 años y Microsoft tiene un controlador para JDBC 4.0. Sin embargo, no puedo encontrar referencias ni comparaciones entre jTDS y el controlador JDBC 4.0 de Microsoft. Con los controladores 2.0 y 3.0 de Microsoft, la opinión general parecía ser que jTDS es más rápido, mejor y más eficiente. ¿Sigue siendo así con JDBC 4.0 o Microsoft ha superado a su competidor en esto?

+0

¿Ha logrado identificar este comportamiento con algún procedimiento específico o parece aleatorio? – heikkim

+0

No, no hemos (todavía). Hemos visto este error en dos implementaciones diferentes de nuestra aplicación en dos lugares diferentes de la aplicación, pero cuando ocurrió, fue obstinado y solo se pudo resolver utilizando la solución prepareSQL = 0. – bartlaarhoven

Respuesta

2

cuando prepareSQL no es igual a 0 jTDS añadir exactamente un nivel de anidamiento. Considere la posibilidad de seguir el procedimiento:

CREATE PROCEDURE F @v int 
AS 
BEGIN 
    select @v = @v - 1 
    IF @v = 0 SELECT @v 
    ELSE EXEC F @v 
END 

Y el código java que lo utilizan:

Connection connection = DriverManager.getConnection("jdbc:jtds:sqlserver://xxx.xxx.xxx.xxx:1433/xxx;prepareSQL=0"); 
PreparedStatement statement = connection.prepareStatement("EXEC F ?"); 
statement.setInt(1, 32); 
statement.execute(); 

Si establece prepareSQL a valor distinto de 0 se producirá un error con el "procedimiento de máxima almacenada, función, disparador o vista de anidación nivel excedido (límite 32) ". ¿Necesitas encontrar por qué tu código usa tanta anidación? Por prepareSQL = 0 está impidiendo que mssql use stamements y forzar a analizar SQL en cada ejecución. No es un gran problema si el tiempo de ejecución de la instrucción es mucho más que el tiempo de compilación de la declaración (por ejemplo, si el procedimiento almacenado se ejecuta 10 segundos, no es un problema si la compilación tomó 10 ms más). Cambiar el controlador no ayudará porque tendrá los mismos problemas.

Cuestiones relacionadas