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... :-)