【问题标题】:Hibernate, Delete a parent row when the foreign key constraint existsHibernate,当存在外键约束时删除父行
【发布时间】:2016-08-28 00:18:45
【问题描述】:

我有 2 个实体类别和出版物。我在这里的关系是每个出版物都有一个类别。

像这样的

create table category(
id INTEGER not null auto_increment,
name varchar(255) not null,
primary key (id)
);


CREATE TABLE PUBLICATION(
ID INTEGER NOT NULL AUTO_INCREMENT,
TITLE varchar(255) NOT NULL,
CONTENT VARCHAR(1000) NOT NULL,
CATEGORY_ID INTEGER NOT NULL,
primary key(ID),
foreign key (CATEGORY_ID) references CATEGORY (ID)
);

和实体对象

package com.java.bricks.entity;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;



    @Entity
    @Table(name="PUBLICATION")
    public class PublicationEntity implements Serializable {

        /**
         * 
         */
        private static final long serialVersionUID = 1L;

        @Id
        @Column(name="ID")
        @GeneratedValue(strategy=GenerationType.AUTO)
        private Long publicationId;

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

        @Column(name="CONTENT")
        private String content;


        @OneToOne
        @JoinColumn(name="CATEGORY_ID")
        private CategoryEntity category;


        public Long getPublicationId() {
            return publicationId;
        }
        public void setPublicationId(Long publicationId) {
            this.publicationId = publicationId;
        }
        public String getTitle() {
            return title;
        }
        public void setTitle(String title) {
            this.title = title;
        }
        public String getContent() {
            return content;
        }
        public void setContent(String content) {
            this.content = content;
        }
        public CategoryEntity getCategory() {
            return category;
        }
        public void setCategory(CategoryEntity category) {
            this.category = category;
        }



    }

和类别实体

package com.java.bricks.entity;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="CATEGORY")
public class CategoryEntity implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    @Id
    @Column(name="ID")
    @GeneratedValue(strategy=GenerationType.AUTO)
    public Long categoryId;

    @Column(name="NAME")
    public String categoryName;


    public Long getCategoryId() {
        return categoryId;
    }
    public void setCategoryId(Long categoryId) {
        this.categoryId = categoryId;
    }
    public String getCategoryName() {
        return categoryName;
    }
    public void setCategoryName(String categoryName) {
        this.categoryName = categoryName;
    }



}

现在当我删除发布记录时,发布记录被成功删除。这很好用。但是现在我想要的是,当我删除类别记录时,它应该删除类别记录(父)以及发布表中的所有外键记录。

我该怎么做?我做了 cascade.all 但我仍然得到同样的错误。

此外,当您有外键记录时,授予用户删除类别的权限是否正确?如果是的话,在这个例子中怎么做

谢谢

【问题讨论】:

  • 当您说您尝试了 cascade.all 时,您是否将其添加到类别或出版物中?
  • 我在发布中添加了级联,我在 Category 中没有发布实例,所以我没有在那里添加它。我在发布中添加了级联

标签: hibernate spring-mvc mapping


【解决方案1】:

Hibernate 通常只会查看被删除的类,而不是扫描整个实体图。如果该类中没有显式链接,则它不会做任何事情。由于 Category 没有 FK,因此您在注解中使用 mappedBy 属性,它将查找具有该名称的实例变量。当它找到实例变量时,它将能够推断出实体之间的关系。

将级联视为从该实体流向映射实体的操作。当您删除一个类别实体时,它会查看发布映射,并发现删除应该级联到该发布。

package com.java.bricks.entity;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="CATEGORY")
public class CategoryEntity implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    @Id
    @Column(name="ID")
    @GeneratedValue(strategy=GenerationType.AUTO)
    public Long categoryId;

    @Column(name="NAME")
    public String categoryName;

    @OneToOne(mappedBy="category", cascade = CascadeType.ALL)
    private Publication publication;    

    public Long getCategoryId() {
        return categoryId;
    }
    public void setCategoryId(Long categoryId) {
        this.categoryId = categoryId;
    }
    public String getCategoryName() {
        return categoryName;
    }
    public void setCategoryName(String categoryName) {
        this.categoryName = categoryName;
    }



}

【讨论】:

  • 但是通过这样做我不是将类别和出版物之间的关系设置为双向的吗?如果我按照你刚才所说的去做,那会是一个真实的陈述吗?另外,一对一映射双向或单向的推荐做法是什么?
  • 现在关系是单向的(发布到类别)。将映射添加到类别将使其成为双向的。即使我不需要立即添加映射,我也会添加它。它使实体记录关系以防我忘记。
  • 嗨@J-Bar,我做了你上面提到的,所以现在当我删除类别时,出版物也会被删除。但是现在我在删除出版物时遇到另一个问题,我收到错误 org.springframework.dao.InvalidDataAccessApiUsageException: deleted object will be re-saved by cascade (remove deleted object from associations): [com.java.bricks.entity.PublicationEntity #18];嵌套异常是 org.hibernate.ObjectDeletedException:已删除的对象将被级联重新保存(从关联中删除已删除的对象):[com.java.bricks.entity.PublicationEntity#18]
  • 完整堆栈跟踪 rg.hibernate.ObjectDeletedException:已删除的对象将被级联重新保存(从关联中删除已删除的对象):[com.java.bricks.entity.PublicationEntity#18] org.hibernate。 impl.SessionImpl.forceFlush(SessionImpl.java:1220) org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:188) org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:117) org. hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateE
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-03
  • 2015-11-15
  • 2015-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-18
相关资源
最近更新 更多