Hibernate级联保存父级和子级 - 未找到父级密钥

时间:2011-02-21 14:09:33

标签: hibernate

我正在使用Spring,Hibernate和oracle进行项目。通过运行sql脚本手动创建数据库模式。一切正常,直到遇到hibernate一对多双向级联保存的问题。

在父类(Product.java)中

@OneToMany(mappedBy="product",
        fetch=FetchType.EAGER,
        cascade={CascadeType.ALL})
public Set<Picture> getPictures() {
        return pictures;
}

@Transient
public void addPicture(Picture picture) {
    picture.setProduct(this);
    pictures.add(picture);
}

在子类(Picture.java)中

@ManyToOne(cascade={CascadeType.ALL})
@JoinColumn(name="lse09lse06id")
public Product getProduct() {
        return product;
}

“lse09lse06id”是子实体表中的外键列。

在我的Controller类中:

Product product = new Product();
.... (set properties of product)
Picture newPicture = new Picture();
.... (set properties of newPicture)
product.addPicture(newPicture);
productService.addProduct(product);

在我的ProductService类中:

@Override
@Transactional
public void addProduct(Product product) {
    productDAO.addProduct(product);
}

在我的ProductDAO课程中:

@Override
public void addProduct(Product product) {
    product.setDateCreated(new Date());
    sessionFactory.getCurrentSession().save(product);
}

执行控制器代码时抛出异常:

  

org.springframework.web.util.NestedServletException:   请求处理失败;嵌套   例外是   org.springframework.dao.DataIntegrityViolationException:   无法执行JDBC批量更新;   SQL [插入lse09pictures   (lse09content,lse09date_created,   lse09date_deleted,lse09date_updated,   lse09is_deleted,lse09lse06id,   lse09id)值(?,?,?,?,?,?,   ?)];约束   [CSSE3005GG.LSE09PICTURES_FK];嵌套   例外是   org.hibernate.exception.ConstraintViolationException:   无法执行JDBC批量更新

抛出一个嵌套异常:

  

java.sql.BatchUpdateException:   ORA-02291:完整性约束   (CSSE3005GG.LSE09PICTURES_FK)违反了    - 未找到父密钥

非常感谢任何帮助。这个问题真的很讨厌。谢谢!

2 个答案:

答案 0 :(得分:0)

cascade移除@ManyToOne(cascade={CascadeType.ALL})。 Hibernate被循环引用搞糊涂了。

或者,在Product实例之前保存Picture实例(通过在其上显式调用session.save())。

答案 1 :(得分:0)

使用Hibernate Cascade类

  • org.hibernate.annotations.Cascade
  • org.hibernate.annotations.CascadeType

您可以尝试像这样重写它吗?

@OneToMany(fetch=FetchType.EAGER,
@Cascade(value = { CascadeType.SAVE_UPDATE, CascadeType.PERSIST,
     CascadeType.MERGE })
public Set<Picture> getPictures() {
    return pictures;
}

还有

@ManyToOne
@Cascade(value = { CascadeType.SAVE_UPDATE, CascadeType.PERSIST,
     CascadeType.MERGE })
@JoinColumn(name="lse09lse06id")
public Product getProduct() {
    return product;
}

在那之后,调用Hibernate.saveOrUpdate应该做你想要的。

Cyber​​ax是正确的,循环引用可能会使Hibernate感到困惑。另外,应谨慎使用级联删除-这就是为什么我只使用了Save,Persist和Merge。