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

时间:2010-12-16 16:22:33

标签: jpa eclipselink jpa-2.0 java-ee-6

我正在尝试创建两个实体,其中两个实体都有embeddedIds。其中一个实体有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;
  ...
}

问题是在为RelatedItem实体创建外键时,我得到了一个SQLException。这是第二个失败的ManyToOne关系。外键生成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”的顺序,但结果没有改变。我还尝试重命名字段以检查持久性提供程序是否按列名选择顺序,但结果再次没有更改。

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

P.S。我使用以下内容:

  • 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);

2 个答案:

答案 0 :(得分:1)

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

Java EE 6和JPA在启用“约定优于配置”方面投入了大量精力,这意味着大多数情况下,事情都可以直接使用。这对程序员来说是理想的,因为你需要担心更少的锅炉板代码,并且它对于JPA和Jave EE容器实现者来说是理想的,因为它使他们可以自由选择性能最佳的解决方案。通过自己声明外键关系,你可以抢夺你和JPA的这种优势。

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

答案 1 :(得分:0)

列的顺序无关紧要。如果是,那么您可以更改索引中的顺序以匹配,或更改列出主键的顺序,或者只使用脚本生成DDL。