ALTER TABLE 添加 ON DELETE CASCADE 语句

问题描述 投票:0回答:4

我想在 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 中的信息模式或系统目录来完成此操作吗?

hibernate postgresql cascade cascading-deletes postgresql-9.0
4个回答
4
投票

您所描述的是教科书外键约束使用

ON DELETE CASCADE
选项。

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
)并强制执行引用完整性


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


1
投票

我找到了答案:

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

   //in Grape object
   @OneToOne
   private Fruit fruit;

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 设置 - 并且您必须实施一个关于如何处理会话中对象删除的策略!

© www.soinside.com 2019 - 2024. All rights reserved.