ALTER TABLE添加ON DELETE CASCADE语句

时间:2012-07-18 00:25:40

标签: hibernate postgresql cascade cascading-deletes postgresql-9.0

我想在PostgreSQL中使用Hibernate执行以下操作:

 ALTER TABLE fruits ADD CONSTRAINTS id ON DELETE CASCADE;

显然,我上面的代码不起作用,所以我正在寻找正确的陈述。

如果我不能那样做,那么下面的内容如何:

我的表fruits中有很多数据。 id中的fruits字段用作表grapes的外键。我需要删除fruits中的特定行,并希望删除级联到grapes并删除grapes中具有指定id的所有条目。我该怎么做?

delete from fruits where id = 1 cascade; 

注意:我不想进行加入并删除grape中的相应数据。这只是一个例子。在实际应用程序中,大量表依赖于fruits

由于我使用的是Hibernate,对于使用delete语句的情况,可以使用hibernate帮助吗?
或者我可以使用PostgreSQL中的信息架构或系统目录吗?

4 个答案:

答案 0 :(得分:4)

您所描述的是使用ON DELETE CASCADE选项的教科书foreign key constraint

SQL 中,您可以在场景中创建表grapes时隐式创建它:

CREATE TABLE grapes (
  grape_id int PRIMARY KEY
  fruit_id int REFERENCES fruits(fruit_id) ON DELETE CASCADE
  );

或者您可以稍后添加:

ALTER TABLE grapes
ADD CONSTRAINT grapes_fruit_id_fkey FOREIGN KEY (fruit_id)
REFERENCES fruits (fruit_id) ON DELETE CASCADE;

您不直接编辑系统目录 - 您几乎从未这样做过!这就是上面提到的DDL语句。

请注意,外键约束需要在引用列(在您的案例中为fruits.fruit_id)上使用唯一索引或主索引,并强制执行referential integrity

答案 1 :(得分:1)

这是一个单向的父子关系,您希望父级的更改级联到子级,但反之则不然。使用注释,我们可以实现这一目标。在fruits实体中:

@Cascade(value = { org.hibernate.annotations.CascadeType.ALL, 
    org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
@OneToMany(fetch = FetchType.LAZY, mappedBy = "fruit")
public Set<Grape> getGrapes() {
    return grapes;
}

在'葡萄'实体中:

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "fruit_id")
public Fruit getFruit() {
    return fruit;
}

当您更新或删除父fruit时,更改将自动级联到grape个孩子。

答案 2 :(得分:1)

我找到了答案:

    //in Fruit object
    @OneToMany(mappedBy = "fruit", orphanRemoval=true)
    private List<Grape> grapes;

   //in Grape object
   @OneToOne
   private Fruit fruit;

答案 3 :(得分:0)

<强>动机

这对我不起作用,我设置了

<property name="show_sql">true</property> 

并且输出没有说明...ON DELETE CASCADE...

之类的内容

我找到了另一个对我有用的解决方案:

让我们假设您有一个作者类和一个作者书的类,并且您希望在删除作者时自动删除所有书籍(通过hibernate,sql-query,...)并且有理由你不能(总是)通过session.delete()删除。

也许:

session.createSQLQuery("DELETE FROM author").executeUpdate();

<强>解决方案

因此,您的作者类可能如下所示:

@Entity
@Table(name = "author")
public class Author {

   @Id
   @GeneratedValue(generator = "increment")
   @GenericGenerator(name = "increment", strategy = "increment")
   @Column(name = "ID")
   private Integer id;

   @Column(name = "NAME")
   private String name;

   @OneToMany(mappedBy = "author")
   private Set<Book> books;
...

并且课本如下:

@Entity
@Table(name = "book")
public class Book {

   @Id
   @GeneratedValue(generator = "increment")
   @GenericGenerator(name = "increment", strategy = "increment")
   @Column(name = "ID")
   private Integer id;

   @Column(name = "TITLE")
   private String title;

   @ManyToOne
   @JoinColumn(name = "AUTHOR_ID", foreignKey = @ForeignKey(name = "FK_BOOK_author_AUTHOR_ID"))
   private Author author;
...

诀窍是使用

自行命名外键约束
foreignKey = @ForeignKey(name = "FK_BOOK_author_AUTHOR_ID")

然后添加

<property name="hibernate.hbm2ddl.import_files">update.sql</property>

hibernate.cfg.xml (不要忘记 hibernate.hbm2ddl.auto )。然后 update.sql 包含表约束的更新:

ALTER TABLE `book` DROP FOREIGN KEY `FK_BOOK_author_AUTHOR_ID`; 
ALTER TABLE `book` ADD CONSTRAINT `FK_BOOK_author_AUTHOR_ID` FOREIGN KEY (`AUTHOR_ID`) REFERENCES `author`(`ID`) ON DELETE CASCADE;

所以hibernate总是能够删除/更改约束,因为它知道约束的名称 - 你还应该检查@Cascade设置 - 你必须实现一个策略来处理如何处理你的对象的删除会话!