2013-03-05 75 views
2

我有一个父母子女关系的应用程序。每个父母都有一组孩子(一对多),每个孩子都有一对父母(多对一)。 在应用我有一个服务层,并在那里我几乎做到以下几点:休眠(JPA)键'PRIMARY'的重复条目'25 -9'

public void addChild() { 
     parent = getParentFromDB(); 
     Child child = new Child(); 
     child.setParent(parent); 
     saveChild(child); 
     Set<Child> children = new HashSet<Child>(); 
     children.addAll(parent.getChildren()); 
     children.add(child); 

     parent.setChildren(children); // notice this line here. 

     saveParent(parent); 
     doStuff(parent); 
    } 

服务层从外立面,这是一个普通的Spring bean与@Transactional注释调用。当我尝试调用addChild()方法我得到以下结果:

2013-03-05 17:09:50,195 [qtp511931089-83] WARN org.hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL Error: 1062, SQLState: 23000 
2013-03-05 17:09:50,196 [qtp511931089-83] ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper - Duplicate entry '25-9' for key 'PRIMARY' 
2013-03-05 17:09:50,198 [qtp511931089-83] ERROR org.hibernate.engine.jdbc.batch.internal.BatchingBatch - HHH000315: Exception executing batch [Duplicate entry '25-9' for key 'PRIMARY'] 
2013-03-05 17:09:50.204:WARN:oejs.ServletHandler:/child/add 
javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: Duplicate entry '25-9' for key 'PRIMARY' 
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1377) 
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1300) 
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1306) 

我没有打开SQL日志中休眠,似乎休眠呼吁拯救两次!如果我删除了“//在这里注意到这一行”,那么所有行都可以正常工作 - 实体保存在数据库中,我可以在数据库中看到25-9关系。问题是,在方法结束时,我有doStuff(parent);方法,做一些事情与家长和它的孩子,所以我不能“在这里//通知这一行”删除行

编辑: 这是家长如何在孩子宣称:

@ManyToOne(fetch = FetchType.EAGER, targetEntity = ParentModel.class, cascade = { CascadeType.REMOVE }) 
@JoinTable(name = "PARENT_CHILDREN", joinColumns = @JoinColumn(name = "CHILD_ID"), inverseJoinColumns = @JoinColumn(name = "PARENT_ID")) 
private ParentModel parent; 

这是孩子们如何在父声明:

@OneToMany(fetch = FetchType.LAZY, targetEntity = ChildModel.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE }) 
@JoinTable(name = "PARENT_CHILDREN", joinColumns = @JoinColumn(name = "PARENT_ID"), inverseJoinColumns = @JoinColumn(name = "CHILD_ID")) 
private Set<ChildModel> children; 
+0

请张贴父母和子女的关系定义 – ben75 2013-03-05 15:36:47

+0

您在持续依赖实体的方式中存在配置错误。你可以发布“父”和“小孩”的映射吗? – Augusto 2013-03-05 15:37:17

回答

2

看来你只是缺少关系的mappedBy参数:

@OneToMany(mappedBy="parent", fetch = FetchType.LAZY, targetEntity = ChildModel.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE }) 
@JoinTable(name = "PARENT_CHILDREN", joinColumns = @JoinColumn(name = "PARENT_ID"), inverseJoinColumns = @JoinColumn(name = "CHILD_ID")) 
private Set<ChildModel> children; 
+0

如果我添加mappedBy参数,我在启动期间得到这个异常: 引起:org.hibernate.AnnotationException:标记为mappedBy的关联不能像\ @JoinTable或@JoinColumn:xxxx.ParentModel.children – 2013-03-06 09:29:31

+0

那样定义数据库映射,以及如何删除JoinTable? – ben75 2013-03-06 09:37:25

+1

我会接受你的答案。它实现了我所追求的,尽管它以不同的方式完成。我最终的配置是: @ManyToOne(fetch = FetchType.EAGER,targetEntity = ParentModel.class,cascade = {CascadeType.REMOVE}) @JoinColumn(name =“PARENT_ID”,nullable = true,referencedColumnName =“ PK“) private ParentModel parent; 和 @OneToMany(的mappedBy = “父”,取= FetchType.LAZY,targetEntity = ChildrenModel.class,级联= {CascadeType.REMOVE}) 私人集儿童; – 2013-03-06 10:17:13