4

我有两个对象,Parent 和 Child。Child 有一个外键返回 PARENT 表(MySQL 数据库)中的 PARENT_ID 字段。

当同时创建/组装 Parent 和 Child 对象并调用 persist 时,不会自动填充 Child PARENT_ID 外键。

示例代码:

@Entity
@Table(name = "PARENT")
public class Parent {
    @Column(name = "PARENT_ID")
    private Long parentId;

    @OneToMany(mappedBy = "parent")
    private List<Child> children;
}

@Entity
@Table(name = "CHILD")
public class Child {
    @Column(name = "CHILD_ID")
    private Long childId;

    @Column(name = "PARENT_ID")
    private Long parentId;

    @ManyToOne
    @JoinColumn(name = "parent_id")
    private Parent parent;
}

我有两个持久性样本:

1)使用休眠EntityManager:

@PersistenceContext
EntityManager em;

...

em.persist(parent);

2) 使用 Spring Data JPA JpaRepository 实例:

public interface ParentRepository extends JpaRepository<Parent, Long> {

}

在我的 ParentServiceImpl 中:

@Autowired
private ParentRepository parentRepository;

...

public Parent save(Parent parent) {
    return parentRepository.save(parent);
}

填充外键的推荐策略是什么?是否应该先保留 Parent 对象,然后再保留 Child 对象的外键?或者有没有办法通过自动或通过引用设置外键来一次持久化它?

编辑:添加了持久性示例。

编辑 2(已修复!):根据 Ryan Stewart 的第二点解决了问题。我从 Child 对象中删除了 Long parentId 字段,并将 parentId 的 @Column 引用放在 getter 上。还要确保正确设置参考(重要的是子参考回到父)。

4

1 回答 1

5

该代码有两件事阻止它工作:

  1. 您的实体没有@Id. 您可能只是因为这是一个示例而忽略了它,但值得指出。
  2. 您已经对 column 进行了双重映射parent_id。Child 具有映射到同一列的 Long 字段和 Parent 字段。摆脱龙。这是你所追求的父母关系。

之后,您将拥有一个完全传统的双向一对多连接列。如果它不适合您,那么您在创建和保存它们的代码中做错了。很可能,您没有正确创建对象。使用这些实体的正确代码如下所示:

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Parent p = new Parent();
Child child = new Child();
child.parent = p;
Child child1 = new Child();
child1.parent = p;
p.children = Arrays.asList(child, child1);
session.save(p);
session.save(p.children.get(0));
session.save(p.children.get(1));
tx.commit();

特别要注意的是,child 应该设置在 parent 中,而 parent 应该设置在 child 中。不要建立一个半损坏的对象模型并期望 Hibernate 来清理你的烂摊子。许多人忽略了这个看似显而易见的要求,并想知道为什么 Hibernate 看起来不稳定和/或不可靠。

于 2012-05-26T22:03:12.420 回答