我有2个对象连接在一起,定义如下:

public class A {
    ...
    @Id
    @Column(name = "A_ID")
    @SequenceGenerator(...)
    @GeneratedValue(...)
    public Long getA_ID();

    @OneToOne(mappedBy = "a", fetch = FetchType.LAZY, cascade = CascadeType.ALL, targetEntity = B.class)
    public B getB();
    ...
}

@VirtualAccessMethods(get = "getMethod", set = "setMethod")
public class B {
    ...

    @Id
    public Long getA_ID();

    @MapsId
    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL ,targetEntity = A.class)
    @JoinColumn(name="A_ID")
    public A getA();

    getMethod(String name);

    setMethod(String name, Object value);
    ...
}


当我进入B并进入A的em.merge(A)INSERT时,一切正常。但是,如果我对更新执行相同的操作,它将仅更新A。更新逻辑如下所示:

@Transactional
public void update(Object fieldOnANewValue, Object fieldOnBNewField) {
    A objA = em.executeQuery(...) //loads objA by primary key
    objA.setFieldOnA(fieldOnANewValue);
    B objB = objA.getB(); //lazy loads objB
    objB.setMethod("FieldOnB", fieldOnBNewValue);
}


如果查看日志,则有一条SQL UPDATE语句提交对A所做的更改,但没有提交给B的更改。如果我手动调用em.merge(objB),则存在相同的问题。有谁确切地知道EclipseLink是做什么来确定是否生成UPDATE语句的?特别是关于@VirtualAccessMethods?但是,我之前设置的@OneToOne映射有所不同,然后em.merge(objB)可以正常工作,再加上INSERT可以工作,所以我不确定是否是问题所在。另一方面,如果我还有另一个也连接到A上的对象,但是只是一个像A is这样的普通POJO,则会为此生成UPDATE语句。缓存已关闭,并且我已验证对象在调用合并之前已正确更新。

最佳答案

请显示完整的代码和映射。

鉴于您正在使用虚拟访问权限(您是否正确使用了它?),这可能是与虚拟访问权限有关的某种变更跟踪问题。在不使用虚拟访问的情况下会发生此问题吗?

尝试设置

@ChangeTracking(ChangeTrackingType.DEFERRED)

看看是否有影响。

您也可以尝试

@InstantiationCopyPolicy

10-08 01:45