De acordo com http://docs .oracle.com/javase/7/docs/api/java/sql/Connection.html#close() :
Este teste, usando o Mysql em vez do Oracle, confirma este fato:
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();
}
}
}
De acordo com http://tomcat.apache.org/tomcat-7.0 -doc/jdbc-pool.html :
Eu recomendaria não configurar
removeAbandoned
para que o Oracle feche a conexão após um tempo limite no lado do servidor, em vez de o Tomcat fechá-la. A Oracle provavelmente não confirmará a transação nesse caso, mas você precisaria testar isso. Como alternativa, você pode aumentar o
removeAbandonedTimeout
configuração, para que seu programa possa terminar e nenhuma conexão seja abandonada? Outro problema que você tem é que seu aplicativo ficou vinculado ao Oracle porque você está confiando na implementação do driver onde a especificação tem um furo. Se você puder, programe de acordo com as especificações, para que você fique livre para migrar seu aplicativo para um banco de dados diferente, embora eu saiba que isso é difícil na prática.
Uma solução completamente diferente seria pegar um pool de conexão de código aberto e estendê-lo com um interceptador AOP que pode interceptar chamadas para
close
e descubra se a transação foi confirmada e, caso contrário, chame rollback
na conexão. Essa é uma solução bastante complexa... :-)