Oracle
 sql >> база данни >  >> RDS >> Oracle

Tomcat jdbc набор от връзки - връщане назад на изоставена транзакция

Според http://docs .oracle.com/javase/7/docs/api/java/sql/Connection.html#close() :

Този тест, използващ Mysql вместо Oracle, потвърждава този факт:

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 настройка, така че вашата програма да може да завърши и никакви връзки да не бъдат изоставени?

Друг проблем, който имате, е, че вашето приложение е обвързано с Oracle, защото разчитате на внедряването на драйвера, където спецификацията има дупка в нея. Ако можете, програмирайте спрямо спецификациите, така че да можете свободно да мигрирате приложението си към друга база данни, въпреки че знам, че това е трудно на практика.

Напълно различно решение би било да се вземе пул от връзки с отворен код и да се разшири с AOP прихващач, който може да прихваща повиквания към close и разберете дали транзакцията е била ангажирана и ако не, извикайте rollback на връзката. Това обаче е доста сложно решение... :-)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Oracle-XMLTYPE :Как да актуализирате стойност

  2. Задаване на classpath за Java съхранена процедура в Oracle

  3. Таблица MERGE, не правете нищо при съвпадение

  4. Автоматично увеличение в Oracle без използване на тригер

  5. Еквивалент на Oracle ISNULL().