JPA和MySQL的事务隔离级别

4

我有一个原生查询,可以批量插入到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(...);
    }

这个查询导致了死锁:当它使用insert .. selectt2读取数据时,另一个进程试图插入一行到t2中。
在执行insert .. select时,我不关心对t2的读取一致性,并希望将事务隔离级别设置为READ_UNCOMMITTED
我该如何在JPA中进行设置呢?
更新 最终我创建了一个常规SQL连接来解决这个问题,因为这似乎是最简单的选项。谢谢大家!

我不明白这是如何导致死锁的?如果tx1执行以下操作: insert into t1 (a, b) select x, y from t2 where x = 'foo' 而在此同时,第二个tx向“t2”表中插入数据,则tx1必须等待tx2结束后才能继续工作。死锁是指tx2在向t2插入数据时也从t1中读取数据吗?你的情况是这样的吗?我的意思是像这样的事情会导致死锁: tx1: insert into t1 (a, b) select x, y from t2 where x = 'foo' tx2: insert into t2 (a, b) select x, y from t1 where x = 'foo' - Pasha
3个回答

4

你需要在连接级别上设置它,从entitymanager获取会话并执行以下操作:

org.hibernate.Session session = (Session)entityManager.getDelegate();
Connection connection = session.connection();
connection.setTransactionIsolation(Connection.READ_UNCOMMITTED);

这就是我说“从em获取会话”的原因;) 我编辑了代码。 - Guillaume
4
如果不是休眠模式呢? - Bozho
1
他说他正在使用Hibernate。我猜其他JPA实现也有类似的方法。 - Guillaume
2
嗨,Guillaume,最终我确实尝试了你的方法,但不幸的是它没有起作用;由于session.connection()方法已被弃用,我决定不花时间进行调查。 - armandino

3

JPA中不支持设置事务隔离级别,只有JDO是支持的标准。当然,使用特定实现的方法可以实现,但这样就不具备可移植性。


0

由于您使用的是BMT,因此可以使用数据源来获取连接并设置事务隔离级别。

DataSource source = (javax.sql.DataSource) jndiCntxt.lookup("java:comp/env/jdbc/myds");
Connection con = source.getConnection( );
con.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);

1
如果他没有使用 DataSource,而是指定了 connectionURL,该怎么办? - DataNucleus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接