【问题标题】:Issue in updating database with jpa in a thread在线程中使用 jpa 更新数据库的问题
【发布时间】:2014-03-17 16:14:43
【问题描述】:

在我们的应用程序中,我们希望根据当前状态更新一些记录。在数据库表中,我们有2个字段名为status和notified,当status处于活动状态时,notified为0,我们需要将notified更新为1。由于数据会不断插入和更新,所以我写了一个线程定期扫描表. 这是线程的伪代码:

public class DataPublisher implements Runnable {
private JPADAO dao;

public DataPublisher(JPADAO dao) {
    this.dao = dao;
}


@Override
public void run() {
    List<Entity> list = dao.getUpdateInformation();
    for(Entity entity : list) {
        dao.updateNotifiedStatus(entity.getId());
    }
}
}

我使用预定的线程池运行线程。 我使用 jpa 来更新数据库。更新状态的代码是这样的:

public class JPADAO {
private EntityManager em;

public JPADAO(EntityManager em) {
    if(em == null)
        throw new NullPointerException("Invalid em argument.");
    this.em = em;
}

public void updateNotifiedStatus(String id) {
    EntityTransaction transaction = em.getTransaction();
    transaction.begin();
    Entity request = em.find(Entity.class, id);
    request.setNotified(1);
    transaction.commit();   

}

当我启动应用程序时,问题是,第一次,所有数据都会正确更新。当我使用数据库客户端手动将通知的字段更改为 0 时,线程可以发现它们匹配要更新的条件。但他们永远不会更新到 1 了。 为什么数据不会在线程中更新?


只是一个更新: 我已经解决了这个问题。主要原因是在我这边,我的进程会用jpa访问数据库。但是其他进程也在以不同的方式访问同一个进程。因为 jpa 默认会从缓存中读取数据。每次在我的查询中,它只会从缓存中获取数据,而不知道数据库已更改。因此,要从数据库中获取最新更新的数据,我们需要在 eclipselink 中禁用缓存。这是我添加的配置:

<property name="eclipselink.query-results-cache" value="false"/>
<property name="eclipselink.cache.shared.default" value="false"/>
<property name="eclipselink.cache.size.default" value="0"/>
<property name="eclipselink.cache.type.default" value="None"/>

【问题讨论】:

  • 尝试在transaction.commit() 之前调用em.flush(),这有时有助于更新。

标签: java multithreading jpa eclipselink


【解决方案1】:

首先,这看起来应该在实体中处理,因此如果状态和通知值分别更改为活动和 0,业务逻辑本身会将通知值更改为 1。

其次,我不确定 DataPublisher 实例是如何在池中使用的,但只有一个实例可以重用,这意味着您一遍又一遍地使用同一个 EntityManager。因为 EntityManagers 缓存托管实例,所以每个 find 调用都会返回它使用该 id 缓存的实体 - 第一次调用从 db 加载数据,而后续迭代只会获取缓存的数据。缓存实体的通知值已经设置为 1 ,因此 JPA 无需更改任何内容。

有几种方法可以解决这个问题。完成后关闭dao中的em,需要时获取新的;在事务提交后清除 em,以便可以重用它并释放实体的当前状态,或者在实体上使用 em.refresh 强制将更改从数据库中拉入上下文。

【讨论】:

    猜你喜欢
    • 2020-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-23
    • 2015-11-25
    • 1970-01-01
    • 2011-12-03
    • 1970-01-01
    相关资源
    最近更新 更多