JPA / OpenJPA 合并总是导致 SQL 更新嵌入式对象
JPA / OpenJPA merge always causes SQL UPDATE on Embedded objects
考虑以下 pojos:
@Embeddable
public class Info {
private String name;
public String getName(){
return name;
}
public void setName(String name){
this.name=name;
}
}
@Entity
public class Person {
@Id
private long pid;
public Person(long pid){
this.pid=pid;
}
@Embedded
private Info info = new Info();
public Info getInfo(){
return info;
}
}
和访问它的一些代码
{
Person p = new Person(1);
p.getInfo().setName("Foo");
EntityManager em = ...
em.merge(p); // <-- SQL INSERT or UPDATE expected
}
执行了以下 SQL:
第一次运行 merge() 执行以下操作(如预期):
- SELECT p.name FROM person p where p.pid=1
- INSERT INTO person (pid,name) VALUES (1,'Foo')
第二次运行 merge() 执行以下操作,这是意外的:
- SELECT p.name FROM person p where p.pid=1
- UPDATE person SET name='Foo' WHERE pid=1
为什么更新发生在第二次运行?即使 "Foo" 仍然等于 "Foo"?!
如果我不使用 Info Embeddable,而是将 "name" 属性放入 Person 类,则 merge() 的第二次运行会按预期工作:有一个 SELECT 但没有 UPDATE执行
对我来说这似乎是一个 OpenJPA 错误或缺少的功能,如果我切换到 EclipseLink 实现,一切都会按预期工作。
此外,在 .merge( new Entity() ) 期间对现有 ID(但在分离的实体上)使用 EclipseLink 更新(也取消)所有具有不同值的字段,而在 OpenJPA 中,空字段不同步到数据库.同样,EclipseLink 在这里按预期执行。
考虑以下 pojos:
@Embeddable
public class Info {
private String name;
public String getName(){
return name;
}
public void setName(String name){
this.name=name;
}
}
@Entity
public class Person {
@Id
private long pid;
public Person(long pid){
this.pid=pid;
}
@Embedded
private Info info = new Info();
public Info getInfo(){
return info;
}
}
和访问它的一些代码
{
Person p = new Person(1);
p.getInfo().setName("Foo");
EntityManager em = ...
em.merge(p); // <-- SQL INSERT or UPDATE expected
}
执行了以下 SQL:
第一次运行 merge() 执行以下操作(如预期):
- SELECT p.name FROM person p where p.pid=1
- INSERT INTO person (pid,name) VALUES (1,'Foo')
第二次运行 merge() 执行以下操作,这是意外的:
- SELECT p.name FROM person p where p.pid=1
- UPDATE person SET name='Foo' WHERE pid=1
为什么更新发生在第二次运行?即使 "Foo" 仍然等于 "Foo"?!
如果我不使用 Info Embeddable,而是将 "name" 属性放入 Person 类,则 merge() 的第二次运行会按预期工作:有一个 SELECT 但没有 UPDATE执行
对我来说这似乎是一个 OpenJPA 错误或缺少的功能,如果我切换到 EclipseLink 实现,一切都会按预期工作。
此外,在 .merge( new Entity() ) 期间对现有 ID(但在分离的实体上)使用 EclipseLink 更新(也取消)所有具有不同值的字段,而在 OpenJPA 中,空字段不同步到数据库.同样,EclipseLink 在这里按预期执行。