Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么OpenJPA在删除之前调用更新?_Java_Jpa_One To Many_Openjpa - Fatal编程技术网

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是错误的,更新是冗余的
我建议您使用相关的“父”行和“子”行设置数据库,然后尝试在不进行更新的情况下手动删除一行或另一行。这将决定是否真的需要更新

根据结果,要么忽略问题,尝试更改模式和/或注释,要么查看OpenJPA问题跟踪程序中是否存在错误报告/解决方法。(您还可以尝试一些实验,看看Hibernate的行为是否与MySQL相同和/或这是否特定。)

我不确定是什么原因导致JPA决定执行这些查询,但是,我确实注意到您的映射存在一些问题

首先,您没有在
@OneToMany
注释上指定
mappedBy
元素(也就是说,您没有告诉OpenJPA
Child
是关系的所有者)。这是我第一次猜测你为什么会看到这种行为。从:

如果关系是双向的,则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;