使用 JoinTable 的 JPA 自联接
Posted
技术标签:
【中文标题】使用 JoinTable 的 JPA 自联接【英文标题】:JPA Self Join using JoinTable 【发布时间】:2013-02-19 09:54:05 【问题描述】:我有 1 个实体调用 Item 我希望能够将父项链接到子项。使用连接表来创建父/子关系。我无法获得任何好的文档。因此,如果有人有任何想法,我会全力以赴。
这就是我所拥有的......大部分时间都有效。
public class Item implements java.io.Serializable
@Id
private Long id;
@ManyToOne(optional = true, fetch = FetchType.LAZY)
@JoinTable(name = "ITEMTOITEM", joinColumns = @JoinColumn(name = "ITEMID") , inverseJoinColumns = @JoinColumn(name = "PARENTITEMID") )
private Item parent;
@OneToMany(mappedBy = "parent", fetch = FetchType.LAZY)
private List<Item> children;
有时,当我想恢复与此项目表相关联的对象时,我会收到以下错误:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.webflow.engine.ActionExecutionException: Exception thrown executing [AnnotatedAction@6669ff5 targetAction = com.assisted.movein.web.common.nav.NavAction@6edf74b7, attributes = map['method' -> 'handleEntry']] in state 'oneTimeChargesAndFeesView' of flow 'in-flow' -- action execution attributes were 'map['method' -> 'handleEntry']'; nested exception is Exception [TOPLINK-4002] (Oracle TopLink Essentials - 2.0.1 (Build b04-fcs (04/11/2008))): oracle.toplink.essentials.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: ORA-00904: "PARENTITEM_ITEMID": invalid identifier
Error Code: 904
Call: SELECT ITEMID, ITEMSHORTDESC, EFFENDDATE, ITEMDESC, PARENTITEM_ITEMID, ITEMTYPECODE FROM ITEM WHERE (ITEMID = ?)
bind => [1250]
Query: ReadObjectQuery(com.domain.Item)
任何帮助将不胜感激。
【问题讨论】:
这里我整理了表格图here。 最后一点需要注意的是,我需要它来使用 eclipselink 和 toplink-essentials。所以我仅限于使用 JPA 1.0 映射。 【参考方案1】:尝试改用@JoinColumn
:
@ManyToOne(optional = true, fetch = FetchType.LAZY)
@JoinColumn(name = "PARENTITEMID", referencedColumnName = "ITEMID")
private Item parent;
@OneToMany(
cascade = CascadeType.ALL,
orphanRemoval = true,
fetch = FetchType.LAZY
)
@JoinColumn(name = "PARENTITEMID")
private List<Item> children;
【讨论】:
我正在寻找在父实体和子实体之间使用联接表。我相信您的映射只允许对自身进行一次映射。 这是没有附加表的映射。每个孩子都有到父母的链接。【参考方案2】:在大量阅读 JPA 2.0 之后,我发现我需要更新版本的 Eclipselink 2.3+ 来支持我正在尝试做的事情。这是在我的案例中实际工作的代码,但由于我们依赖于旧版本 [EclipseLink 2.0.2],它不会工作。另一个项目仍在使用 Toplink-essentials JPA 1.0,它再次喜欢这种表示法。
public class Item
@ManyToOne(optional = true, fetch = FetchType.LAZY)
@JoinTable(name = "ITEMINCENTIVESMAPPING",
joinColumns = @JoinColumn(name = "INCENTIVEITEMID", referencedColumnName = "ITEMID", insertable = false, updatable = false) ,
inverseJoinColumns = @JoinColumn(name = "ITEMID", referencedColumnName = "ITEMID", insertable = false, updatable = false) )
private Item parentItem;
@OneToMany(fetch = FetchType.LAZY)
@JoinTable(name = "ITEMINCENTIVESMAPPING",
joinColumns = @JoinColumn(name = "INCENTIVEITEMID", referencedColumnName = "ITEMID") ,
inverseJoinColumns = @JoinColumn(name = "ITEMID", referencedColumnName = "ITEMID") )
private List<Item> items;
【讨论】:
对我来说,看起来您已经映射了两个独立的关系:单向多对一和单向一对多。为什么不映射一个单一的双向关系?这是为自引用多对多关系提出的解决方案(使用了双向映射):drag0sd0g.blogspot.com/2010/03/… 如何在这种类型的模型上进行自定义 CRUD 操作?例如通过 parentItem() 获取。任何帮助表示赞赏。谢谢!!!【参考方案3】:我相信@JoinTable 只允许在@OneToOne 或@OneToMany 或@ManyToMany 上使用,我认为在@ManyToOne 上没有任何意义。使用@JoinColumn 或@OneToOne。
你的@OneToMany 也没有意义,mappedBy 必须是一个属性并且你没有 parentItem,它应该是 parent,并且 parent 应该使用 @JoinColumn。
【讨论】:
James,感谢您的提醒,mappedBy 是一个 CAP 错误。我在原版中修复了它。以上是关于使用 JoinTable 的 JPA 自联接的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot JPA:在自联接关系中的 JSON 视图上递归