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

Tomcat jdbc-forbindelsespulje - rollback opgivet transaktion

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

Denne test, der bruger Mysql i stedet for Oracle, bekræfter dette faktum:

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

Ifølge http://tomcat.apache.org/tomcat-7.0 -doc/jdbc-pool.html :

Jeg vil anbefale ikke at indstille removeAbandoned så Oracle lukker forbindelsen efter en timeout på serversiden, i stedet for at Tomcat lukker den. Oracle vil sandsynligvis ikke begå transaktionen i så fald, men du bliver nødt til at teste dette.

Alternativt kan du øge removeAbandonedTimeout indstilling, så dit program kan afsluttes, og ingen forbindelser bliver opgivet?

Et andet problem, du har, er, at din applikation er blevet bundet til Oracle, fordi du er afhængig af driverimplementeringen, hvor specifikationen har et hul i den. Hvis du kan, programmer mod specifikationer, så du er fri til at migrere din applikation til en anden database, selvom jeg ved, det er svært i praksis.

En helt anden løsning ville være at tage en open source-forbindelsespulje og udvide den med en AOP-interceptor, som kan opsnappe opkald til close og find ud af, om transaktionen er blevet begået, og hvis ikke, ring til rollback på forbindelsen. Det er dog en ret kompleks løsning... :-)



  1. Valg af sidste post fra INNER JOIN og gruppering

  2. Flere joinforbindelser til samme tabel

  3. Er det virkelig nødvendigt at oprette SQLite-tabeller, hver gang applikationen starter?

  4. Implementering af inkrementel belastning ved hjælp af Change Data Capture i SQL Server