sql >> Base de Datos >  >> RDS >> Oracle

Grupo de conexiones de Tomcat jdbc - transacción abandonada de reversión

Según http://docs .oracle.com/javase/7/docs/api/java/sql/Connection.html#close() :

Esta prueba, utilizando Mysql en lugar de Oracle, confirma este hecho:

import static org.junit.Assert.assertEquals;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.junit.Test;


public class DBTest {

    public Connection openConnection() throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.jdbc.Driver");
        Connection c = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "password");
        c.setAutoCommit(false);
        return c;
    }

    @Test
    public void testSO25886466() throws SQLException, ClassNotFoundException {

        {
            Connection c = openConnection();
            PreparedStatement delete = c.prepareStatement("delete from temp");
            delete.executeUpdate();
            c.commit();
            c.close();
        }

        {
            Connection c = openConnection();
            PreparedStatement insert = c.prepareStatement("insert into temp values ('a', 'b')");
            insert.execute();
            //c.commit(); as the op says, DONT commit!!
            c.close(); //WITHOUT having closed the statement or committing the transaction!!
        }

        {
            Connection c = openConnection();
            PreparedStatement select = c.prepareStatement("select count(*) from temp");
            select.execute();
            ResultSet rs = select.getResultSet();
            while(rs.next()){
                assertEquals(0/*i'd expect zero here!*/, rs.getInt(1));
            }
            rs.close();
            select.close();
            c.close();
        }
    }
}

Según http://tomcat.apache.org/tomcat-7.0 -doc/jdbc-pool.html :

Recomendaría no configurar removeAbandoned para que Oracle cierre la conexión después de un tiempo de espera en el lado del servidor, en lugar de que Tomcat la cierre. Oracle probablemente no confirmará la transacción en ese caso, pero necesitaría probar esto.

Alternativamente, ¿podría aumentar el removeAbandonedTimeout configuración, para que su programa pueda finalizar y no se abandonen las conexiones?

Otro problema que tiene es que su aplicación se ha vinculado a Oracle porque confía en la implementación del controlador donde la especificación tiene un agujero. Si puede, programe según las especificaciones, de modo que tenga la libertad de migrar su aplicación a una base de datos diferente, aunque sé que es difícil en la práctica.

Una solución completamente diferente sería tomar un grupo de conexiones de código abierto y ampliarlo con un interceptor AOP que pueda interceptar llamadas para close y averigüe si la transacción se ha confirmado, y si no, llame a rollback en la conexión. Sin embargo, esa es una solución bastante compleja... :-)