Theo http://docs .oracle.com / javase / 7 / docs / api / java / sql / Connection.html # close () :
Thử nghiệm này, sử dụng Mysql thay vì Oracle xác nhận sự thật này:
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();
}
}
}
Theo http://tomcat.apache.org/tomcat-7.0 -doc / jdbc-pool.html :
Tôi khuyên bạn không nên đặt removeAbandoned
để Oracle đóng kết nối sau một khoảng thời gian chờ ở phía máy chủ, thay vì Tomcat đóng nó. Oracle có thể sẽ không thực hiện giao dịch trong trường hợp đó, nhưng bạn sẽ cần phải kiểm tra điều này.
Ngoài ra, bạn có thể tăng removeAbandonedTimeout
để chương trình của bạn có thể kết thúc và không có kết nối nào bị bỏ rơi?
Một vấn đề khác mà bạn gặp phải là ứng dụng của bạn đã bị ràng buộc với Oracle vì bạn đang dựa vào việc triển khai trình điều khiển mà thông số kỹ thuật có một lỗ hổng trong đó. Nếu bạn có thể, hãy lập trình dựa trên các thông số kỹ thuật để bạn có thể tự do di chuyển ứng dụng của mình sang một cơ sở dữ liệu khác, mặc dù tôi biết điều đó là khó trong thực tế.
Một giải pháp hoàn toàn khác sẽ là sử dụng một nhóm kết nối mã nguồn mở và mở rộng nó với một bộ đánh chặn AOP có thể chặn các cuộc gọi đến close
và xác định xem giao dịch đã được cam kết chưa và nếu chưa, hãy gọi rollback
trên kết nối. Đó là một giải pháp khá phức tạp mặc dù ... :-)