我有RECEIPE表,CUISINE_ID是CUISINE.ID表的外键。插入新的RECIPE时可以插入,只插入CUISINE_ID,CUISINE表中没有新行。
表格结构
create table CUISINE(cuisine_id number primary key, name varchar2(20));
create table RECIPE(id number primary key,
name varchar2(25) not null,
cuisine_id number,
constraint cuisine_fk foreign key (cuisine_id) references
cuisine(cuisine_id));
类映射:
@Entity
@Table(name = "cuisine")
public class Cuisine {
@Id
@Column(name = "cuisine_id")
private int id;
@Column(name = "name")
@NotBlank(message = "You can not leave this empty.")
@NotNull(message = "You can not leave this empty.")
private String name;
@Entity
@Table(name = "recipe")
public class Recipe {
@Id
@Column(name = "id")
private int id;
@Column(name = "name")
private String name;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "cuisine_id")
private Cuisine cuisine;
一旦我从JSP页面填充了RECEIPE类,我就会从modelAttribute中得到以下内容
Recipe [id=0, name=Burger, cuisine=Cuisine [id=0, name=American]
DAO代码
public void addRecipe(Recipe recipe) {
String hql = "select max(id) from Recipe";
Integer id = ((Integer) getSession().createQuery(hql).uniqueResult()) + 1;
recipe.setId(id);
getSession().save(recipe);
}
从日志中我可以看到以下内容已插入:
Hibernate: insert into cuisine (name, cuisine_id) values (?, ?)
Hibernate: insert into recipe (cuisine_id, name, id) values (?, ?, ?)
我的要求是没有在烹饪表中插入新行,因为recipe.cusinie_id应该只存储id。
提前致谢,
答案 0 :(得分:0)
传递给DAO的Recipe对象可能包含对Cuisine对象的引用。我假设当时两个对象都与会话无关。
您对烹饪的引用的注释包含@OneToOne(cascade = CascadeType.ALL)
,告诉Hibernate还保存参考烹饪对象。这会产生insert into cuisine
声明。
您应该删除级联注释,因为它还会导致在删除食谱时删除菜肴。
另一个解决方案是从DB加载Cuisine对象,并在保存之前在Recipe中引用它。 (但那个犯规仍然会让你删除级联)
答案 1 :(得分:0)
对于您的DAO方法,您只是传递Recipe
对象的新实例,并且此对象具有您问题中提到的参数:
Recipe [id=0, name=Burger, cuisine=Cuisine [id=0, name=American]
现在在DAO方法中,您从数据库获取最大ID并使用新的id值更新Recipe
实例,因此配方实例的属性将变为这样(假设数据库中的max(id))是100):
Recipe [id=101, name=Burger, cuisine=Cuisine [id=0, name=American]
您的CASCADE TYPE
实体和ALL
实体之间的Recipe
设置为Cuisine
,因此当您尝试使用以下行保存recipe
实例时:
getSession().save(recipe);
hibernate会做什么,它会尝试命中数据库以获取cuisine
id
的实例为0
,因为recipe
的实例为cuisine
1}} id
是0
。
select cuisine_.cuisine_id, cuisine_.name as name2_0_
from cuisine cuisine_
where
cuisine_.cuisine_id=0
如果cuisine
表的数据库中没有id
作为0
的记录,则hibernate假定您正在尝试在数据库中保存cuisine
的新记录,因此它还会为insert
生成cuisine
个查询。
要避免在insert
表上进行此cuisine
查询,请确保您之前分配了分配给id
对象的正确cuisine
到recipe
实例调用你的DAO方法。
答案 2 :(得分:-1)
由于您是@OneToOne(cascade = CascadeType.ALL)
,我们的代码告诉您必须首先保存引用,然后保存实际的表值。
我在这里看到你一次性保存整个交易。
DAO实现中的这段代码可能会有所帮助。
public void addRecipe(Recipe recipe) {
String hql = "select max(id) from Recipe";
getSession().beginTransaction();
Integer id = ((Integer) getSession().createQuery(hql).uniqueResult()) + 1;
recipe.setId(id);
getSession().save(recipe.getCuisine);
getSession().save(recipe);
getSession().getTransaction().commmit();
}