orderby hibernate jpa collections sql-order-by sorted

Colección ordenada JPA/hibernate @OrderBy vs @Sort



@orderby jpa (3)

Me gustaría tener una colección de objetos secundarios (aquí el ejemplo de cat-gatito) que están ordenados. Y mantenga su orden añadiendo nuevos elementos.

@Entity public class Cat { @OneToMany(mappedBy = "cat", cascade = CascadeType.ALL) @OrderBy("name ASC") private List<Kitten> kittens; public void setKittens(List<Kitten> kittens) { this.kittens = kittens; } public List<Kitten> getKittens() { return kittens; } }

Cuando hago cat.getKittens.add(newKitten) la orden por nombre se romperá.

¿Es posible dejar que hibernate haga el trabajo de mantener la colección siempre ordenada? ¿Usando la anotación de hibernación @Sort ?
@Sort tiene la desventaja de que te obliga a implementar una interfaz comparable ... ¿Cuál sería la forma correcta de ''JPA puro'' para hacer eso? ¿Guardar todo en DB y volver a cargarlo? Tiene sentido combinar @OrderBy y @Sort?

La solución de actualización hasta ahora es combinar @OrderBy y @Sort. @OrderBy lleva a una cláusula ORDER BY en el SQL generado que es mejor para el rendimiento (supongo que java está "ordenando" nuevamente al insertar en el contenedor ordenado, pero eso debería ser mucho más rápido porque los elementos ya están ordenados) @Sort juntos con una interfaz Comparable implementada conduce a un contenedor siempre ordenado. Tenga en cuenta que utilizo SortedSet lugar de List . Aquí el Código actualizado:

@Entity public class Cat { @OneToMany(mappedBy = "cat", cascade = CascadeType.ALL) @OrderBy("name ASC") @Sort(type = SortType.NATURAL) private SortedSet<Kitten> kittens; public void setKittens(SortedSet<Kitten> kittens) { this.kittens = kittens; } public SortedSet<Kitten> getKittens() { return kittens; } }


La última versión de Hibernate usa nuevas anotaciones para lograr esto:

@SortNatural @OrderBy("name ASC") private SortedSet<Kitten> kittens = new TreeSet<>();

Hay dos partes para esto:

  1. La anotación @OrderBy especifica que se debe agregar una cláusula order by a la consulta de la base de datos al recuperar los registros relacionados.
  2. La anotación @SortNatural asume que Kitten implementa la interfaz Comparable y usa esa información al construir la instancia de TreeSet . Tenga en cuenta que puede reemplazar esto con la anotación @SortComparator , que le permite especificar una clase de Comparator que se pasará al constructor TreeSet .

Consulte la documentación: docs.jboss.org/hibernate/orm/5.2/userguide/html_single/…


Si desea evitar las anotaciones no estándar, puede hacer que los kittens utilicen una implementación de Collection ordenada. Esto aseguraría que los kittens siempre en orden. Algo como esto:

@Entity public class Cat { @OneToMany(mappedBy = "cat", cascade = CascadeType.ALL) @OrderBy("name ASC") private SortedSet<Kitten> kittens = new TreeSet<>(); }

Tenga en cuenta que este enfoque también requiere que Kitten implemente Comparable (alternativamente, podría pasar un Comparator a su constructor TreeSet ). Además, estoy usando un Set porque no conozco ninguna implementación de List clasificada estándar y supongo que el Cat no tiene ningún clon en su hoja = p.

Actualización: no estoy seguro de cuán quisquilloso es Hibernate con sus definiciones getter / setter, pero con EclipseLink he podido eliminar un setter por completo y ajustar la List devuelta por mi getter en una llamada Collections.unmodifiableList(...) . Luego definí métodos especiales para modificar la colección. Podría hacer lo mismo y forzar a las personas que llaman a usar un método de agregar elementos en orden ordenado. Si Hibernate se queja de no tener getter / setter, ¿tal vez podría cambiar el modificador de acceso? Supongo que se trata de hasta dónde estás dispuesto a llegar para evitar dependencias no estándar.


@Entity public class Cat { @OneToMany(mappedBy = "cat", cascade = CascadeType.ALL) private Set<Kitten> kittens = new TreeSet<>(); }

No es necesario escribir

@OrderBy("name ASC")

Asegúrese de que Kitten Class implemente una interfaz comparable correctamente.