Java EE 6 JPA 2 ManyToOne 关系创建无效的外键

发布于 2024-10-08 03:25:08 字数 3757 浏览 0 评论 0原文

我正在尝试创建两个实体,其中两个实体都有嵌入的 ID。其中一个实体有 2 个对另一个实体的引用,其中这两个引用都作为 ManyToOne 相关。

下面写了示例代码;

@Embeddable
public class ItemPK {
  @Column(nullable = false, length = 100)
  private String itemId;
  @Column(name = "item_client_id", nullable = false)
  private int clientId; 
  ...
}

@Entity
@Table(name = "item")
public class Item {
  @EmbeddedId
  private ItemPK id;

  @ManyToOne
  @JoinColumn(name = "item_client_id")
  private Client client;

  @OneToMany(mappedBy="item", cascade = CascadeType.ALL, orphanRemoval = true)
  private Set<RelatedItem> relatedItems;

  @OneToMany(mappedBy="relatedItem", cascade = CascadeType.ALL, orphanRemoval = true)
  private Set<RelatedItem> relatedItemsRHS;
  ...
}

@Embeddable
public class RelatedItemPK {
  @Column(name = "itemId", length = 100, nullable = false)
  private String itemId;
  @Column(name = "item_client_id", nullable = false)
  private int clientId;
  @Column(name = "relatedItemId", length = 100, nullable = false)
  private String relatedItemId;
  @Column(name = "related_item_client_id", nullable = false)
  private int relatedItemClientId;
  ...
}

@Entity
@Table(name = "related_item")
public class RelatedItem {
  @EmbeddedId
  private RelatedItemPK id;

  @ManyToOne(cascade = CascadeType.ALL, optional = false)
  @JoinColumns({
    @JoinColumn(name="itemId", referencedColumnName="itemId", insertable=false, updatable=false),
    @JoinColumn(name="item_client_id", referencedColumnName="item_client_id", insertable=false, updatable=false)
  })
  private Item item;
  @ManyToOne(cascade = CascadeType.ALL, optional = false)
  @JoinColumns({
    @JoinColumn(name="related_item_client_id", referencedColumnName="item_client_id", insertable=false, updatable=false),
    @JoinColumn(name="relatedItemId", referencedColumnName="itemId", insertable=false, updatable=false)
  })
  private Item relatedItem;
  ...
}

问题是在为相关项实体创建外键时,我收到了 SQLException。这是第二个失败的多对一关系。外键生成sql如下,

ALTER TABLE related_item ADD CONSTRAINT FK_related_item_related_item_client_id FOREIGN KEY (related_item_client_id, relatedItemId) REFERENCES item (item_client_id, itemId)

由于item表首先由itemId索引,然后由item_client_id索引,因此该语句会导致MySQL产生错误。

我想切换列的位置,以便 SQL 应如下所示,

ALTER TABLE related_item ADD CONSTRAINT FK_related_item_relatedItemId FOREIGN KEY (relatedItemId, related_item_client_id) REFERENCES item (itemId,item_client_id)

我尝试更改“JoinColumn”的顺序,但结果没有改变。我还尝试重命名字段以检查持久性提供程序是否按列名称选择顺序,但结果再次没有改变。

那么,有没有办法强制执行列排序呢?

ps 我使用以下内容:

  • MySQL 5.1
  • EclipseLink 2.0.0
  • Java EE 6
  • JPA 2
  • GlassFish v3

编辑:EclipseLink 生成以下 SQL,但无法运行;

CREATE TABLE related_item (SIMILARITY DOUBLE, widget_id INTEGER NOT NULL, relatedItemId VARCHAR(100) NOT NULL, itemId VARCHAR(100) NOT NULL, related_item_client_id INTEGER NOT NULL, item_client_id INTEGER NOT NULL, PRIMARY KEY (widget_id, relatedItemId, itemId, related_item_client_id, item_client_id));
CREATE TABLE item (IMAGEURL VARCHAR(2048), STATUS VARCHAR(64), URL VARCHAR(2048), PRICE DOUBLE, STOCK INTEGER, DESCRIPTION TEXT(64000), NAME VARCHAR(255), ITEMID VARCHAR(100) NOT NULL, item_client_id INTEGER NOT NULL, PRIMARY KEY (ITEMID, item_client_id));
ALTER TABLE related_item ADD CONSTRAINT FK_related_item_itemId FOREIGN KEY (itemId, item_client_id) REFERENCES item (itemId, item_client_id);
ALTER TABLE related_item ADD CONSTRAINT FK_related_item_related_item_client_id FOREIGN KEY (related_item_client_id, relatedItemId) REFERENCES item (item_client_id, itemId);
ALTER TABLE item ADD CONSTRAINT FK_item_item_client_id FOREIGN KEY (item_client_id) REFERENCES client (ID);

I am trying to create two entities where both entities have embeddedIds. One of the entities have 2 references to the other entity, where both of those references are related as ManyToOne.

Example codes are written below;

@Embeddable
public class ItemPK {
  @Column(nullable = false, length = 100)
  private String itemId;
  @Column(name = "item_client_id", nullable = false)
  private int clientId; 
  ...
}

@Entity
@Table(name = "item")
public class Item {
  @EmbeddedId
  private ItemPK id;

  @ManyToOne
  @JoinColumn(name = "item_client_id")
  private Client client;

  @OneToMany(mappedBy="item", cascade = CascadeType.ALL, orphanRemoval = true)
  private Set<RelatedItem> relatedItems;

  @OneToMany(mappedBy="relatedItem", cascade = CascadeType.ALL, orphanRemoval = true)
  private Set<RelatedItem> relatedItemsRHS;
  ...
}

