ALTER TABLE添加ON DELETE CASCADE语句



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

 ALTER TABLE fruits ADD CONSTRAINTS id ON DELETE CASCADE;

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

如果我不能做到这一点,那么下面的怎么样:

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

delete from fruits where id = 1 cascade; 

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

既然我使用的是Hibernate,那么当我使用delete语句时,Hibernate能帮我吗
或者我可以用PostgreSQL中的信息模式或系统目录来做这件事吗?

您所描述的是使用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),并强制执行引用完整性。

这是一种单向的父子关系,您希望父级的更改级联到子级,但反之亦然。使用注释,我们可以实现这一点。在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子级。

我找到了答案:

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

动机

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

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

并且输出没有任何类似CCD_ 17的状态。

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

假设你有一个作者类和一个作者书籍类,并且你想在删除作者时自动删除所有书籍(通过hibernate、sql查询…),并且有一些原因你不能(总是)通过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设置-并且你必须实现一个关于如何处理会话中对象删除的策略!

最新更新