Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@OrderColumn annotation in Hibernate 3.5

Tags:

I'm trying to use the @OrderColumn annotation with Hibernate 3.5

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

When retrieving data, everything works fine. But I can't make it reorder elements in the List and save the new order to the database.

like image 201
Piotr Gwiazda Avatar asked Jun 02 '10 08:06

Piotr Gwiazda


People also ask

What is @OrderColumn in hibernate?

@OrderColumn is used to store list index. As list is ordered collection, so to maintain the list index there can be a column in database and while inserting the data, list index will be stored in that column. For this the property in entity should be annotated with. @OrderColumn (name="column-name")

Is @column annotation necessary?

@Column. Let's start with the @Column annotation. It is an optional annotation that enables you to customize the mapping between the entity attribute and the database column.

What is the use of @entity annotation in hibernate?

@Entity annotation marks this class as an entity. @Table annotation specifies the table name where data of this entity is to be persisted. If you don't use @Table annotation, hibernate will use the class name as the table name by default.

What is @basic annotation in hibernate?

We can use the @Basic annotation to mark a basic type property: @Entity public class Course { @Basic @Id private int id; @Basic private String name; ... } In other words, the @Basic annotation on a field or a property signifies that it's a basic type and Hibernate should use the standard mapping for its persistence.


2 Answers

The combination of @OneToMany(mappedBy="...") and @OrderColumn is not supported by Hibernate. This JIRA issue tracks a request to throw a more obvious error message when this invalid combination is used: http://opensource.atlassian.com/projects/hibernate/browse/HHH-5390

I think that this isn't supported mainly because it is an odd relational pattern. The annotations above indicate that the "one" side of the relationship determines how the relationship will be flushed to the database, but the order/position is only available on the "many" side by examining the List. It makes more sense for the "many" side to own the relationship, since that side knows about both the membership and the ordering of the elements.

The Hibernate Annotations docs describe this situation in some detail:

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

The workaround is to remove the "mappedBy" attribute, which will cause the association to use the default join table strategy instead of a column on the target table. You can specify the name of the join table using the @JoinTable annotation.

The net effect of this change is that the "many" side of the relationship now determines how the relationship is persisted. Your java code needs to ensure that the List is updated properly, because Hibernate will now disregard the "one" side when flushing the entities.

If you still want to have the "one" side accessible in Java, map it with

@ManyToOne @JoinColumn(name="...", insertable=false, updatable=false, nullable=false) 
like image 163
Peter Centgraf Avatar answered Sep 22 '22 14:09

Peter Centgraf


Do something like this:

@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);         }     } } 
like image 39
Daniel De León Avatar answered Sep 19 '22 14:09

Daniel De León