2009-05-26 10 views
3

[Edit: Anscheinend ist dies nur ein Problem für Arrays und FoxyBOA Antwort könnte direkt (oder gerade ist) die Antwort.]Warum enthalten verknüpfte Sammlungen Nullwerte? (Hibernate, Annotation, Frühling)

Meine Frage bezieht sich auf diese Software: Hibernate3 + Annotation , Spring MVC, MySQL und in diesem Beispiel auch Spring Security.

Ich frage mich, warum Sammlungen, die automatisch von Hibernate zugeordnet werden Nullwerte für jede Zeilennummer der untergeordneten Tabelle enthalten (neben den Elementen, die korrekt sind). Mein Beispiel:

Ich habe einen Benutzer und eine Behörden Tisch, der Primärschlüssel der Benutzer Tabelle Benutzername ist, die als Fremdschlüssel dient. Im Moment gibt es 13 Zeilen in meinem Behörden Tabelle. Wenn ich einen Benutzer aus der Datenbank (MySQL InnoDB) abzurufen und Ruhezustand ruft automatisch die Behörden des Benutzers zu dieser Abbildung entsprechen:

@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; 
} 

... I mit einer Sammlung am Ende „Stellen“, die 14 (0-13) Elemente, von denen nur vier nicht-null sind (vier Zeilen in der Datenbanktabelle gehören zu diesem bestimmten Benutzer, also ist das richtig). Soweit ich erkennen, bin ich mit Hibernate Standardwerte für Eigenschaften wie Fetchmode usw. Ich bin der Benutzer wie folgt erhalten:

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

Die Logging-Informationen aus org.hibernate.loader.loader richtig „erwähnt“ vier Reihen für das Ergebnisset. Der Benutzer hat jedoch die vier richtigen Elemente plus zehn Nullwerte im Array. In meinem speziellen Beispiel führt dies zu dieser Ausnahme:

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

Antwort

2

Ich kann Ihnen empfehlen, Ihre Daten zu überprüfen. Wenn Sie verpasste Indizes haben (id Spalte in Ihrem Fall), erhalten Sie anstelle der verpassten ID null in Ihrem Array. I.e.

table authorities: 
username id 
bob 1 
bob 3 
bob 5 

Als Ergebnis ein Array wird: {0 = null, 1 = bob, 2 = null, 3 = bob, 4 = null, 5 = bob}

UPDATE: ich die Situation in zwei Fällen erfüllt:

  1. Missed Schlüsselwerte in indexierte Spalte id bei Behörden Tabelle (zB 0,1,3,4,5 - Wert 2. Hibernate fehlen wird automatisch fügen Sie einen Array-Wert mit Schlüssel 2 und Wert null) automatisch hinzu.
  2. Indexed Werte sind in der Reihenfolge, aber wählen Kriterien Filter Teil von ihnen (zB Ihre HQL ähnlich wie "von Benutzer u beitreten u.authorities a wo a.id = 2". In diesem Fall laden einen Benutzer, aber in Ruhezustand behördlichen Array haben Sie nur 3 Werte: 0 - null, 1 - null, 2 - Autorität mit ID 2).
+0

Ich habe einige Indizes hinzugefügt und entfernt, bekomme aber immer noch 14 Werte mit vier korrekten Werten bei diesen Array-Indizes, die dem Wert meiner ID-Spalte entsprechen. Ich denke wirklich, dass hier mein Problem liegt. Könntest du ein bisschen mehr "ausarbeiten", ich verstehe nicht ganz, was du meinst. Danke bis jetzt! – Wolfram

3

Die Antwort liegt in der Annotation @IndexColumn. Es verwendet den Wert von id als Array-Index, daher ist die Anzahl der Elemente im Array im Grunde genommen der Wert der höchsten ID in der Tabelle "Authorities".

siehe hibernate documentation on indexed collections

versuchen die Anmerkung zu entfernen.

Auch nur als ein Gedanke; Haben Sie überlegt, ein Set für das Mapping zu verwenden? Es ist nicht unbedingt notwendig, es ist nur ein bisschen häufiger Form der Zuordnung, das ist alles.

+0

Zuerst hatte ich nicht die Annotation @IndexColumn, die zu einer "org.hibernate.AnnotationException führte: Liste/Array muss mit einer @IndexColumn kommentiert werden". Wie für den Typ Frage: Ich implementierte die "UserDetails" Schnittstelle und ihre Methode "GrantedAuthority [] getAuthorities();". Ich werde es untersuchen, um die @IndexColumn loszuwerden. Sie haben mir wirklich geholfen, dieses Problem zu verstehen. – Wolfram

+0

Ich verstehe. Ich habe die Integration der Frühjahrssicherheitsfunktion einige Male implementiert, das Muster, das mir am besten gedient hat, ist eine Methode wie "UserDetails toUserDetails()" in der Entität User. Dies ermöglicht Ihnen die Verwendung einer unveränderlichen Nicht-Hibernate-Implementierung, die Ihnen wiederum sehr gut helfen wird, da das Zurücksetzen von Hibernate-Objekten in der http-Sitzung (da die meisten Benutzerdetails enden) fast immer in Tränen endet. –

+0

Klingt gut. Und anstatt den Benutzer direkt von der Methode "loadUserByUsername (..)" des UserDetailsService zurückzugeben, geben Sie user.toUserDetails() zurück. In Bezug auf das "Ende in Tränen", als ich das Array manuell korrigierte, endete ich in zahlreichen Hibernate-Ausnahmen (zB beim Versuch, einen Null-gefüllten Benutzer zurück in die DB zu schreiben, woher auch immer ich kam, schaute ich nicht es weiter, aber "rollte zurück" zu meinem ersten Problem). Ich nehme an, das hast du gemeint. – Wolfram

Verwandte Themen