Java 为什么OpenJPA在删除之前调用更新?
我正在尝试使用Java 为什么OpenJPA在删除之前调用更新?,java,jpa,one-to-many,openjpa,Java,Jpa,One To Many,Openjpa,我正在尝试使用entityManager.remove(parent)删除具有一对多父子关系的父实体。但是,从SQL日志中,我看到OpenJPA首先调用UPDATE,并尝试为notnull字段设置null executing prepstmnt 773394836 UPDATE child SET parent_id = ? WHERE parent_id = ? [params=(null) null, (long) 16] executing prepstmnt 1127292223 DEL
entityManager.remove(parent)
删除具有一对多父子关系的父实体。但是,从SQL日志中,我看到OpenJPA首先调用UPDATE
,并尝试为notnull
字段设置null
executing prepstmnt 773394836 UPDATE child SET parent_id = ? WHERE parent_id = ? [params=(null) null, (long) 16]
executing prepstmnt 1127292223 DELETE FROM parent WHERE id = ? [params=(long) 16]
executing prepstmnt 1297966852 DELETE FROM child WHERE lookup_id = ? AND parent_id = ? [params=(int) 1, (long) 16]
我如何配置我的类以防止第一次调用UPDATE
我的班级:
@Entity
@Table(name = "parent")
public class Parent {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
private String name;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER,
orphanRemoval = true)
@JoinColumn(name = "parent_id")
private List<Child> children;
// getters, etc.
}
@Entity
@Table(name = "child")
@IdClass(ChildPrimaryKey.class)
public class Child {
@Id
@Column(name = "parent_id", nullable = false, updatable = false)
private long parentId;
@Id
@Column(name = "lookup_id")
private int lookupId;
@ManyToOne
@JoinColumn(name = "parent_id", referencedColumnName = "id",
nullable = false, insertable = false, updatable = false)
private Parent parent;
// getters, etc.
}
这是一个假设
我认为发生的事情是UPDATE语句是为了避免在执行删除时违反约束。或者至少,这就是OpenJPA认为需要进行更新的原因
有两种可能性:
- OpenJPA是正确的,更新是必要的
- OpenJPA是错误的,更新是冗余的
@OneToMany
注释上指定mappedBy
元素(也就是说,您没有告诉OpenJPAChild
是关系的所有者)。这是我第一次猜测你为什么会看到这种行为。从:
如果关系是双向的,则mappedBy元素必须是
用于指定要删除的实体的关系字段或属性
是关系的所有者
若要解决此问题,请更改父项的@OneToMany
以包含mappedBy
元素,并删除@JoinColumn
:
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL,
fetch = FetchType.EAGER, orphanRemoval = true)
private List<Child> children;
我怀疑更新失败(它试图将PK/NOT NULL列设置为NULL),我尝试在数据库中手动删除。只需从父级删除id=?,即可执行删除操作。不需要更新。子项的第二次删除也是不必要的。使用mappedBy而不是@JoinColumn会在插入时导致异常,因为OpenJPA尝试将0作为父项。\u id:
由以下原因引起:org.apache.OpenJPA.lib.jdbc.ReportingSQLException:无法添加或更新子行:外键约束失败(`test`.`child`,CONSTRAINT``fk_library_code``外键(`parent_id`)在更新级联的删除级联上引用`parent`(`id``){prepsmnt 972578961插入子(lookup_id,parent_id)值(?,[params=(int)1,(long)0]}[code=1452,state=23000]
。我认为mappedBy是用于连接表的。在进一步研究之后,在这种情况下使用mappedBy
是正确的方法。但是,子实体和父实体必须分开管理。例如,必须将子实体上的parent\u id
设置为正确的值,子实体必须手动删除,等等>@在这种情况下不需要MapsId
。@VictorLyuboslavsky如果您使用@MapsId
,parentId
将自动从Parent
中为您复制。您的用例正是以下内容中描述的:“指定为父实体的简单主键提供映射的ManyToOne或OneToOne关系属性"。此外,您不必单独删除子项…您可以显示更新的实体吗?如果我使用@MapsId
,我会得到一个无意义的异常:com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:“字段列表”中的未知列“t1.lookupId”
。我认为@MapsId
不打算与@IdCl一起使用驴
@VictorLyuboslavsky你可能是对的…我没有注意到你指定了@IdClass
。你试过使用吗?而且,我认为我的答案没有解决你的问题…你是如何解决你的问题的?
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL,
fetch = FetchType.EAGER, orphanRemoval = true)
private List<Child> children;
@Id
private long parentId;
// ...
@MapsId("parentId")
@ManyToOne
@JoinColumn(name = "parent_id", referencedColumnName = "id", nullable = false)
private Parent parent;