We are migrating from 4.2.13 to 4.3.8. In our setup we had the following code snippet:
Observed behaviour
@OneToMany(mappedBy = "klant", cascade = {CascadeType.REFRESH, CascadeType.REMOVE }, fetch = FetchType.EAGER)
@OrderBy("pk.periodeVanaf asc")
@SortComparator(BurgerlijkeStaatDatumVanafAscComparator.class)
private SortedSet<BurgerlijkeStaat> burgerlijkeStaat;
Hibernate 4.2.13.Final
In 4.2, the combination of @OrderBy and @Sort (we used @Sort there) worked fine (although I admit that this combination is somewhat strange). Both the @OrderBy and @Sort annotations are picked up. See org.hibernate.cfg.annotations.CollectionBinder.bind() line 454.
Hibernate 4.2.8.Final
However, in Hibernate 4.3, the @SortComparator is silently ignored in case @OrderBy is set (ref: org.hibernate.cfg.annotations.CollectionBinder.applySortingAndOrdering(Collection) line 555).
This results in a class cast exception:
-
The @SortComparator is silently ignored, therefore no comparator is set on the collection (lines 578 and 614).
-
Given that the type of the set is a SortedSet, a TreeSet is instantiated in org.hibernate.type.SortedSetType.instantiate(int). In this case, comparator is null
-
As the TreeSet is initialized with a class that does not implement Comparable, a ClassCast exception is thrown.
Expected behaviour
The fact that @OrderBy takes precedence over @Sort* is fine with me. However, Hibernate should validate that both are set and issue and error in this behaviour that this is not allowed. This validation is needed, as it is not clear to the programmer why a ClassCast exception is thrown.
I would expect an additional check like below inserted at line 483 (after the if (isSorted)).
if (hasToBeSorted && isSorted && orderBy != null) {
throw new AnnotationException(
"You cannot specify both @OrderBy and @SortComparator or @SortNatural on the same relationship (" + safeCollectionRole() + ")"
);
}
|