Java 休眠链接到对象中的下一个和/或上一个

Java 休眠链接到对象中的下一个和/或上一个,java,hibernate,orm,hibernate-mapping,Java,Hibernate,Orm,Hibernate Mapping,我遇到了以下情况,我没有成功地为其编写正确的hibernate注释 形势 让我们假设一个企业主有两个商店。在这些商店里,他出售商品。现在,当用户进入商店时,他们希望按照外观顺序对其购物列表(非重要类)上的物品进行排序。业务负责人对每家商店的每篇文章都有一个概述,并带有指向上一篇文章和下一篇文章的链接。使用此列表,我们可以轻松地“计算”订单。因此,对于一家商店来说,这实际上不是一个问题。问题是第二家商店什么时候进来 守则: 我删除了一些lombok注释和其他样板代码,以使示例尽可能清晰 @实体 @

我遇到了以下情况,我没有成功地为其编写正确的hibernate注释

形势 让我们假设一个企业主有两个商店。在这些商店里,他出售商品。现在,当用户进入商店时,他们希望按照外观顺序对其购物列表(非重要类)上的物品进行排序。业务负责人对每家商店的每篇文章都有一个概述,并带有指向上一篇文章和下一篇文章的链接。使用此列表,我们可以轻松地“计算”订单。因此,对于一家商店来说,这实际上不是一个问题。问题是第二家商店什么时候进来

守则: 我删除了一些lombok注释和其他样板代码,以使示例尽可能清晰

@实体
@表(名称=存储)
公共最终类存储序列{
@嵌入ID
@AttributeOverride(name=“value”,column=@column(name=STORE\u NUMBER))
私人店号店号;
@OneToMany(cascade=CascadeType.ALL,orphan=true)
@JoinColumn(name=STORE\u NUMBER,referencedColumnName=STORE\u NUMBER,nullable=false)
私人物品;
}
@实体
@表(名称=文章)
班级文章{
//请注意,前面没有添加STORENUMBER,因为只有一个STORE。
@嵌入ID
@列(名称=文章编号)
私人物品编号id;
@OneToOne(级联=级联类型.ALL)
@JoinColumn(名称=上一篇文章\u ID,引用ColumnName=文章\u ID)
@塞特//移动物体
私人物品;
@OneToOne(级联=级联类型.ALL)
@JoinColumn(name=NEXT\u ARTICLE\u ID,referencedColumnName=ARTICLE\u ID)
@塞特//移动物体
下一篇私人文章;
}
这很有效。。。但是,如果我现在“启动”第二个商店(B)(当然它与商店(A)有一些相同的articleId,但顺序不同),例如,如果商店B的列表中有相同的id,我就无法在其中创建一个物品(UniqueConstraintViolationException)

因此,我可能还必须将storenumber添加到Article类中(从那时起,一篇文章可以知道它位于哪个位置的哪个商店……这是有意义的)但是……

问题 如果我将storenumber作为id的一部分包含在文章类中,那么如何在next和previous字段上进行映射,因为他们现在还需要在PK中包含storenumber,而无需在next_storenumber和previous_storenumber中添加db列(将有相同的storenumber->business rule)并保持字段的可更新性。 可更新性很重要:我可以在商店里移动一些东西。 我通过使用以下命令成功读取了添加的字段:

@JoinColumns({
@JoinColumn(name=上一篇文章,referencedColumnName=下一篇文章,insertable=false,updateable=false),
@JoinColumn(name=STORE\u NUMBER,referencedColumnName=STORE\u NUMBER,insertable=false,updateable=false),
})
但是当省略insertable=false和updateable=false时,我会得到一个启动异常,说明我引用了STORE_NUMBER表,并告诉我只允许insertable和updateable false

编辑: 一种选择是将“门店号”列复制到下一个门店号和上一个门店号列,然后我可以将一篇文章放在另一家门店的文章旁边

指向实际阅读所有这些内容的人

找到解决方案的人将获得额外积分

游戏/设置/匹配提出解决方案的人,该解决方案无需在文章类中添加商店编号!只是出于好奇,想知道如果可能的话

分析问题后,我们看到了两种选择:

  • 添加代理/人工密钥(自动生成)并通过此号码存储链接。由于我们数据库的性质,它会导致列中包含文章编号,列中包含指向下一篇文章编号的编号等。从维护/db的角度来看,这并不理想
  • 添加2个附加列以存储下一个\u存储\u id和上一个\u存储\u id以正确链接字段。但是,我可以将一篇文章放在另一个商店的文章旁边,并且我还有一个带有copy-in-date的附加列(将对它们设置相同或空的约束)
纯属运气,我偶然发现了第三种解决方案: 只需为nextId和previousId添加一个额外的@Column注释字段。实际上是一个干净的“黑客”

@实体
@表(名称=存储)
公共最终类存储序列{
@嵌入ID
@列(名称=门店号)
私人长仓号;
@OneToMany(cascade=CascadeType.ALL,orphan=true)
@JoinColumn(name=STORE\u NUMBER,referencedColumnName=STORE\u NUMBER,nullable=false,insertable=false,updateable=false)
私人物品;
}
@实体
@表(名称=文章)
班级文章{
@嵌入ID
private ArticleInStore id;//包含存储和项目\u id
@OneToOne(级联=级联类型.ALL)
@连接柱({
@JoinColumn(name=PREVIOUS\u ARTICLE\u ID,referencedColumnName=ARTICLE\u ID,insertable=false,updateable=false),
@JoinColumn(name=STORE\u ID,referencedColumnName=STORE\u ID,insertable=false,updateable=false)
})
//请注意,SETTER现在是自定义的
//无法使其可写,因为我们需要上一个\u STORE\u ID列。
私人物品;
@OneToOne(级联=级联类型.ALL)
@连接柱({
@JoinColumn(name=NEXT\u ARTICLE\u ID,referencedColumnName=ARTICLE\u ID,insertable=false,updateable=false),
@JoinColumn(name=STORE\u ID,referencedColumnName=STORE\u ID,insertable=false,updateable=false)
})
@JoinColumn(name=NEXT\u ARTICLE\u ID,referencedColumnName=ARTICLE\u ID)
//请注意,SETTER现在是自定义的
//做不到