JPA合并第一次不起作用,但第二次起作用

问题描述 投票:0回答:1

我知道这很普遍,关于合并而不更新数据库中的数据,存在很多问题。但这有点不同。

从前端,当我单击保存按钮时,我可以看到CaseSpecimen中所有三个属性的数据都已更新,但是在此对象上调用合并时,它不会更新数据库。返回响应后,如果我再次单击保存按钮,因为该字段具有所需的数据,则再次在CaseSpecimen对象上调用合并后,这次它将数据保存在数据库中。

而且这仅针对一种标本类型发生。假设针对案例c,我们有2个样本类型A和B。如果我更新Type A中的值并单击Save,它将更新数据库中的数据。但是,如果我对Type B做完全相同的操作,它将不会第一次更新数据,但是如果我第二次单击保存按钮,那么值将在数据库中更新。

SpecModel.java

@Entity
@Table(name = "CASE_SPECIMEN")
@NamedQuery(name = "CaseSpecimen.findAll", query = "SELECT c FROM CaseSpecimen c")
@XmlAccessorType(XmlAccessType.FIELD)
public class CaseSpecimen extendsBaseEntity implements Serializable, 
Comparable<CaseSpecimen> {
    private static final long serialVersionUID = 1L;

    @Column(name = "SPECIMEN_BODY_SITE")
    private String bodySite;

    @Column(name = "SPECIMEN_PROCEDURE")
    private String procedureName;

    @Column(name = "SPECIMEN_SOURCE")
    private String specimenSource;

   ... 
   getters and setters
}

主体

@Entity
@Table(name = "`CASE`")
@XmlAccessorType(XmlAccessType.FIELD)
public class Case extends BaseEntity implements Serializable {
public static final String CASE_CODE_SEPERATOR = "-";

private static final long serialVersionUID = 1L;

   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Column(name = "CASE_ID")
   @GsonIgnore
   @XmlTransient
   private int id;

   @OneToMany(mappedBy = "patientCase", cascade = { CascadeType.MERGE, CascadeType.PERSIST })
   @NotFound(action = NotFoundAction.IGNORE)
   private Set<CaseSpecimen> caseSpecimens;

   ...
   getters and setters
}

案例道:

@Singleton
public class CaseDao extends GenericEntityDAO<PendingList> {
    @PersistenceContext(name = "APP_DB")
    protected EntityManager entityManager; 

    public CaseSpecimen updateCaseSpecimen(CaseSpecimen specimen) {
        return entityManager.merge(specimen);
    }
}

控制器:

 for (CaseSpecimen specimen : case.getCaseSpecimens()) {
    ... if the updated object from front end the below line will execute
    caseSpecimensUpdatedList.add(caseService.updateCaseSpecimen(specimen));
}

CaseService:当前是一个额外的层。这仅称为“ Dao方法”。

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" 
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
            xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
            http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
        <persistence-unit name="APP_DB"  >
             <jta-data-source>java:jboss/datasources/AppDataSource</jta-data-source>
        <properties>
        <property name="jboss.entity.manager.jndi.name" value="java:/AppEntityManager"/>
        <property name="wildfly.jpa.default-unit" value="true"/>
        <property name="hibernate.default_batch_fetch_size" value="100"/>
        <property name="hibernate.event.merge.entity_copy_observer" value="allow"/>

    </properties>
</persistence-unit>

java hibernate jpa merge ejb-3.0
1个回答
0
投票

如果您阅读了合并的文档,将会发现:

将给定实体的状态合并到当前持久性上下文中。

这并不意味着数据库将立即更新!持久性上下文充当事务后写式高速缓存,对任何实体状态更改进行排队。像任何后写式缓存一样,更改首先在内存中应用,并在刷新期间与数据库同步。刷新操作接受每个实体状态更改,并将其转换为INSERT,UPDATE或DELETE语句。

确实是flush文档说:

将持久性上下文同步到基础数据库。

这在当前交易中显然是正确的。直到提交事务,更改才可见。

如果未明确调用刷新,则持久提供将遵循应具有不同设置的策略:AUTO或COMMIT。

再次阅读FlushModType的文档说:

在事务中执行查询时,如果在服务器上设置了FlushModeType.AUTOQuery或TypedQuery对象,或者如果持久性上下文的刷新模式设置为AUTO(默认值),并且尚未为Query或TypedQuery对象指定刷新模式设置,则持久性提供程序负责确保对状态的所有更新持久化上下文中所有可能影响查询结果的实体中的所有实体对于查询的处理都是可见的。持久性提供程序实现可以通过将这些实体刷新到数据库或通过其他某种方式来实现。

如果设置了FlushModeType.COMMIT,则未指定对持久化上下文中的实体进行查询更新的效果。

© www.soinside.com 2019 - 2024. All rights reserved.