【问题标题】:JPQL DELETE query: delete entities within a list of another entityJPQL DELETE 查询:删除另一个实体列表中的实体
【发布时间】:2014-07-04 01:00:50
【问题描述】:

我尝试编写一个 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() 不是一个选项,因为我想删除大量数据。

感谢您的每一个回答和帮助。

【问题讨论】:

    标签: java sql jpa


    【解决方案1】:

    我没有足够的声望,无法添加 cmets。

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

    编辑 1:

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

    【讨论】:

    • 你是对的。我在我的主要帖子中添加了注释。父方正在控制关系。但是我有大量的 A 对象,它们存储了大量的 B 对象。这就是我使用 DELETE 语句的原因。
    • 问题是,如果我调用 parent.getData(),那么列表中的所有实体都会被选中(无论获取类型是延迟还是渴望)。我试图阻止这种情况。
    • 我的第一种方法是可行的。我已经激活了 jpa 的日志功能,并在 squirrel 中测试了生成的查询。但是,jpa 与第三个表生成 m:n 关系,这会触发外键违规异常。 ://
    【解决方案2】:

    好的,在 Syfors 的建议下,我改变了 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 关系生成第三个表,现在我的 JPQL 查询工作正常:

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

    【讨论】:

      猜你喜欢
      • 2015-02-12
      • 2017-06-30
      • 1970-01-01
      • 2015-09-12
      • 1970-01-01
      • 1970-01-01
      • 2013-02-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多