从异步方法锁定数据库表重复调用em.merge

时间:2017-08-23 18:01:49

标签: hibernate jpa transactions

我正在使用JBoss / Wildfly 7.1中的Java Persistence API与MSSQL数据库进行交互。我有一个长期运行的异步函数,定期插入和更新到表中,但每次更新之间有几秒钟。当此函数运行时,表在事务中被锁定,我无法从Java应用程序内部或外部查询表。下面是我如何实现DAO的示例:

@Stateless
class Dao {

    @PersistenceContext(unitName = "persistenceUnit")
    private EntityManager em;

    public void mergeEntity(Entity e){
        em.merge(e);
    }

    public Entity getEntity(int id){
        return em.find(Entity.class,id);
    }
}

class Service {

    @Inject
    private Dao dao;

    private void updateEntity(int id){
        Entity e = dao.getEntity(id)
        //do update logic
        dao.mergeEntity(e);
    }
}

我也尝试过请求mergeEntity方法的新交易:

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void mergeEntity(Entity e){
    em.merge(e);
}

当我这样做时,合并永远不会执行,操作就会挂起。打开Hibernate的跟踪日志记录并未发现任何表明存在问题的内容。有什么办法可以防止Hibernate在没有主动修改它的情况下锁定它吗?

2 个答案:

答案 0 :(得分:0)

除MySQL(使用REPEATABLE_READ)外,大多数关系数据库系统的默认隔离级别为READ_COMMITTED。所有数据库都允许您设置默认事务隔离级别。

您可以尝试使用READ_UNCOMMITTED来绕过长时间运行的更新问题。使用Hibernate,意味着设置:

<property name="hibernate.connection.isolation">1</property>

答案 1 :(得分:0)

看起来事务从getEntity调用开始保持打开状态,因为服务被注入到一个总体EJB中。放置@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)时,其他事务从未关闭,因此合并永远不会打开新事务。通过在getEntity方法上调用@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)时,在事务中不会考虑连接。这样,当调用merge方法时,容器可以自由地为合并打开一个新事务。