http://docsによると.oracle.com / javase / 7 / docs / api / java / sql / Connection.html#close() :
OracleではなくMysqlを使用したこのテストでは、この事実が確認されています。
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();
}
}
}
http://tomcat.apache.org/tomcat-7.0によると、 -doc / jdbc-pool.html :
removeAbandoned
を設定しないことをお勧めします Oracleは、Tomcatが接続を閉じるのではなく、サーバー側でタイムアウトした後に接続を閉じるようにします。その場合、Oracleはおそらくトランザクションをコミットしませんが、これをテストする必要があります。
または、removeAbandonedTimeout
を増やすこともできます プログラムを終了し、接続が放棄されないように設定しますか?
もう1つの問題は、仕様に穴が開いているドライバーの実装に依存しているため、アプリケーションがOracleに関連付けられていることです。可能であれば、仕様に照らしてプログラミングし、アプリケーションを別のデータベースに自由に移行できるようにします。ただし、実際には難しいことはわかっています。
まったく異なる解決策は、オープンソースの接続プールを取得し、close
への呼び出しをインターセプトできるAOPインターセプターで拡張することです。 トランザクションがコミットされているかどうかを確認し、コミットされていない場合は、rollback
を呼び出します。 接続上。しかし、それは非常に複雑な解決策です... :-)