Tri de l'expression dans Spring Data JPA
J'ai la classe d'entité suivante où objectId est une chaîne alphanumérique
@Data
@Entity
@Table(name = "CASE_INFO")
public class CaseInfo {
@Id
@Column(name = "ID")
private UUID id;
@Column(name = "OBJECT_ID")
private String objectId;
}
J'ai aussi le référentiel suivant
@Repository
public interface CaseInfoRepository extends JpaRepository<CaseInfo, UUID>, JpaSpecificationExecutor<CaseInfo> { }
Maintenant, quand je fais une requête basée sur la spécification et des objets paginables comme celui-ci
Specification<CaseInfo> specification = (Specification<CaseInfo>) (root, query, criteriaBuilder) -> criteriaBuilder.and();
Pageable pageable = PageRequest.of(0, 25, Sort.by("objectId"));
caseInfoRepository.findAll(specification, pageable);
Je veux être en mesure de trier le résultat en fonction de CaseInfo.objectId numériquement afin que l'ordre par requête SQL ressemble à quelque chose comme ça
... order by to_number(OBJECT_ID) ...
Si je fais quelque chose comme
PageRequest.of(0, 25, Sort.by("objectId"))
il trie par ordre alphabétique de sorte que "100" soit avant "2", ce qui est faux pour mon cas d'utilisation.
j'ai trouvé https://www.baeldung.com/spring-data-jpa-query où il utilise
JpaSort.unsafe("LENGTH(name)")
mais cela ne semble pas fonctionner car si je le fais
PageRequest.of(0, 25, JpaSort.unsafe("to_number(objectId)"))
Il donne le message d'erreur "Aucune propriété à trouver pour le type CaseInfo! Vouliez-vous dire 'id'?"
Quelqu'un connaît-il un moyen de donner une expression personnalisée à l'objet Sort?
Réponses
Vous pouvez ajouter un champ de formule convertissant la valeur de chaîne en valeur numérique, puis trier par ce champ ou utiliser l'implémentation par défaut findAll(Pageable pageable):
@Data
@Entity
@Table(name = "CASE_INFO")
public class CaseInfo {
@Id
@Column(name = "ID")
private UUID id;
@Column(name = "OBJECT_ID")
private String objectId;
@Formula(value = "CAST(OBJECT_ID AS NUMERIC(10, 0))")
private int numObjectId;
}
Dépôt:
@Repository
public interface CaseInfoRepository extends
JpaRepository<CaseInfo, UUID>, JpaSpecificationExecutor<CaseInfo> {
// sort by formula field
List<CaseInfo> findAllByOrderByNumObjectId(Pageable pageable);
}
Il y a un truc avec l' aide de CASTfonction@Formula - il est très probable à l' échec lors de la coulée à INT, INTEGER, BIGINTmais il fonctionne lors de la coulée à NUMERIC(10, 0).
Numeric doit également être suffisamment grand pour contenir la valeur dans la chaîne après la conversion, sinon un débordement d'entier peut se produire.