2009-05-26 5 views
3

[Edit: Apparemment, cela est seulement un problème pour les tableaux et la réponse de FoxyBOA pourrait diriger (ou même est-) la réponse.]Pourquoi les collections associées contiennent-elles des valeurs nulles? (Mise en veille prolongée, Annotation, Printemps)

Ma question porte sur ces logiciels: Hibernate3 + Annotation , Spring MVC, MySQL et dans cet exemple aussi Spring Security. Je me demandais pourquoi les collections, qui sont automatiquement associées par Hibernate, contiennent des valeurs NULL pour chaque numéro de ligne de la table enfant (en plus des éléments corrects). Mon exemple:

J'ai un utilisateurs et une autorités table, la clé primaire des utilisateurs tableau est nom d'utilisateur qui sert de clé étrangère. À l'heure actuelle, il y a 13 lignes dans ma table autorités. Lorsque je récupère un utilisateur de la base de données (MySQL InnoDB) et Hibernate récupère automatiquement les autorités de l'utilisateur correspondant à cette cartographie:

@OneToMany 
@JoinColumn(name = "username") 
@IndexColumn(name="id") // "id" was the primary key and is used to sort the elements 
public Authority[] getAuthorities() { 
    return authorities; 
} 
public void setAuthorities(Authority[] authorities) { 
    this.authorities = authorities; 
} 

... Je finis avec une « autorités » collection contenant 14 (0-13) les éléments dont seulement quatre ne sont pas null (quatre lignes dans la table de base de données appartiennent à cet utilisateur spécifique, donc c'est correct). Pour autant que je me rends compte, j'utilise par défaut Hibernate pour des propriétés comme fetchmode etc. Je reçois l'utilisateur comme ceci:

Criteria criteria = getSession().createCriteria(User.class); 
criteria.add(Restrictions.eq("username",username)); 
User user = (User) criteria.uniqueResult(); 

Le org.hibernate.loader.loader de correctement les informations de journalisation « mentions » quatre lignes pour le résultat. Néanmoins, l'utilisateur créé a les quatre éléments corrects plus dix valeurs NULL dans le tableau. Dans mon exemple spécifique, cela se traduit par cette exception:

java.lang.IllegalArgumentException: Granted authority element 0 is null - GrantedAuthority[] cannot contain any null elements 

Répondre

2

Je peux vous recommander de vérifier vos données. Si vous avez un index manqué (colonne id dans votre cas), alors au lieu de l'identifiant manqué, vous obtiendrez null dans votre tableau. I.e.

table authorities: 
username id 
bob 1 
bob 3 
bob 5 

En conséquence, vous aurez un tableau: {0 = null, 1 = bob, 2 = null, 3 = bob, 4 = null, 5 = bob}

MISE À JOUR: j'ai rencontré la situation dans deux cas:

  1. valeurs clés dans la colonne indexée Missed id à autorités tableau (par exemple 0,1,3,4,5 - valeur manquante 2. Hibernate automatique ajouter mathématiquement à une valeur de tableau avec la clé 2 et la valeur null).
  2. Les valeurs indexées sont dans l'ordre, mais certains critères en filtrent une partie (par exemple votre HQL similaire à celle "de l'utilisateur u rejoignez u.authorities où a.id = 2".) Dans ce cas, hibernate charge un utilisateur, mais dans Le tableau des autorités vous donnera seulement 3 valeurs: 0 - null, 1 - null, 2 - autorité avec l'identifiant 2).
+0

J'ai ajouté et supprimé des index, mais je reçois toujours 14 valeurs avec quatre valeurs correctes à ces index de tableau qui sont identiques à la valeur de ma colonne id. Donc je pense vraiment que c'est là que réside mon problème. Pourriez-vous «élaborer» un peu plus, je ne comprends pas très bien ce que vous voulez dire. Merci pour l'instant! – Wolfram

3

La réponse se trouve dans l'annotation @IndexColumn. Il utilise la valeur de id comme index de tableau, donc le nombre d'éléments dans le tableau va fondamentalement être la valeur de l'ID le plus élevé dans la table Authorities.

voir le hibernate documentation on indexed collections

essayez de supprimer l'annotation.

Aussi juste comme une pensée; avez-vous envisagé d'utiliser un Set pour le mapping? ce n'est pas strictement nécessaire, c'est juste une forme de cartographie un peu plus commune, c'est tout.

+0

Au début, je n'avais pas l'annotation @IndexColumn, qui a abouti à une "org.hibernate.AnnotationException: List/tableau doit être annoté avec un @IndexColumn". En ce qui concerne la question de type: je mettais en œuvre l'interface "UserDetails" et sa méthode "GrantedAuthority [] getAuthorities();". Je vais y jeter un coup d'oeil pour me débarrasser de @IndexColumn. Vous m'avez vraiment aidé à comprendre ce problème. – Wolfram

+0

Je vois. J'ai implémenté plusieurs fois l'intégration de sécurité de printemps, le modèle qui m'a le mieux servi est d'avoir une méthode comme 'UserDetails toUserDetails()' sur l'entité Utilisateur. Cela vous permet d'utiliser une implémentation immuable d'aucune mise en veille prolongée, qui à son tour vous sera très utile car mettre des objets hibernate dans la session http (car la plupart des détails des utilisateurs finissent) se termine presque toujours en larmes. –

+0

Ça a l'air génial. Et au lieu de renvoyer l'utilisateur directement à partir de la méthode "loadUserByUsername (..)" du UserDetailsService, vous renvoyez user.toUserDetails()? En ce qui concerne la "fin des larmes", lorsque je corrigeais le tableau manuellement, je me retrouvais dans de nombreuses exceptions Hibernate (par exemple, en essayant d'écrire un utilisateur vide dans la DB, d'où cela venait, je ne regardais pas plus loin mais "reculé" à mon premier problème). Je suppose que c'est ce que vous vouliez dire. – Wolfram

Questions connexes