3

I'm hoping someone can help me with my hibernate issue as I've been banging my head against Google for around an hour without result.

So the issue is that I have a SortedMap in a class, using Integer as the Key (and its natural built-in compareTo method) and another class as the value type. I'm using the key to keep the user-defined order of the value type and trying to get Hibernate to persist this.

For whatever reason, Hibernate has defaulted to disregarding the key I have inputted and instead using the value type's primary key as the key instead. When I load my Map back out of the database all of my keys have been changed in this way.

Definition of the Map is shown below (I'm using annotation-style Hibernate);

@ManyToMany(cascade = CascadeType.ALL)
@MapKey
@Sort(type = SortType.NATURAL)
private SortedMap<Integer, Column> columnOrder;

I can't use the Column type to store the order itself as the Column may be used in many instances of the containing type, with a different key value each time. Any guidance would be most appreciated.

DavidH
  • 223
  • 2
  • 13
  • Not directly related to your question, but I wonder why you don't just use a list of `Column`? We had a similar use case and in the end went much better with a list. – SpaceTrucker Oct 10 '12 at 13:50
  • 1
    I may be mistaken, but the order is changeable by the user at any point, and with a List, I don't think hibernate would persist the change in ordering. A SortedMap ensures correct ordering by its internal implementation. – DavidH Oct 10 '12 at 13:53
  • I just want to not that in our use case the task of maintaining the keys in that sorted map became a nightmare. If you start with a continuous range of keys `1..n` and make only one change (switch, add, remove), you will have to touch `O(n)` elements in that map in your own code. If you were using a list, the list would take care of it. – SpaceTrucker Oct 11 '12 at 06:28

2 Answers2

2

So I found the answer after discovering this StackOverflow question with a similar issue: Sorted map of Java primitives using JPA2 and Hibernate?

By changing the @MapKey annotation to the @MapKeyColumn annotation, I was able to give Hibernate the instruction to persist the key in the column name I specified, as below;

@ManyToMany(cascade = CascadeType.ALL)
@MapKeyColumn(name = "hierarchyOrdering")
@Sort(type = SortType.NATURAL)
private SortedMap<Integer, Column> columnOrder;

Thanks for the help.

Community
  • 1
  • 1
DavidH
  • 223
  • 2
  • 13
1

From the javadoc of javax.persistence.OrderColumn:

Specifies a column that is used to maintain the persistent order of a list. The persistence provider is responsible for maintaining the order upon retrieval and in the database. The persistence provider is responsible for updating the ordering upon flushing to the database to reflect any insertion, deletion, or reordering affecting the list.

So it is possible to use a list for that.

The JPA 2.0 spec states in section 2.2 Persistent Fields and Properties:

Collection-valued persistent fields and properties must be defined in terms of one of the following collection- valued interfaces regardless of whether the entity class otherwise adheres to the JavaBeans method conventions noted above and whether field or property access is used: java.util.Collection, java.util.Set, java.util.List[3], java.util.Map. The collection implementation type may be used by the application to initialize fields or properties before the entity is made persistent. Once the entity becomes managed (or detached), subsequent access must be through the interface type.

So it seems as if a SortedMap is not supported by JPA.

SpaceTrucker
  • 13,377
  • 6
  • 60
  • 99
  • SortedMap *is a* Map. Also, using List + `@OrderColumn` only works if the ordering is contiguous. If that is the case, you are right, that is a great combo. – Steve Ebersole Oct 10 '12 at 17:35