Requête JPQL pour l'élément dans la liste stockée avec AttributeConverter

comme Tobias Liefke a suggéré ici , j'ai implémenté un AttributeConverter pour stocker les valeurs list dans une colonne de chaîne simple séparée par des virgules.

Classe Convertisseur:

public class ListNumbersConverter implements AttributeConverter<List<Long>, String>

champ dans la classe D'entité:

@Column(name = "user_ids", nullable = false)
@Convert(converter = ListNumbersConverter.class)
private List<Long> userIds;

cela fonctionne bien mais je ne peux pas interroger les enregistrements pour des éléments de liste spécifiques. J'ai essayé d'utiliser l'opérateur IN dans la requête JPQL comme ci-dessous:

? in userIds 

avec ceci, je n'obtiens qu'un résultat si le paramètre input param est le premier élément de la valeur DB. e.g: valeur en DB est "1,2,3". Je suis capable de récupérer cet enregistrement si la valeur param d'entrée est 1 pour la requête mentionnée ci-dessus, mais pas capable de récupérer si la valeur est 2 ou 3. Comment dois-je écrire ma requête pour récupérer tous les enregistrements qui contiennent un élément spécifique?

ma base de données est MySQL.

1
demandé sur Tobias Liefke 2018-05-15 20:15:10

1 réponses

Hibernate ne sais pas comment le convertisseur de cartes de la liste de la colonne. Il ne peut pas construire de mapping à partir du JPQL ? in userIds vers le fragment SQL correspondant, car il aurait besoin de savoir comment votre convertisseur est implémenté.

mais vous pouvez toujours construire ce fragment SQL vous-même, par exemple:

WHERE concat(',', entity.userIds, ',') LIKE concat('%,', ?, ',%')

la première concat est de s'assurer que l'expression correspond même à la première et à la dernière valeur de la liste (qui ne commencerait ou ne se terminerait pas avec le séparateur).

il y a d'autres fonctions spécifiques à la base de données qui pourraient être utilisées, mais cet exemple fonctionne sur tous les types de bases de données que je connais.

une autre remarque: vous ne devez pas essayer de joindre userIds dans la requête - comme il est d'un de base type, même si c'est une liste. Voir le JavaDoc de @Convert :

l'annotation convertie est utilisé pour spécifier la conversion d'un champ de Base ou propriété.

néanmoins Hibernate se plaindra si vous comparez directement votre attribut avec un littéral ( entity.userIds = '1' ) parce que le type de l'attribut ne correspond pas au type du littéral. Mais aussi longtemps que vous utilisez une fonction comme ci-dessus pour chaque côté de la comparaison, il ne me plaindrai pas.

0
répondu Tobias Liefke 2018-05-29 12:23:56