Hibernate不删除外键行(而是将其设置为NULL)

时间:2014-12-05 04:57:41

标签: java spring hibernate

我有一个RECIPE表与INGREDIENT表具有OneToMany关系,因为单个配方可以有很多成分。问题是如果用户删除了一个成分(通过前端将所有字段(ingredient_idingredient)设置为NULL,则删除包含两个表RECIPE_INGREDIENT的关系的行但Ingredient表中的行仍然存在。我们不能告诉Hibernate还删除那些行吗?

Oracle表格

create table recipe(id number primary key,
                    name varchar2(25) unique);

create table ingredient(ingredient_id number(4) primary key,
                    ingredient varchar2(40));

create table recipe_ingredient(recipe_id number(4),
                           ingredient_id number(4),
                           constraint recipe_fk foreign key(recipe_id)
                           references recipe(recipe_id),
                           constraint ingredient_fk foreign
                           key(ingredient_id) references
                           ingredient(ingredient_id));

成分和配方POJO

@Entity
@Table(name = "ingredient", uniqueConstraints={
        @UniqueConstraint(columnNames="INGREDIENT_ID")
})
public class Ingredient implements Serializable {   
    @Id
    @Column(name = "INGREDIENT_ID", unique=true, nullable=false)
    @SequenceGenerator(name="seq_ingredient", sequenceName="seq_ingredient")
    @GeneratedValue(strategy=GenerationType.AUTO, generator="seq_ingredient")
    private Integer ingredientId;

    @Column(name = "INGREDIENT")
    private String ingredient;

    /*@ManyToOne(fetch=FetchType.EAGER)
    @JoinColumn(name="RECIPE_ID")
    private Recipe recipe;*/

    //getter and setters



@Entity
@Table(name = "recipe")
public class Recipe implements Serializable {    
    @Id
    @Column(name = "id")
    private Integer id;

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

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
    @JoinTable(name = "recipe_ingredient", joinColumns = { @JoinColumn(name = "recipe_id") }, inverseJoinColumns = { @JoinColumn(name = "ingredient_id") })
    private List<Ingredient> ingredients;

//getters and setter
}

DAO代码

public class RecipeDaoImpl implements RecipeDao {
    public void addRecipe(Recipe recipe) {
        getSession().saveOrUpdate(recipe);
    }
}

日志显示INGREDIENT表中的行仍然存在,而Hibernate只是从'RECIPE_INGREDIENT'表中删除行。

请注意以下ingredient_id已删除null。在这两种情况下,它都将ingredient.recipe_id更新为NULL。

Received following from frontend:
RecipeController - Recipe[recipeId=126,name=Sandwich,ingredients=[Ingredient[ingredientId=270,ingredient=Salt],[ingredientId=<null>,quantity=<null>]]]

Hibernate: update RECIPE set NAME=? where RECIPE_ID=?
Hibernate: update ingredient set INGREDIENT=? where INGREDIENT_ID=?
Hibernate: delete from recipe_ingredient where recipe_id=?
Hibernate: insert into recipe_ingredient (recipe_id, ingredient_id) values (?, ?)

所以数据库表有,

INDREDIENT
INGREDIENT_ID   INGREDIENT
271             Salt    
272             Sugar

RECIPE_INDGREDIENT
RECIPE_ID   INDREDIENT_ID
126         271

2 个答案:

答案 0 :(得分:1)

我通过将insertable = false, updatable = false作为属性添加到@JoinColumn

来解决了这个问题

像这样:

@JoinColumn(name="RECIPE_ID", insertable = false, updatable = false)

答案 1 :(得分:0)

关系中的孤儿删除

当从关系中删除target entityone-to-one关系中的one-to-many时,通常需要cascade the remove operation到目标实体。此类目标实体被视为“孤儿”,orphanRemoval attribute可用于指定应删除孤立实体。

例如,如果RECIPE有多个INGREDIENT且其中一个已从list中移除,则已移除的INGREDIENT将被视为孤儿。如果orphanRemoval is set to true,则从INGREDIENT移除list时,系统商品实体将被删除。

orphanRemoval中的@OneToMany and @oneToOne属性需要Boolean value,默认为false。

以下示例将删除操作从孤立关系中删除后,将删除操作级联到孤立的INGREDIENT实体:

@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER, orphanRemoval="true")
@JoinColumn(name="RECIPE_ID")
private List<Ingredient> ingredients;

添加更多

orphanRemovalDELETE CASCADE.

orphanRemoval 是一个完全由ORM特定的东西。它是marks "child" entity to be removed when it's no longer referenced from the "parent" entity,例如当您从父实体的相应集合中删除子实体时。

ON DELETE CASCADE 是特定于数据库的事情,deletes the "child" row in the database when the "parent" row is deleted