Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate: @OrderBy vs @OrderColumn to maintain the order of a collection

Tags:

hibernate

What is the preferred way for maintaining the order of a collection while persisting and also while retrieving from database?

I know that @OrderBy is more of a in-memory sorting that might work in retrieving only when you presist the rows in the order of column you chose.

Let's say I chose to use a column backed by a database sequence, will hibernate make sure that elements in collection are persisted in the same order as in collection (say List).

Any thought?

More details:

Let’s say I have a class A which has one-to-many relationship with class B. B has a primary key field, ‘Id’, which is backed by a sequence in DB.

Class A {
  List<B> bList;
}

I always wanted to retain the order of elements B in A like below:

bList = { b1, b2, b3 }

One way to achieve is using @OrderBy (“Id ASC”). This would work only when the list B is persisted in the order as below:

----------------
Id ----bValue
----------------

1------ b1
2------ b2
3-------b3
------------------

When we retrieve since it is ordered by Id, the order is maintained.

Let’say the collection B is persisted in the following way:

----------------
Id ----bValue
----------------
1------ b2
2------ b1
3-------b3
------------------

When we retrieve, the order of list B go for a toss (since it is order by Id column). So my question, if the collection B always persist in the same order as it appears in the list or not.

like image 649
Phani Kumar Avatar asked Jul 11 '12 12:07

Phani Kumar


People also ask

What is difference between sorted and ordered collection in Hibernate?

When use sorting, Hibernate will load the associated Book entities from the database and use a Java Comparator to sort them in memory. That is not a good approach for huge Sets of entities. Ordering uses an ORDER BY clause in the SQL statement to retrieve the entities in the defined order.

Which annotation is used to order the elements of a collection without using a query?

The annotation @OrderBy Specifies the ordering of the elements of a collection valued association or element collection at the point when the association or collection is retrieved.

What does@ OrderColumn do?

@OrderColumn annotation specifies a column that should maintain the persistent order of a list. The persistence provider maintains the order and also updates the ordering on insertion, deletion, or reordering of the list. This annotation can be used on @OneToMany or @ManyToMany relationship or on @ElementCollection .

What is order column 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")


1 Answers

OrderBy adds an order by clause to the generated SQL to order the members of the retrieved collection by a column of the table of the target entity:

@OrderBy("lastname ASC")
public List<Student> students;

will generate a SQL query like

select ... order by student.lastname ASC

OrderColumn defines the name of an additional column in the table, containing the index of the entity in the list. If you change the ordering of the elements in the list, Hibernate will change the value of this column. And if your students have 0, 3, and 5 as values in this column, the list will be

[student0, null, null, student3, null, student5]

This is well described in the javadoc of those 2 annotations.

EDIT:

The order in which B identifiers are assigned depends on how you persist these B instances:

  • if you explicitely call session.save(), of session.saveOrUpdate(), this assigns an ID to the entity, so calling it for b1, b2 and b3 will respect the order
  • AFAIK, all the other methods (cascading, merge(), persist()) don't guarantee any order (except if you merge or persist, and then flush())

So if you want the list to hold b1, b2 and b3 in this order, regardless of the way those are persisted, your best bet is to add an @OrderColumn annotation to the collection. Hibernate will automatically populate this column with 0 for b1, 1 for b2 and 2 for b3. And when you'll reload the parent entity, They will be in the same order in the list.

like image 117
JB Nizet Avatar answered Sep 21 '22 08:09

JB Nizet