Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JPA merge()只更新一些字段。其他更改未被识别_Java_Hibernate_Jpa_Merge_Persistence - Fatal编程技术网

Java JPA merge()只更新一些字段。其他更改未被识别

Java JPA merge()只更新一些字段。其他更改未被识别,java,hibernate,jpa,merge,persistence,Java,Hibernate,Jpa,Merge,Persistence,这是我的第一篇文章。所以,我希望这个问题是令人兴奋的。 我有一个java程序,它使用Swing+JPA来处理 PostgreSQL数据库。我使用EclipseLink JPA 2.0作为我的 持久性提供者。我的实体类是自动创建的 由Netbeans 7.2.1生成 我面临的问题是:在更新过程中,我改变了四个 使用find()检索对象的字段,然后使用 merge()更新数据库中的对象。三个 表中识别并更新了四项变更, 但其中一个没有更新 我尝试了几种方法来解决这个问题:我尝试更改与持久化单元的同步

这是我的第一篇文章。所以,我希望这个问题是令人兴奋的。 我有一个java程序,它使用Swing+JPA来处理 PostgreSQL数据库。我使用EclipseLink JPA 2.0作为我的 持久性提供者。我的实体类是自动创建的 由Netbeans 7.2.1生成

我面临的问题是:在更新过程中,我改变了四个 使用find()检索对象的字段,然后使用 merge()更新数据库中的对象。三个 表中识别并更新了四项变更, 但其中一个没有更新

我尝试了几种方法来解决这个问题:我尝试更改与持久化单元的同步策略相关的选项,更改代码中的行位置(随着其他字段的更新),我还尝试使用注释@Basic(optional=false)作为实体类字段的前缀。。我的任何一次尝试都成功了

下面是我的实体类(Senha.java)的代码:

当我在数据库中查看时,字段Status Hchamada、Nchamadas被更新,但是字段Painel(布尔类型)没有更新。下面我提供了JPA/EclipseLink的日志摘录:

**begin transaction**

**[EL Fine]**: 
Thread(Thread[AWT-EventQueue-1,4,file:...-threadGroup])--UPDATE senha SET
 hchamada = ?, nchamadas = ? WHERE (id = ?)
    bind => [02:15:49, 2, 4]

**[EL Finer]**:
Thread(Thread[AWT-EventQueue-1,4,file:...-threadGroup])

**commit transaction**
查看代码,我在更改值之前放置了一个if,以查看JPA管理的实体是否已经具有我想要设置的值。下面是修改后的代码:

EntityManagerFactory emf = ctrlCreateEntityManager();
EntityManager em = emf.createEntityManager();

...

current = em.find(Senha.class, getCurrentId());
if (current.getStatus().equals('W')) {
    em.getTransaction().begin();
    current.setStatus(current.getNchamadas() >= 2 ? 'L' : current.getStatus());
    current.setHchamada(Calendar.getInstance().getTime());
    current.setNchamadas(current.getNchamadas() + 1);
    if (current.getPainel()) {
        System.out.println("Painel is already true");
    } 
    current.setPainel(true);
    em.merge(current);
    em.getTransaction().commit();
    frame.getLbNumeroSenha().setText(formatSenha(current.getNumeracao()));
} 
... 
em.close();
emf.close();
当我运行代码时,我得到一条消息,指示我的实体已经设置了我要在数据库中写入的值。因此,我认为JPA/EclipseLink不会更新该值,如果它与它所管理的实体类的关系没有改变的话。但是,在运行代码之前,我手动将数据库字段painel更新为false。然后:

  • 我不明白为什么在检索实体时无法识别此更新
  • 如何强制JPA更新所有字段(即使没有更改)
  • 可能的(不太好的)解决方案:

    就在发布这条消息的那一刻,我意识到了一个可能的解决方案(不太好)。在更新之前修改代码,从数据库中删除实体(提交),然后启动其他事务,更新对象。它是,再次删除和持久化对象。它起作用了


    在我尝试在同一事务中使用remove()和merge()之前,它不起作用。

    根据实现的不同,EclipseLink在您的情况下,JPA将始终插入所有映射列,并且只更新已更改的列。如果需要其他操作,则可以使用API、SQL或存储过程自定义用于这些操作的查询

    您可以使用Hibernate dynamicInsert和DynamicCupDate修改此行为,但不能使用EclipseLink。这些迁移指南告诉您这一点


    您尝试过不同的列定义吗?例如,请参见.Hi@SpaceTrucker,我尝试更改字段的数据类型和表中列的顺序,并尝试将注释另存为整数。但其中任何一个都能解决问题。JPA继续从数据库中检索一个字段“painel”未更新为最新值的值。将em.find()配置为使用悲观锁定。2.在使用find()而不指定锁定后,请使用em.refresh(object)。您可能希望尝试删除()、刷新()、持久化(),然后提交()。刷新是一种反模式,但这取决于你。@DiegoDias你找到解决这个问题的方法了吗?我在EclipseLink上也面临着类似的问题
    **begin transaction**
    
    **[EL Fine]**: 
    Thread(Thread[AWT-EventQueue-1,4,file:...-threadGroup])--UPDATE senha SET
     hchamada = ?, nchamadas = ? WHERE (id = ?)
        bind => [02:15:49, 2, 4]
    
    **[EL Finer]**:
    Thread(Thread[AWT-EventQueue-1,4,file:...-threadGroup])
    
    **commit transaction**
    
    EntityManagerFactory emf = ctrlCreateEntityManager();
    EntityManager em = emf.createEntityManager();
    
    ...
    
    current = em.find(Senha.class, getCurrentId());
    if (current.getStatus().equals('W')) {
        em.getTransaction().begin();
        current.setStatus(current.getNchamadas() >= 2 ? 'L' : current.getStatus());
        current.setHchamada(Calendar.getInstance().getTime());
        current.setNchamadas(current.getNchamadas() + 1);
        if (current.getPainel()) {
            System.out.println("Painel is already true");
        } 
        current.setPainel(true);
        em.merge(current);
        em.getTransaction().commit();
        frame.getLbNumeroSenha().setText(formatSenha(current.getNumeracao()));
    } 
    ... 
    em.close();
    emf.close();