Oracle
 sql >> Base de données >  >> RDS >> Oracle

Pool de connexions Tomcat jdbc - restauration de la transaction abandonnée

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

Ce test, utilisant Mysql plutôt qu'Oracle confirme ce fait :

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

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

Je recommanderais de ne pas définir removeAbandoned afin qu'Oracle ferme la connexion après un délai d'attente côté serveur, plutôt que Tomcat la ferme. Oracle ne validera probablement pas la transaction dans ce cas, mais vous devrez tester cela.

Sinon, pourriez-vous augmenter le removeAbandonedTimeout pour que votre programme puisse se terminer et qu'aucune connexion ne soit abandonnée ?

Un autre problème que vous avez est que votre application est devenue liée à Oracle parce que vous comptez sur l'implémentation du pilote où la spécification a un trou. Si vous le pouvez, programmez selon les spécifications, afin que vous soyez libre de migrer votre application vers une autre base de données, même si je sais que c'est difficile en pratique.

Une solution complètement différente serait de prendre un pool de connexions open source et de l'étendre avec un intercepteur AOP qui peut intercepter les appels à close et déterminez si la transaction a été validée, et si ce n'est pas le cas, appelez rollback sur la connexion. C'est une solution assez complexe cependant... :-)