sql >> Databasteknik >  >> RDS >> Oracle

Tomcat jdbc-anslutningspool - återställning övergiven transaktion

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

Detta test, med Mysql istället för Oracle bekräftar detta 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();
        }
    }
}

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

Jag skulle rekommendera att inte ställa in removeAbandoned så att Oracle stänger anslutningen efter en timeout på serversidan, snarare än att Tomcat stänger den. Oracle kommer förmodligen inte att begå transaktionen i så fall, men du skulle behöva testa detta.

Alternativt kan du öka removeAbandonedTimeout inställning, så att ditt program kan avslutas och inga anslutningar avbryts?

Ett annat problem du har är att din applikation har blivit knuten till Oracle eftersom du förlitar dig på drivrutinsimplementeringen där specen har ett hål i sig. Om du kan, programmera mot specifikationer, så att du är fri att migrera din applikation till en annan databas, även om jag vet att det är svårt i praktiken.

En helt annan lösning skulle vara att ta en anslutningspool med öppen källkod och utöka den med en AOP-interceptor som kan avlyssna samtal till close och räkna ut om transaktionen har genomförts, och om inte, ring rollback på anslutningen. Det är dock en ganska komplicerad lösning... :-)



  1. Använd en utlösare för att stoppa en infogning eller uppdatering

  2. ISO-8859-1-tecken trunkerar text som infogas i utf-8 mysql-kolumn

  3. ORA-00984:kolumn inte tillåten här

  4. välj alternativvärde från databasen på valt