我想在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中的信息架构或系统目录吗?
答案 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设置 - 你必须实现一个策略来处理如何处理你的对象的删除会话!