Java Eclipselink merge无法为更改的值生成UPDATE语句
我有两个对象连接在一起,定义如下:Java Eclipselink merge无法为更改的值生成UPDATE语句,java,jpa,orm,eclipselink,Java,Jpa,Orm,Eclipselink,我有两个对象连接在一起,定义如下: public class A { ... @Id @Column(name = "A_ID") @SequenceGenerator(...) @GeneratedValue(...) public Long getA_ID(); @OneToOne(mappedBy = "a", fetch = FetchType.LAZY, cascade = CascadeType.ALL, targetEnti
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);
...
}
当我转到em.merge(A)
并将B连接到A以进行插入时,一切正常。但是,如果我对更新执行相同的操作,它将只更新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);
}
如果我查看日志,会有一个SQLUPDATE
语句提交我对a所做的更改,但对B没有任何更改。如果我手动调用em.merge(objB)
则存在相同的问题。有人确切地知道EclipseLink是如何决定是否生成UPDATE
语句的吗?特别是关于@VirtualAccessMethods
?但是,我以前的@OneTone映射设置不同,并且em.merge(objB)
工作正常,再加上INSERT
工作正常,所以我不确定这是否是问题所在。另一方面,如果我有另一个对象也连接到了,但只是像is一样是一个普通POJO,则会为此生成UPDATE
语句。缓存已关闭,在调用merge之前,我已验证对象是否已正确更新。请显示完整的代码和映射
假设您正在使用虚拟访问(您是否正确地使用了它?),那么这可能是与虚拟访问相关的某种更改跟踪问题。问题是否在不使用虚拟访问的情况下发生
试着设置
@ChangeTracking(ChangeTrackingType.DEFERRED)
看看这是否有影响
你也可以试试
@实例化CopyPolicy请显示完整的代码和映射
假设您正在使用虚拟访问(您是否正确地使用了它?),那么这可能是与虚拟访问相关的某种更改跟踪问题。问题是否在不使用虚拟访问的情况下发生
试着设置
@ChangeTracking(ChangeTrackingType.DEFERRED)
看看这是否有影响
你也可以试试
@实例化CopyPolicy合并操作甚至不应该是必需的,因为A和B是附加的。对它们所做的任何更改都应该在刷新时透明地写入数据库。“合并”必须用于将分离的实体状态合并到附着的实体状态。合并一个已经连接的实例是不必要的。删除em.merge()
调用会导致正在生成的A的UPDATE
的问题相同,但B的问题不同。问题必须在//将updatedFoa复制到objA
之后。给我们看看这段代码。我想你是指B。我所做的就是用更新后的值调用setMethod()。setMethod()只覆盖映射中的值。我不知道的是EclipseLink在字段更新时如何确定这些虚拟方法。在地图上,这个领域显然是更新了,但日食没有注意到这一点。根据你告诉我的,这之前一定有效的原因是因为我们必须创建新的实体,因为连接是只读的,然后当我们调用merge时,它将获取更改。不,我是指A。如果它所做的只是更新映射中的一个值,那么我不明白为什么B会被修改,因为我猜映射是,用于保持与另一实体的关联。没有看到任何具体的代码,我们只能猜测到底出了什么问题。如果您需要帮助,请向我们展示代码。合并操作甚至不需要,因为A和B是附加的。对它们所做的任何更改都应该在刷新时透明地写入数据库。“合并”必须用于将分离的实体状态合并到附着的实体状态。合并一个已经连接的实例是不必要的。删除em.merge()
调用会导致正在生成的A的UPDATE
的问题相同,但B的问题不同。问题必须在//将updatedFoa复制到objA
之后。给我们看看这段代码。我想你是指B。我所做的就是用更新后的值调用setMethod()。setMethod()只覆盖映射中的值。我不知道的是EclipseLink在字段更新时如何确定这些虚拟方法。在地图上,这个领域显然是更新了,但日食没有注意到这一点。根据你告诉我的,这之前一定有效的原因是因为我们必须创建新的实体,因为连接是只读的,然后当我们调用merge时,它将获取更改。不,我是指A。如果它所做的只是更新映射中的一个值,那么我不明白为什么B会被修改,因为我猜映射是,用于保持与另一实体的关联。没有看到任何具体的代码,我们只能猜测到底出了什么问题。如果您需要帮助,请向我们展示代码。我不知道虚拟访问是否被正确使用。由于这样一个事实,如果我添加对象C和D,其中C是一个普通的POJO,D是像B一样的虚拟访问,C工作,但B和D不工作,所以我相当确定这个问题与虚拟访问的更改跟踪有关。我现在就试试这些建议。@ChangeTracking(ChangeTrackingType.DEFERRED)为具有虚拟访问权限的对象生成了更新语句。非常感谢你,詹姆斯!我不知道虚拟访问是否被正确使用。由于这样一个事实,如果我添加对象C和D,其中C是一个普通的POJO,D是像B一样的虚拟访问,C工作,但B和D不工作,所以我相当确定这个问题与虚拟访问的更改跟踪有关。我现在就试试这些建议。@ChangeTracking(ChangeTrackingType.DEFERRED)为具有虚拟访问权限的对象生成了更新语句。非常感谢你,詹姆斯!