我有一个RECIPE
表与INGREDIENT
表具有OneToMany关系,因为单个配方可以有很多成分。问题是如果用户删除了一个成分(通过前端将所有字段(ingredient_id
和ingredient
)设置为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
答案 0 :(得分:1)
我通过将insertable = false, updatable = false
作为属性添加到@JoinColumn
像这样:
@JoinColumn(name="RECIPE_ID", insertable = false, updatable = false)
答案 1 :(得分:0)
关系中的孤儿删除
当从关系中删除target entity
或one-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;
添加更多
orphanRemoval
和DELETE 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
。