使用onetomany连接更新实体,而不在子实体中使用id

时间:2014-08-04 12:38:49

标签: java spring hibernate jpa

我有以下结构:表格“parent”和“children”,由parents.id = children.parent_id

绑定。

应用程序将这些表中的数据读入以下类的对象:

public class Parent {
    private int id;
    private Map<String, String> children;
    ....
}

然后应用程序更改其中的数据。 我需要做的是对现有记录应用更改。我不允许更改父类或数据库结构。我试图通过以下方式使用jpa存储库来做到这一点:

我的实体

@Repository
public interface ParentsDao extends JpaRepository<ParentEntity, Integer> {
}

@Entity
@Table(name = "parents")
public class ParentEntity {
    @Id
    @GeneratedValue
    @Column(name = "id", updatable = false, insertable = false)
    private Integer id;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
    @JoinColumn(name="parent_id")
    private Set<ChildEntity> children;
    ...
}

@Entity
@Table(name = "children")
public class ChildEntity {
    @Id
    @GeneratedValue
    @Column(name = "id", updatable = false, insertable = false)
    private Integer id;

    @ManyToOne
    @JoinColumn(name="parent_id", updatable = false)
    private ScheduledReportsEntity scheduledReport;

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

    @Column(name = "child_value")
    private String value;
    ...
}

以下是我的服务,其中action()启动整个事情:将Parent转换为ParentEntity并保存它

public class ParentServiceImpl {
        @Autowired
        ParentsDao parentsDao;

        public 

void action(Parent parent) {
            ParentEntity entity = convert(parent);  // moving data from Parent to ParentEntity object
            parentsDao.save(entity); //here I receive exception
        }
        private ParentEntity convert(Parent parent) {

        Set<ChildEntity> children = new HashSet<ChildEntity>();
        for(Map.Entry<String, String> entry : simpleObj.getChildren().entrySet()){
            ChildEntity childEntity = new ChildEntity();
            childEntity.setName(entry.getKey());
            childEntity.setValue(entry.getValue());
            children.add(entity);
        }

        ParentEntity entity = new ParentEntity();
        entity.setId(parent.getId());
        entity.setChildren(children);

        return entity;
    }
}

但我收到以下错误:

com.app.impl.ParentServiceImpl: org.springframework.dao.DataIntegrityViolationException: 
could not insert: [com.app.entities.ChildEntity]; 
SQL [insert into scheduled_report_params (child_name, child_value, parent_id) values (?, ?, ?)]; 
constraint [null]; 
nested exception is org.hibernate.exception.ConstraintViolationException: could not insert: [com.app.entities.ChildEntity]

我有两个问题: 我认为这与儿童缺失的ids有关,对吗? 2.如果原因是缺少ids,那么有什么方法可以以某种方式解决它并提供其他领域的保存? 任何建议都会很棒。 感谢

1 个答案:

答案 0 :(得分:1)

您遇到了设计问题。

你是对的,如果id是子实体的主键,那么它必须存在于来自子集的所有预先存在的(不是新的)ChildEntity元素中{{1} }元素,如果你修改它。如果没有,Hibernate将尝试插入它们。

所以你必须在两种解决方案中做出选择:

  • ParentEntity中使用生成的主键,并找到将其保留在应用程序中的方法。例如,您可以使用ChildEntity作为真实的模型类,其中ParentEntity视图

    Parent
  • 使用子名作为主键。 class Parent { private ParentEntity inner; public Parent(ParentEntity entity) { inner = entity; // initialize children or have getChildren to dynamically create it // from inner.childre ... } ... } 看起来像是:

    ChildEntity

但是你不能简单地忘记应用程序中的主键。