9

我有一个A具有基本类型集合的实体(例如String)。我使用这样的映射是因为与每个实例相关联的字符串A依赖于A的生命周期。如果我想A从数据库中删除一个实例,我还希望删除其关联String的 s。

我的映射如下:

@Entity
public class A {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(name = "name", nullable = false, unique = true)
    private String name;

    @ElementCollection(fetch = FetchType.EAGER)
    @CollectionTable(name = "AStrings", joinColumns = @JoinColumn(name = "id"))
    @Column(name = "strings", nullable = false)
    private Set<String> strings;
}

如果我创建一个实例A并为其添加一些字符串,那么我可以使用Session.save(myInstance). 的实例A及其关联String的 s 都被持久化。

但是,如果我想从数据库中删除相同的实例,使用Session.createQuery("delete A a where a.name = ?").setString(0, name).executeUpdate(),我会得到一个外键约束错误:

无法删除或更新父行:外键约束失败

但是,我希望String在删除 ' 实例之前自动删除关联的As ,但似乎并非如此。我也没有找到指定级联规则的方法。

我的配置有问题吗?

谢谢


编辑: 我也试过@Cascade(CascadeType.DELETE)在现场使用strings,但它仍然没有帮助。通过查看数据库,我看不到ON DELETE有关外键的任何策略。

有同样问题的人打开了 JIRA:https ://hibernate.onjira.com/browse/HHH-4301 。必须存在解决方案(或解决方法),我不能是唯一使用@ElementCollection.

我已经解决了这个问题。我认为使用 Session.delete() 删除或使用 HQL 查询是等效的,但似乎不是。使用 HQL 查询,依赖对象不会自动删除,所以我得到一个外键约束错误。使用 Session.delete() 解决了这个问题。此外,Hibernate 似乎没有使用数据库的级联功能,因为我在生成的 DDL 中仍然没有看到任何 CASCADE 策略,它在内部处理了这个。

4

4 回答 4

7

我已经解决了这个问题。

我认为使用Session.delete()或使用HQL查询删除实体是等效的,但似乎不是。使用HQL查询,依赖对象不会自动删除,所以我得到一个外键约束错误,如问题中所述。

使用Session.delete()可以解决问题。此外,Hibernate 似乎没有使用数据库的级联功能,因为我在生成的 DDL 中仍然没有看到任何 CASCADE 策略,它在内部处理了这个。


对于版主:

我过去已经添加了我对问题的答案(如您所问),但由于这是解决问题的答案并且没有(来自其他用户)发布任何答案,我想我应该在这里发布它作为答案.

于 2013-01-15T14:40:59.210 回答
0
  • 添加orphanRemoval配置怎么样?

  • A.strings().clear()还是在删除一个A实例之前手动调用?

如果以上两个都不起作用,也许有一些错误ElementCollection

于 2012-08-29T09:16:11.433 回答
0

测试强制删除孤儿:

@Cascade( { org.hibernate.annotations.CascadeType.ALL, 
    org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
于 2012-08-29T09:20:15.503 回答
-2

添加“@Cascade”(org.hibernate.annotations.Cascade)

前任:

@Entity
public class A {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @ElementCollection(fetch = FetchType.EAGER)
    @CollectionTable(name = "AStrings", joinColumns = @JoinColumn(name = "id"))
    @Column(name = "strings", nullable = false)
    @Cascade(value=org.hibernate.annotations.CascadeType.ALL)
    private Set<String> strings;
}
于 2012-08-29T09:03:28.700 回答