2010-12-03 4 views
1

Ich habe eine Person-Klasse mit der folgenden Felder-Ruhe batching Operation nicht wie erwartet funktioniert

id, hashedId, Beschreibung

ID ist der Primärschlüssel durch eine Sequenz und hashedId nicht erzeugt wird Null.

ich folgendes tun:

  1. session.saveOrUpdate (Person)
  2. person.setHashedId (hash (person.getId()))

Die Id ist in der DB automatisch generiert. Wenn ich das tue, shouldnt erwarte ich nur 2 Aussagen

  1. Wählen Sie die nächste Sequenz Id (Person id)
  2. Insert erhalten, die Person Datensatz einfügen?

Es ist jedoch versucht, einen Einsatz direkt nach dem Schritt 1 (während der abschließende Transaktion verpflichten, ofcourse) mit null hashedId - ich wieder eine Einschränkungsverletzung Fehlermeldung erhalten - HashedId nicht null sein kann.

Antwort

1

Hibernate ist das Richtige zu tun :-) http://docs.jboss.org/hibernate/core/3.3/reference/en/html/mapping.html#mapping-declaration-id Siehe Abschnitt „5.1.4.4. Identität Spalten und Sequenzen“

Das ist, weil Hibernate nicht über die ID tut weiß, ob es durch die DB erzeugt wird. Und die ID wird einem Datensatz nicht wirklich zugewiesen, nur weil Sie eine Sequenz aufgerufen haben. Sie sollten Hibernate entweder den Datensatz speichern lassen und die tatsächliche ID für den Datensatz abrufen, oder Sie sollten eine Hibernate-generierte ID (wie hilo) verwenden (oder sie selbst generieren, wobei der Generatortyp "zugewiesen" ist).

2

Wenn Sie Session.save() oder ähnliches aufrufen, erzeugt Hibernate sofort IDs und führt die Einfügung durch, anstatt sie einfach in die Warteschlange zu stellen, um sie später zu speichern. Es gibt also keine Lücke, in der das Element seine ID zugewiesen hat, bevor es eingefügt wird. Für die "Identität" ID Generation Strategie ist es völlig unmöglich, diese aufzuspalten sowieso ...

Meiner Erfahrung nach ist der sicherste und einfachste Weg, um mit dieser Art von Fall umzugehen, ein Interceptor (oder vielleicht ein EventListener?) um die Entität einzufangen, die mit der hashedId-Eigenschaft unset eingefügt wurde, und sie direkt vor dem Speichern zu generieren. Es ist ein bisschen unangenehm, aber IMHO besser als ID-Generierung in den Anwendungscode zu ziehen.

Hier ist ein Beispiel, wo ich die ‚Referenz‘ Eigenschaft einer neuen Ticket Einheit erzeugen (ein Interceptor mit):

public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, 
    Type[] types) { 
    boolean changed = super.onSave(entity, id, state, propertyNames, types); 

    if (entity instanceof Ticket) { 
     for (int i = 0; i < propertyNames.length; i++) { 
      if (propertyNames[i].equals("reference") && state[i] == null) { 
       state[i] = generateTicketReference((Integer) id); 
       changed = true; 
      } 
     } 
    } 

    return changed; 
} 
0

Das HashedId Feld aus der ID abgeleitet ist, nicht wahr? basierend auf einer kostengünstigen Funktion, nehme ich an? Also musst du dieses Feld in der DB wirklich beibehalten? Verwenden Sie es direkt in Abfragen? Können Sie nicht einfach die Methode getHashedId() immer Hash (this.id) zurückgeben? Auf diese Weise haben Sie dieses hashedId-Feld nicht in der Datenbank und müssen es nicht verwalten - da es einfach anhand der ID abgeleitet wird.

Hoffe, das hilft.

Verwandte Themen