JPQL DELETE查询:删除另一个实体列表中的实体

时间:2014-07-03 00:16:45

标签: java sql jpa

我尝试编写一个JPQL查询,它删除另一个实体集合中的所有实体。 (示例代码,没有getter / setter和注释)

class Aa implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String value;
}

@Entity
class A implements Serializable {   
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @JoinColumn(nullable = false)
    @OneToOne
    private Aa aa;

    @OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
    private List<B> data;
}
@Entity
class B implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;


    private String value;
}

我尝试了以下内容:

DELETE FROM B b WHERE b.id IN(SELECT k.id FROM A a JOIN a.data k WHERE a.id = :id)

但它在外键违规异常中结束。 另一种方法是

DELETE FROM B b WHERE EXISTS(SELECT a FROM A a WHERE a.id = :id)

但它也以外键违规结束。

但是如果我直接在数据库上执行sql查询,比如

DELETE FROM B WHERE id = <a id number here>

然后没有错误发生...

EntityManager.remove()不是一个选项,因为我想删除大量的数据。

我很感谢每一个答案和帮助。

2 个答案:

答案 0 :(得分:0)

由于我没有足够的声誉,因此无法添加评论。

你跳过了注释,这是很重要的,因为它有助于知道哪一方,父母,孩子或者他们之间的某些东西控制着这种关系。例如,如果父方控制,则在某些情况下,在父方清空List并持续删除其子项就足够了。所以更多代码会有所帮助。

编辑1:

如果您使用的是JPA 2.0,则可以将orphanRemoval="true"添加到@OneToMany。然后从持久性中获取父级,执行parent.getData().clear(),然后执行EntityManager.merge(parent)或让孩子意识到关系。您正在尝试删除那些不了解其父母的孩子,因此我建议您通过家长这样做,或让他们知道。

答案 1 :(得分:0)

好的,在Syfors&#39;的帮助下建议我改变了A和B之间的关系:

class Aa implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String value;
}

@Entity
class A implements Serializable {   
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @JoinColumn(nullable = false)
    @OneToOne
    private Aa aa;

    @OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL}, mappedBy = "owner")
    private List<B> data;
}
@Entity
class B implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @OneToOne
    private A owner;


    private String value;
}

我也发现:

  

[...]通常最好在Java中定义ManyToOne后向引用[...]

来源:http://en.wikibooks.org/wiki/Java_Persistence/OneToMany

现在JPA没有为m:1关系生成一个thrid表,现在我的JPQL查询工作正常:

DELETE FROM B b WHERE b.id IN(SELECT k.id FROM A a JOIN a.data k WHERE a.id = :id)