Java EE 6 JPA 2 Соотношение ManyToOne создает неверный внешний ключ - PullRequest
5 голосов
/ 16 декабря 2010

Я пытаюсь создать две сущности, в которых обе сущности имеют встроенные идентификаторы. Одна из сущностей имеет 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)

Так как таблица элементов индексируется сначала по 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 ]

1 голос
/ 18 декабря 2010

Пожалуйста, включите трассировку стека. Однако я настоятельно рекомендую пропустить теги @JoinColumn, если у вас нет ОЧЕНЬ веской причины для указания внешних ключей самостоятельно. Указав атрибут mappedBy в одном из направлений, JPA может выяснить, что делать самостоятельно.

Java EE 6 и JPA приложили немало усилий, чтобы включить Конвенцию поверх Конфигурации, что означает, что большую часть времени все будет работать «из коробки». Вам, программисту, это желательно, потому что у вас меньше кода для беспокойства, и желательно для разработчиков контейнеров JPA и Jave EE, потому что это дает им свободу выбора наиболее эффективных решений. Объявляя о связях с внешними ключами, вы лишаете вас и JPA этого преимущества.

Редактировать: На самом деле, я подозреваю, что как определение mappedBy, так и определение @JoinTable могут быть основной причиной вашей проблемы. Но мне нужно увидеть трассировку стека, чтобы сказать наверняка.

0 голосов
/ 17 июня 2013

Порядок столбцов не должен иметь значения.Если это так, то вы можете изменить порядок в своем индексе, чтобы он соответствовал, или изменить порядок, в котором вы указали свой первичный ключ, или просто использовать ваши сценарии для генерации вашего DDL.

...