Oracle
 sql >> Database >  >> RDS >> Oracle

Pool di connessioni jdbc Tomcat - rollback della transazione abbandonata

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

Questo test, utilizzando Mysql anziché Oracle, conferma questo fatto:

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();
        }
    }
}

Secondo http://tomcat.apache.org/tomcat-7.0 -doc/jdbc-pool.html :

Consiglierei di non impostare removeAbandoned in modo che Oracle chiuda la connessione dopo un timeout sul lato server, anziché chiuderla Tomcat. Oracle probabilmente non eseguirà il commit della transazione in questo caso, ma dovresti testarlo.

In alternativa, potresti aumentare il removeAbandonedTimeout impostazione, in modo che il tuo programma possa terminare e nessuna connessione venga abbandonata?

Un altro problema che hai è che la tua applicazione è diventata legata a Oracle perché ti affidi all'implementazione del driver in cui le specifiche hanno un buco in essa. Se puoi, programma contro le specifiche, in modo da essere libero di migrare la tua applicazione su un database diverso, anche se so che è difficile nella pratica.

Una soluzione completamente diversa sarebbe quella di prendere un pool di connessioni open source ed estenderlo con un intercettore AOP in grado di intercettare le chiamate per close e scopri se la transazione è stata confermata e, in caso contrario, chiama rollback sulla connessione. Questa è una soluzione piuttosto complessa però... :-)