JPA是否支持@ManyToMany(mappedBy = ... ) + @OrderColumn?

13

我有一个实体映射如下:

@Entity
@Table(name = "Groups")
@IdClass(value = GroupId.class)
public class Group implements Serializable
{
    @Id
    @Column(name = "round_id")
    private Integer roundId;

    @Id
    @Column(name = "ordinal_nbr")
    private Integer ordinalNbr = 0;

    ...
}

它有一个组合键(round_id, ordinal_nbr),用于指示轮次中组的顺序。
现在想象一个连接表,包含通过自引用(从Group到Group)链接有序组的实体:
CREATE TABLE GroupLinks
(
  parent_round_id INTEGER NOT NULL,
  parent_ordinal_nbr SMALLINT NOT NULL,
  child_round_id INTEGER NOT NULL,
  child_ordinal_nbr SMALLINT NOT NULL,
  PRIMARY KEY (parent_round_id, parent_ordinal_nbr, child_round_id, child_ordinal_nbr),
  FOREIGN KEY (parent_round_id, parent_ordinal_nbr) REFERENCES Groups (round_id, ordinal_nbr),
  FOREIGN KEY (child_round_id, child_ordinal_nbr) REFERENCES Groups (round_id, ordinal_nbr)
);

我知道可以为拥有实体(无论我选择哪个)映射@ManyToMany+@JoinTable+@OrderColumn

@ManyToMany
@JoinTable(name = "GroupLinks", joinColumns = {@JoinColumn(name = "parent_round_id", referencedColumnName = "round_id"), @JoinColumn(name = "parent_ordinal_nbr", referencedColumnName = "ordinal_nbr")}, inverseJoinColumns = {@JoinColumn(name = "child_round_id", referencedColumnName = "round_id"), @JoinColumn(name = "child_ordinal_nbr", referencedColumnName = "ordinal_nbr")})
@OrderColumn(name = "child_ordinal_nbr")
private List<Group> children;

问题:

对于拥有方,是否支持使用@OrderColumn来映射@ManyToMany(mappedBy = ...)的反向关系?

@ManyToMany(mappedBy = "parents")
@OrderColumn(name = "parent_ordinal_nbr")
private List<Group> parents;

JPA 2规范是否允许或拒绝此操作? 谢谢。

更新1:

以上基本上是一个图形结构。这里有一个例子:

IMAGE

GroupLinks表包含方框实体。只看B2 Group实体时,parents列表将包含(a,1,b,2)(a,2,b,2)。至于children列表,则会包含(b,2,c,1)(b,2,c,2)(b,2,c,3)
如您所见,B2列表中的实体不会发生冲突,因此@OrderColumn对于parentschildren两个关系都可以正常工作-至少在理论上是这样。但是在这里(JPA)的实践是什么呢?
请注意,仅在Hibernate和/或EclipseLink上尝试并不能真正回答这个问题,即JPA 2规范或JPA兼容提供程序是否应该或必须支持此场景。

更新2:

尝试在Hibernate上使用以上映射会导致以下映射异常:

Caused by: org.hibernate.MappingException: Repeated column in mapping for collection: com.kawoolutions.bbstats.model.Group.parents column: parent_ordinal_nbr
    at org.hibernate.mapping.Collection.checkColumnDuplication(Collection.java:340)
    at org.hibernate.mapping.Collection.checkColumnDuplication(Collection.java:363)
    at org.hibernate.mapping.Collection.validate(Collection.java:320)
    at org.hibernate.mapping.IndexedCollection.validate(IndexedCollection.java:89)
    at org.hibernate.cfg.Configuration.validate(Configuration.java:1291)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1729)
    at org.hibernate.ejb.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:84)
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:904)
    ... 9 more

移除@OrderColumn中的parent_ordinal_nbr会导致children关系出现相同的异常。看起来Hibernate不喜欢同时用于外键的排序列。


更新3:

在GlassFish上使用EclipseLink测试过,这个方法可行,没有映射异常。

这引出了两个后续问题:

  1. JPA是否禁止外键列的顺序?我不明白为什么它们不能正常工作...
  2. 这是Hibernate的一个bug吗?
2个回答

11

OrderColumn的文档中包含了您需要的信息:

在引用要排序的集合的关系一方上指定OrderColumn注释。排序列不作为实体或可嵌入类状态的一部分而可见。

OrderBy注释应用于由应用程序维护且作为持久状态可见的排序。当指定OrderColumn时,不使用OrderBy注释。

OrderColumn用于向连接表添加一个额外的列,用于维护列表的顺序。如javadoc所述,排序列不是实体状态的一部分。在您的情况下,似乎您想通过其持久属性之一对列表中的元素进行排序。在这种情况下,必须使用OrderBy注释(或者有一个getter在返回列表之前对其进行排序)。


无论实体的状态如何...后续问题在这里:http://stackoverflow.com/questions/10054400/jpa-ordercolumn-and-visible-state-of-an-entity - Kawu
好的解释。真正展示了OrderColumn和OrderBy之间的区别。+1 - Shay Elkayam

0
在OPENJPA中,@OrderColumn存在问题,检索操作可以正常工作,但保存实体时会出现“分离对象”错误,这个错误与添加此注释(@OrderColumn)有关。
解决方案是在parent.getChildEntity类中使用比较器来对子实体列表进行排序,从而避免使用@OrderColumn。
Collections.sort(this.child, new Comparator<class_type>() {
@Override
        public int compare(class_type p1, class_type p2) {
            return (int) (p1.getId() - p2.getId());
        }

    });

问题已解决 :) John V, Col


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接