为什么OpenJPA在DELETE之前调用UPDATE?

时间:2013-06-28 03:04:27

标签: java jpa one-to-many openjpa

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

2 个答案:

答案 0 :(得分:2)

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

首先,您没有在mappedBy注释中指定@OneToMany元素(即您没有告诉OpenJPA Child是该关系的所有者)。这是我第一次猜到你为什么会看到这种行为。来自API specification

  

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

要解决此问题,请更改Parent的{​​{1}}以包含@OneToMany元素并删除mappedBy

@JoinColumn

此外,我注意到您尝试将 @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true) private List<Child> children; 的ID用作Parent ID的一部分,并在Child上有两个字段映射到同一个PK列( Childparent)。处理此问题的首选方法是@MapsId

parentId

答案 1 :(得分:0)

这是一个假设。

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

有两种可能性:

  • OpenJPA是正确的,必须更新
  • OpenJPA错误,UPDATE是多余的

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

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