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

时间:2012-03-31 15:34:08

标签: hibernate jpa many-to-many eclipselink

我有一个实体映射如下:

@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)来表示一轮中的组的顺序。

现在假设一个连接表包含通过自引用(从组到组)链接有序组的实体:

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;

问题:

对于自有方,是否也支持将@ManyToMany(mappedBy = ...)反向关系映射到@OrderColumn

@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应该可以正常使用两种关系 parents和{ {1}} - 至少在理论上。但这里的做法是什么(JPA)?

请注意,仅仅在Hibernate和/或EclipseLink上尝试它并不能真正回答JPA 2规范或JPA兼容提供程序应该或必须支持这种情况的问题。


更新2:

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

children

删除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 的{​​{1}}会导致@OrderColumn关系出现相同的异常。看起来Hibernate不喜欢在外键中使用的订单列。


更新3:

在GlassFish上使用EclipseLink进行测试......这样做,没有映射异常。

这提出了两个后续问题:

  1. JPA是否禁止使用外键列?对我来说,为什么他们不应该只是简单地工作......
  2. 这是一个Hibernate错误吗?

2 个答案:

答案 0 :(得分:8)

javadoc or OrderColumn包含您要查找的信息:

  

OrderColumn注释指定在   引用要订购的集合的关系。该   订单列不可见作为实体状态的一部分或   可嵌入的课程。

     

OrderBy注释应该用于可见的排序   持久状态并由应用程序维护。 OrderBy   

指定OrderColumn时不使用注释

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

答案 1 :(得分: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