1

也许这是一个很容易回答的问题......但我没有让它运行。在persist() 中,我得到子表中的引用键为空的异常(数据库当然不允许这样做)。我有一个食谱和一些准备步骤。

我正在使用 EclipseLink 2.4.1

Recipe.java(rcpid 由 JPA 自动设置)

@Entity
public class Recipe {
    @Id
    long rcpid;

    List<Recipestep> recipesteps = new ArrayList<>();

    @OneToMany(
        cascade=CascadeType.ALL,
        fetch=FetchType.EAGER,
        mappedBy="recipe",
        targetEntity=Recipestep.class )
// This does NOT work. Following line tries to access a join-table !!!
// @JoinColumn(name="rcpid", referencedColumnName="rcpid") 
        public List<Recipestep> getRecipesteps() { return recipesteps; }
    // some more attributes, getters and setters
}

Recipestep.java(rpsid 由 JPA 自动设置)

@Entity
public class Recipestep {
    @Id
    long rpsid;

    Recipe recipe;

    @ManyToOne( targetEntity=Recipe.class )
    @JoinColumn( name="rcpid" )
    public Recipe getRecipe() { return recipe; }

    // some more attributes, getters and setters
}

上面的代码是一个有效的解决方法。然而,为了拥有干净(且可支持)的代码,这种关系应该只是单向的,即父级中的集合引用其所有子级。

4

2 回答 2

1

您已将其映射为单向一对多,但对于 recipestep rcpid 数据库列有两个映射。尝试将长 rcpid 更改为

@ManyTOne
Recipe rcp;

然后从 oneToMany 中删除 joincolumn 定义,并通过 rcp manyToOne 关系将其标记为映射来使其成为双向的。此处发布了一个示例http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Mapping/Relationship_Mappings/Collection_Mappings/OneToMany

当首次插入目标实体时,Eclipselink 将始终使用连接列在单向 oneToMany 关系上插入空值,然后在处理配方实体时更新它。您在 Recipestep 中的 rcpid 映射也可能为空,这意味着您对同一字段有两个可写映射,这很糟糕,尤其是当它们像这样发生冲突时。

于 2013-05-13T12:05:29.947 回答
0

您正在体验默认的 JPA 行为。将实体添加到recipesteps列表中不足以创建双向关系。

要解决此问题,您需要rcpid在列表中的每个元素上显式设置。

编辑:我认为问题在于 JPA 不知道在RecipeRecipestep 表中存储 id 的位置。它假定一个名称(“recipebo_rcpid”),但您的表似乎缺少它。

尝试将“recipe_id”列添加到Recipestep表中,并将mappedBy属性添加到@OneToMany注释中:

@OneToMany(
  cascade=CascadeType.ALL,
  fetch = FetchType.EAGER,
  mappedBy = "recipe" )

您可能不需要targetEntity注释中的属性 -List已经键入。

于 2013-05-12T18:16:41.290 回答