@Embeddable
public class RelatedItemPK {
  @Column(name = "itemId", length = 100, nullable = false)
  private String itemId;
  @Column(name = "item_client_id", nullable = false)
  private int clientId;
  @Column(name = "relatedItemId", length = 100, nullable = false)
  private String relatedItemId;
  @Column(name = "related_item_client_id", nullable = false)
  private int relatedItemClientId;
  ...
}

@Entity
@Table(name = "related_item")
public class RelatedItem {
  @EmbeddedId
  private RelatedItemPK id;

  @ManyToOne(cascade = CascadeType.ALL, optional = false)
  @JoinColumns({
    @JoinColumn(name="itemId", referencedColumnName="itemId", insertable=false, updatable=false),
    @JoinColumn(name="item_client_id", referencedColumnName="item_client_id", insertable=false, updatable=false)
  })
  private Item item;
  @ManyToOne(cascade = CascadeType.ALL, optional = false)
  @JoinColumns({
    @JoinColumn(name="related_item_client_id", referencedColumnName="item_client_id", insertable=false, updatable=false),
    @JoinColumn(name="relatedItemId", referencedColumnName="itemId", insertable=false, updatable=false)
  })
  private Item relatedItem;
  ...
}

The problem is while creating foreign keys for RelatedItem entity, I got an SQLException. It is the second ManyToOne relation that fails. The foreign key generation sql is below,

ALTER TABLE related_item ADD CONSTRAINT FK_related_item_related_item_client_id FOREIGN KEY (related_item_client_id, relatedItemId) REFERENCES item (item_client_id, itemId)

Since item table is indexed first by itemId then by item_client_id, this statement causes MySQL to produce an error.

I would like to switch the places of columns so that the SQL should look like the following,

ALTER TABLE related_item ADD CONSTRAINT FK_related_item_relatedItemId FOREIGN KEY (relatedItemId, related_item_client_id) REFERENCES item (itemId,item_client_id)

I tried changing the order of "JoinColumn"s but the result didn't change. I also tried renaming the fields to check if persistence provider choses the order by column name but again the result didn't change.

So, is there a way to enforce the column ordering?

p.s. I use following stuff:

  • MySQL 5.1
  • EclipseLink 2.0.0
  • Java EE 6
  • JPA 2
  • GlassFish v3

Edit: EclipseLink produces following SQL, which fails to run;

CREATE TABLE related_item (SIMILARITY DOUBLE, widget_id INTEGER NOT NULL, relatedItemId VARCHAR(100) NOT NULL, itemId VARCHAR(100) NOT NULL, related_item_client_id INTEGER NOT NULL, item_client_id INTEGER NOT NULL, PRIMARY KEY (widget_id, relatedItemId, itemId, related_item_client_id, item_client_id));
CREATE TABLE item (IMAGEURL VARCHAR(2048), STATUS VARCHAR(64), URL VARCHAR(2048), PRICE DOUBLE, STOCK INTEGER, DESCRIPTION TEXT(64000), NAME VARCHAR(255), ITEMID VARCHAR(100) NOT NULL, item_client_id INTEGER NOT NULL, PRIMARY KEY (ITEMID, item_client_id));
ALTER TABLE related_item ADD CONSTRAINT FK_related_item_itemId FOREIGN KEY (itemId, item_client_id) REFERENCES item (itemId, item_client_id);
ALTER TABLE related_item ADD CONSTRAINT FK_related_item_related_item_client_id FOREIGN KEY (related_item_client_id, relatedItemId) REFERENCES item (item_client_id, itemId);
ALTER TABLE item ADD CONSTRAINT FK_item_item_client_id FOREIGN KEY (item_client_id) REFERENCES client (ID);

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

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

发布评论

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

评论(2

自此以后,行同陌路 2024-10-15 03:25:08

请包含堆栈跟踪。但是,我强烈建议您跳过 @JoinColumn 标记,除非您有非常充分的理由自己指定外键。通过在其中一个方向上指定mappedBy属性,JPA可以弄清楚自己要做什么。

Java EE 6 和 JPA 投入了大量精力来启用约定优于配置,这意味着大多数时候,一切都可以开箱即用。这对于程序员来说是理想的,因为您无需担心样板代码,对于 JPA 和 Jave EE 容器实现者来说也是理想的,因为这使他们可以自由地选择性能最佳的解决方案。通过自己声明外键关系,您和 JPA 都失去了这一优势。

编辑:事实上,我怀疑指定mappedBy 和指定@JoinTable 可能是问题的根本原因。但我需要查看堆栈跟踪才能确定。

Please include the stack trace. However, I strongly recommend you skip the @JoinColumn tags unless you have a VERY good reason for specifying the foreign keys yourself. By specifying the mappedBy attribute in one of the directions, JPA can figure out what to do by itself.

Java EE 6 and JPA put a lot of effort into enabling Convention over Configuration, which means that most of the time, things will work out of the box. It's desirable for you, the programmer because you have less boiler plate code to worry about, and it's desirable for the JPA and Jave EE container implementors because it gives them freedom to chose the best performing solutions. By declaring the foreign key relationships yourself, you rob both you and JPA of this advantage.

Edit: In fact, I suspect that both specifying mappedBy and specifying the @JoinTable could be the root cause of your problem. But I need to see the stack trace to tell for sure.

眼泪也成诗 2024-10-15 03:25:08

列的顺序应该不重要。如果是这样,那么您可以更改索引中的顺序以进行匹配,或者更改列出主键的顺序,或者仅使用脚本来生成 DDL。

The order of the columns should not matter. If it does, then you could change the order in your index to match, or change the order you list your primary key in, or just use your scripts to generate your DDL.

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