2010-01-21 11 views
22

Ich habe eine Tabelle mit einer generierten ID, aber in einigen Fällen möchte ich es selbst einstellen. Kann ich Hibernate zwingen, den @GeneratedValue zu ignorieren?@Id @GeneratedValue aber eigenen ID-Wert setzen

+0

Haben Sie es versucht, sehen was passiert? – skaffman

+5

Ja, Hibernate ist es egal, ob die ID gesetzt ist oder nicht - es wird trotzdem ein Wert generiert. – woezelmann

+2

Ich wusste, dass ich das schon mal irgendwo gesehen habe: http://StackOverflow.com/Questions/89439/Bypass-generatedvalue-in-Hibernate - benutz 'merge()' anstatt 'persist()' – skaffman

Antwort

6

Es hat eine übertrieben sein, aber haben Sie sich Gedanken über Ihre eigene CustomIDGenerator schreiben, die wahrscheinlich Subklassen der Autogenerator von Hibernate sagen und macht ein paar Methoden, wo Sie die ID des nächsten Klassenobjekt festlegen können

erzeugt, so zum Beispiel zu
class MyGenerator extends .... { 

public void setIdForObject(Class clazz, Long id) { 
    //once you use this API, the next time an object of 
    //type clazz is saved the id is used 
} 

public void setIdForObject(Class clazz, Long id, Matcher matcher) { 
    //once you use this API, the next time an object of 
    //type clazz is saved and the matcher matches yes the id will be 
    //assigned. Your matcher can match properties like name, age etc 
    //to say the matched object 
} 
} 

Dies kompliziert könnte aber zumindest ist möglich, da pro hibernate doco

+0

In den hibernate.org Foren gibt es einen Benutzer, der seine Generator-Klasse für dieses genaue Szenario geschrieben hat: https://forum.hibernate.org/viewtopic.php?p=2404032 – tmarthal

+0

Ich stolperte auf diese Anfrage auf der Suche nach einer Lösung für die exakt gleiche Frage (obwohl ich EclipseLink anstelle von Hibernate verwende). Ich begann mit einem benutzerdefinierten ID-Generator, aber (zumindest in meinem EclipseLink-Szenario) gibt es ein Problem: Woher weiß ich, ob das Objekt, das persistent sein muss, bereits eine ID hat oder nicht? Ich habe nicht das Entitätsobjekt in meinem benutzerdefinierten ID-Generator zur Hand. Ich kann also nicht feststellen, ob ich eine neue ID generieren muss - falls das Objekt keine hat. Oder wenn ich nur die ID zurückgebe, die das Objekt bereits hat (oder vielleicht Null oder was auch immer notwendig ist). – Jens

+0

Add-on zu meinem Kommentar vor: In EclipseLink gibt es beim Erstellen eines eigenen Sequence-Generators eine Methode namens 'shallAlwaysOverrideExistingValue', die überschrieben werden kann. Dies scheint eine mögliche Lösung zu sein. Obwohl es sich ein wenig unangenehm anfühlt, Dinge zu überschreiben, die ich nicht vollständig überblicke und auch keine Dokumentation zu diesem [Bug] gefunden habe (https://bugs.eclipse.org/bugs/show_bug.cgi?id=300556) Eintrag. – Jens

2

Für Ihren Anwendungsfall können Sie diesen Benutzer manuell hinzufügen. Eine Möglichkeit besteht darin, die Einfügeoperation in eine Datei mit dem Namen "./import.sql" (in Ihrem Klassenpfad) zu versetzen. Hibernate wird diese Anweisungen ausführen, wenn die SessionFactory gestartet wird.

+0

@Emmanuel Bernard Er sagte: ** aber in einigen Fällen ** würde ich es gerne selbst einstellen. Wenn Sie definieren, wie Hibernate eine Entity speichern soll (über die Datei "/.import.sql"), funktioniert die automatische Generierung des Bezeichners nicht, oder? –

+0

Nein, es ist nicht verwandt, import.sql ist einfach SQL, so können Sie tun, was Sie wollen, einschließlich der Aktualisierung der Sequenz oder Tabelle ID, wenn nötig –

+0

Gut zu wissen (+1) Ich werde es versuchen. –

4

Obwohl diese Frage vor einer ganzen Weile gefragt wurde, fand ich die perfekte Antwort für sie in this post von @lOranger und wollte teilen es.

Dieser Vorschlag prüft, ob die aktuelle ID des Objekts auf etwas anderes als null gesetzt ist, und wenn dies der Fall ist, wird sie verwendet, andernfalls wird sie mit der Standardgenerierungsstrategie (oder der konfigurierten) generiert.

Es ist einfach, direkt, und adressiert das Problem, das von @Jens heraufbeschworen wird, von einem, der die aktuelle ID des Objekts nicht abrufen kann.

Ich setzte es nur (durch die UUIDGenerator erstreckt), und es wirkt wie ein Zauber :-D

1

Ihre eigene identifiergenerator/sequencegenerator

public class FilterIdentifierGenerator extends IdentityGenerator implements IdentifierGenerator{ 

@Override 
public Serializable generate(SessionImplementor session, Object object) 
     throws HibernateException { 
    // TODO Auto-generated method stub 
    Serializable id = session.getEntityPersister(null, object) 
      .getClassMetadata().getIdentifier(object, session); 
    return id != null ? id : super.generate(session, object); 
} 

} 

ändern Ihr Unternehmen als erstellen:

@Id 
@GeneratedValue(generator="myGenerator") 
@GenericGenerator(name="myGenerator", strategy="package.FilterIdentifierGenerator") 
@Column(unique=true, nullable=false) 
private int id; 
... 

und beim Speichern anstelle von persist()merge() oder update()

verwenden
Verwandte Themen