Уровень изоляции транзакций JPA и MySQL

У меня есть собственный запрос, который выполняет пакетную вставку в базу данных MySQL:

    String sql = "insert into t1 (a, b) select x, y from t2 where x = 'foo'";
    EntityTransaction tx = entityManager.getTransaction();
    try {
        tx.begin();
        int rowCount = entityManager.createNativeQuery(sql).executeUpdate();
        tx.commit();
        return rowCount;
    }
    catch(Exception ex) {
        tx.rollback();
        log.error(...);
    }

Этот запрос вызывает взаимоблокировку: пока он читает из t2 в insert .. select, другой процесс пытается вставить строку в t2.

Меня не волнует согласованность операций чтения из t2 при выполнении insert .. select, и я хочу установить уровень изоляции транзакций READ_UNCOMMITTED.

Как мне настроить его в JPA?


Обновить

В итоге я создал обычное SQL-соединение для этого случая, как мне показалось самым простым вариантом. Всем спасибо!


person armandino    schedule 27.05.2010    source источник
comment
Я не могу понять, как это привело к тупику? Если tx1 выполнить: вставить в t1 (a, b) выбрать x, y из t2, где x = 'foo' И пока это происходит, второй tx делает вставку в таблицу t2, чем tx1 ждет, пока не закончится tx2, после tx2 закончился tx1, продолжайте свою работу. Dedalock означает, что tx2 при вставке в t2 также выполняет чтение из t1? Это твой случай? я имею в виду, что что-то вроде этого приводит к тупику: tx1: вставить в t1 (a, b) выбрать x, y из t2, где x = 'foo' tx2: вставить в t2 (a, b) выбрать x, y из t1, где x = 'фу'   -  person Pasha    schedule 05.06.2014


Ответы (3)


Вам нужно установить его на уровне подключения, получить сеанс от entitymanager и сделать это:

org.hibernate.Session session = (Session)entityManager.getDelegate();
Connection connection = session.connection();
connection.setTransactionIsolation(Connection.READ_UNCOMMITTED);
person Guillaume    schedule 27.05.2010
comment
вот почему я сказал получить сеанс от em ;) я отредактировал код - person Guillaume; 27.05.2010
comment
а если не спящий режим? - person Bozho; 28.05.2010
comment
Ну, он сказал, что использует Hibernate. Я предполагаю, что есть аналогичные способы сделать это для других реализаций JPA. - person Guillaume; 28.05.2010
comment
Привет, Гийом, в конце концов я попробовал ваш подход, но, к сожалению, он не сработал; видя, что метод session.connection() устарел, я решил не тратить время на расследование. - person armandino; 03.06.2010

В JPA вы этого не сделаете. JDO — единственный стандарт, поддерживающий настройку изоляции txn. Очевидно, что переход к конкретным методам реализации может позволить это, но тогда вы становитесь непереносимым

person DataNucleus    schedule 28.05.2010

Поскольку вы используете BMT, вы можете сделать следующее, используя источник данных, чтобы получить соединение. и выставить исо. уровень.

DataSource source = (javax.sql.DataSource) jndiCntxt.lookup("java:comp/env/jdbc/myds");
Connection con = source.getConnection( );
con.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
person OpenSource    schedule 28.05.2010
comment
а если он не использует DataSource, а вместо этого указал connectionURL? - person DataNucleus; 09.11.2012