Hibernate 3.5中的@OrderColumn注释

时间:2010-06-02 08:49:44

标签: hibernate jpa jpa-2.0 one-to-many

我正在尝试将@OrderColumn注释与Hibernate 3.5一起使用

@OneToMany(mappedBy = "parent",fetch=FetchType.EAGER, cascade=CascadeType.ALL)
@OrderColumn(name = "pos")
private List<Children> childrenCollection;

检索数据时,一切正常。但我不能让它重新排序列表中的元素并将新订单保存到数据库。

3 个答案:

答案 0 :(得分:26)

Hibernate不支持@OneToMany(mappedBy =“...”)和@OrderColumn的组合。当使用此无效组合时,此JIRA问题会跟踪发出更明显错误消息的请求:http://opensource.atlassian.com/projects/hibernate/browse/HHH-5390

我认为这不受支持主要是因为它是一种奇怪的关系模式。上面的注释表明关系的“一”侧决定了如何将关系刷新到数据库,但是通过检查List,订单/位置仅在“多”侧可用。对于“很多”方来说,拥有这种关系更有意义,因为那一方知道元素的成员资格和顺序。

Hibernate Annotations文档详细描述了这种情况:

http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#entity-hibspec-collection-extratype-indexbidir

解决方法是删除“mappedBy”属性,这将导致关联使用默认连接表策略而不是目标表上的列。您可以使用@JoinTable批注指定连接表的名称。

这种变化的净效果是,关系的“多”方面现在决定了关系的持久性。你的java代码需要确保List正确更新,因为Hibernate现在会在刷新实体时忽略“one”方。

如果您仍希望在Java中访问“one”端,请使用

进行映射
@ManyToOne
@JoinColumn(name="...", insertable=false, updatable=false, nullable=false)

答案 1 :(得分:9)

做这样的事情:

@Entity
class Parent {

    @OneToMany
    @OrderColumn(name = "pos")
    List<Child> children;
}

@Entity
class Child {

    @ManyToOne
    Parent parent;
    @Column(name = "pos")
    Integer index;

    @PrePersist
    @PreUpdate
    private void prepareIndex() {
        if (parent != null) {
            index = parent.children.indexOf(this);
        }
    }
}

答案 2 :(得分:3)

您应该尝试在关联的所有者上指定OrderColumn。 或者在您的映射中,您将所有者放在子项上,所有者应该是父项(在双向关联中,所有者是没有关键字mappedBy的所有者,这里您将此关键字放在父类的上,然后您表示父母的班级不是所有者)

在您的子类中,您应该在parentCollection上有关键字mappedBy。但不是关于孩子们的收藏 在你的父类中,你应该有@JoinTable注释,如下所示:

@OneToMany(mappedBy = "parent",fetch=FetchType.EAGER, cascade=CascadeType.ALL)
@OrderColumn(name = "pos")
@JoinTable( name = "<NAME_OF_YOUR_TABLE>", joinColumns = @JoinColumn( <JOIN_COLUMNS_...> )
private List<Children> childrenCollection;