JPA多对多引用问题

发布于 2024-08-29 09:39:09 字数 1915 浏览 6 评论 0原文

我有三张桌子。 AvailOptions 和 PlanTypeRef 具有名为 AvailOptionPlanTypeAssoc 的 ManyToMany 关联表。精简后的架构如下所示

CREATE TABLE [dbo].[AvailableOptions](
  [SourceApplication] [char](8) NOT NULL,
  [OptionId] [int] IDENTITY(1,1) NOT NULL,
  ...
)

CREATE TABLE [dbo].[AvailOptionPlanTypeAssoc](
  [SourceApplication] [char](8) NOT NULL,
  [OptionId] [int] NOT NULL,
  [PlanTypeCd] [char](2) NOT NULL,
)

CREATE TABLE [dbo].[PlanTypeRef](
  [PlanTypeCd] [char](2) NOT NULL,
  [PlanTypeDesc] [varchar](32) NOT NULL,
)

,Java 代码如下所示。

//AvailableOption.java
@ManyToMany(cascade={CascadeType.ALL}, fetch=FetchType.EAGER)
@JoinTable(
  name = "AvailOptionPlanTypeAssoc",
  joinColumns = { @JoinColumn(name = "OptionId"),
                  @JoinColumn(name="SourceApplication")},
  inverseJoinColumns=@JoinColumn(name="PlanTypeCd"))
List<PlanType> planTypes = new ArrayList<PlanType>();

//PlanType.java
@ManyToMany
@JoinTable(
  name = "AvailOptionPlanTypeAssoc",
  joinColumns = { @JoinColumn(name = "PlanTypeCd")},
  inverseJoinColumns={@JoinColumn(name="OptionId"),
                      @JoinColumn(name="SourceApplication")})
List<AvailableOption> options = new ArrayList<AvailableOption>();

当对可用选项进行选择并将其重新连接到自身时,就会出现问题。请注意回溯中的以下 SQL 代码。第二个内部联接应该位于 PlanTypeRef 上。

SELECT t0.OptionId, 
  t0.SourceApplication, 
  t2.PlanTypeCd, 
  t2.EffectiveDate, 
  t2.PlanTypeDesc, 
  t2.SysLstTrxDtm, 
  t2.SysLstUpdtUserId, 
  t2.TermDate 
FROM dbo.AvailableOptions t0 
  INNER JOIN dbo.AvailOptionPlanTypeAssoc t1 
    ON t0.OptionId = t1.OptionId AND t0.SourceApplication = t1.SourceApplication 
  INNER JOIN dbo.AvailableOptions t2 
    ON t1.PlanTypeCd = t2.PlanTypeCd 
WHERE (t0.SourceApplication = ? AND t0.OptionType = ?) 
ORDER BY t0.OptionId ASC, t0.SourceApplication ASC 
[params=(String) testApp, (String) junit0]}

I have three tables. AvailableOptions and PlanTypeRef with a ManyToMany association table called AvailOptionPlanTypeAssoc. The trimmed down schemas look like this

CREATE TABLE [dbo].[AvailableOptions](
  [SourceApplication] [char](8) NOT NULL,
  [OptionId] [int] IDENTITY(1,1) NOT NULL,
  ...
)

CREATE TABLE [dbo].[AvailOptionPlanTypeAssoc](
  [SourceApplication] [char](8) NOT NULL,
  [OptionId] [int] NOT NULL,
  [PlanTypeCd] [char](2) NOT NULL,
)

CREATE TABLE [dbo].[PlanTypeRef](
  [PlanTypeCd] [char](2) NOT NULL,
  [PlanTypeDesc] [varchar](32) NOT NULL,
)

And the Java code looks like this.

//AvailableOption.java
@ManyToMany(cascade={CascadeType.ALL}, fetch=FetchType.EAGER)
@JoinTable(
  name = "AvailOptionPlanTypeAssoc",
  joinColumns = { @JoinColumn(name = "OptionId"),
                  @JoinColumn(name="SourceApplication")},
  inverseJoinColumns=@JoinColumn(name="PlanTypeCd"))
List<PlanType> planTypes = new ArrayList<PlanType>();

//PlanType.java
@ManyToMany
@JoinTable(
  name = "AvailOptionPlanTypeAssoc",
  joinColumns = { @JoinColumn(name = "PlanTypeCd")},
  inverseJoinColumns={@JoinColumn(name="OptionId"),
                      @JoinColumn(name="SourceApplication")})
List<AvailableOption> options = new ArrayList<AvailableOption>();

The problem arises when making a select on AvailableOptions it joins back onto itself. Note the following SQL code from the backtrace. The second inner join should be on PlanTypeRef.

SELECT t0.OptionId, 
  t0.SourceApplication, 
  t2.PlanTypeCd, 
  t2.EffectiveDate, 
  t2.PlanTypeDesc, 
  t2.SysLstTrxDtm, 
  t2.SysLstUpdtUserId, 
  t2.TermDate 
FROM dbo.AvailableOptions t0 
  INNER JOIN dbo.AvailOptionPlanTypeAssoc t1 
    ON t0.OptionId = t1.OptionId AND t0.SourceApplication = t1.SourceApplication 
  INNER JOIN dbo.AvailableOptions t2 
    ON t1.PlanTypeCd = t2.PlanTypeCd 
WHERE (t0.SourceApplication = ? AND t0.OptionType = ?) 
ORDER BY t0.OptionId ASC, t0.SourceApplication ASC 
[params=(String) testApp, (String) junit0]}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

眼波传意 2024-09-05 09:39:09

您正在映射双向关联。这意味着您必须选择一方作为协会的所有者。这一方将负责更新数据库中的关系。

如果您选择AvailableOption 作为关系的所有者并且想要为其指定一个新的计划类型,则必须将计划类型添加到该选项。仅将该选项添加到计划类型中不会产生任何效果。

这是映射:

//AvailableOption.java
@ManyToMany(cascade={CascadeType.ALL}, fetch=FetchType.EAGER)
@JoinTable(
  name = "AvailOptionPlanTypeAssoc",
  joinColumns = { @JoinColumn(name = "OptionId"),
                  @JoinColumn(name="SourceApplication")},
  inverseJoinColumns=@JoinColumn(name="PlanTypeCd"))
List<PlanType> planTypes = new ArrayList<PlanType>();

//PlanType.java
@ManyToMany(
    mappedBy = "planTypes"
)
List<AvailableOption> options = new ArrayList<AvailableOption>();

您还可以参考 hibernate注释文档第2.2.5章

问候
大卫

You are mapping a bidirectional association. That means you have to choose one side as the owner of the association. This side will be responsible for updating the relationship in the database.

If you choose AvailableOption as the owner of the relationship and you want a new PlanType for it, you have to add the plantype to the option. Adding the option only to the plantype will have no effect.

Here is the Mapping:

//AvailableOption.java
@ManyToMany(cascade={CascadeType.ALL}, fetch=FetchType.EAGER)
@JoinTable(
  name = "AvailOptionPlanTypeAssoc",
  joinColumns = { @JoinColumn(name = "OptionId"),
                  @JoinColumn(name="SourceApplication")},
  inverseJoinColumns=@JoinColumn(name="PlanTypeCd"))
List<PlanType> planTypes = new ArrayList<PlanType>();

//PlanType.java
@ManyToMany(
    mappedBy = "planTypes"
)
List<AvailableOption> options = new ArrayList<AvailableOption>();

You may also refer to the hibernate annotation documentation chapter 2.2.5

Regards
David

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文