0

我正在尝试使用删除具有一对多父子关系的父实体entityManager.remove(parent)。但是,从 SQL 日志中,我看到 OpenJPAUPDATE首先调用并尝试为NOT NULL字段设置 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.
}

我的数据库表(在 MySQL 中):

CREATE  TABLE IF NOT EXISTS `parent` (
  `id` BIGINT NOT NULL AUTO_INCREMENT ,
  `name` VARCHAR(50) NOT NULL ,
  PRIMARY KEY (`id`))
ENGINE = InnoDB;

CREATE  TABLE IF NOT EXISTS `child` (
  `lookup_id` INT NOT NULL ,
  `parent_id` BIGINT NOT NULL ,
  PRIMARY KEY (`parent_id`, `lookup_id`) ,
  INDEX `fk_library_code_idx` (`parent_id` ASC) ,
  CONSTRAINT `fk_library_code`
    FOREIGN KEY (`parent_id` )
    REFERENCES `parent` (`id` )
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB;
4

2 回答 2

2

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

首先,您没有在注释mappedBy上指定元素@OneToMany(即,您没有告诉 OpenJPAChild是关系的所有者)。这将是我对您为什么会看到这种行为的第一个猜测。从API 规范

如果关系是双向的,则必须使用 mappedBy 元素来指定作为关系所有者的实体的关系字段或属性。

要解决此问题,请更改您Parent的 's@OneToMany以包含该mappedBy元素并删除@JoinColumn

  @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, 
             fetch = FetchType.EAGER, orphanRemoval = true)
  private List<Child> children;

此外,我注意到您正在尝试使用Parent's ID 作为 's ID 的一部分,并且在映射到同一个 PK 列(和)Child时有两个字段。处理此问题的首选方法是:ChildparentparentId@MapsId

  @Id
  private long parentId;

  // ...

  @MapsId("parentId")
  @ManyToOne
  @JoinColumn(name = "parent_id", referencedColumnName = "id", nullable = false)
  private Parent parent;
于 2013-06-28T06:11:39.643 回答
0

这是一个假设。

我认为正在发生的是 UPDATE 语句是为了避免在执行 DELETE 时违反约束。或者至少,这就是 OpenJPA认为它需要进行更新的原因。

有两种可能:

  • OpenJPA 是对的,需要 UPDATE
  • OpenJPA 错误,UPDATE 是多余的

我建议您使用相关的“父”和“子”行设置数据库,然后尝试手动删除一行或另一行而不执行更新。这将确定 UPDATE 是否真的有必要。

根据结果​​,要么忽略问题,尝试更改架构和/或注释,要么查看 OpenJPA 问题跟踪器中是否有错误报告/解决方法。(您也可以尝试一些实验来查看 Hibernate 的行为方式是否相同和/或这是否特定于 MySQL。)

于 2013-06-28T04:16:01.767 回答