2012-10-05 12 views
5

Ich habe ein neues Objekt. Ich möchte id wissen, bevor Sie es speichern. Ist es möglich? Oder gibt es einen anderen Weg dafür? Ich verwende jpa als orm und Oracle als Datenbank.Wie kann ich ID vor dem Speichern eines Objekts in jpa

@Id 
@Basic(optional = false) 
@Column(name = "ID", nullable = false) 
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "woTypeSeq") 
private Long id; 

Ich habe ein Code-Feld in meiner Entität. Wenn der Benutzer keinen Wert für das Feld code eingibt, möchte ich Code als Entitäts-ID festlegen. Wenn ich eine Entität persistiere, kann ich natürlich eine ID erhalten und den Code-Wert als ID setzen, aber dies ist eine zusätzliche Abfrage-Datenbank.

Ich mag wie die

if(entity.getCode()==null) { 
    entity.setCode(entity.getId); 
    jpaDao.saveOrUpdate(entity); 
} 
+1

Sie konnten die @GeneratedValue vermeiden, verwenden Sie den Generator selbst den Wert zu erhalten und es zu Einheit auf „manuell“ – SJuan76

+0

ich nicht Ich möchte es manuell auf entity setzen. Wenn ich den nächsten Wert für id von oracle bekomme und es auf die ID der neuen Entity setze, ist das rational? – mstzn

Antwort

5

Nach langen Nachforschungen anstellen über Dies, endlich habe ich eine Lösung gefunden.

In der Tat, wenn Sie Sequenzgenerator in JPA verwenden, sicher können Sie nicht Unternehmens-ID erhalten, bevor sie in der Datenbank zu speichern, weil neben id wird von Datenbank-Sequenz zugeordnet werden.

Es gibt einen Weg, um die ID zu erhalten, wenn Sie einen benutzerdefinierten Generator verwenden, können Sie die ID erhalten vor dem Speichern.Hier ist eine einfache Implementierung:

public class CustomGenerator extends IdentityGenerator implements Configurable { 

    private IdentifierGenerator defaultGenerator; 

    public Serializable generate(SessionImplementor session, Object object) throws HibernateException { 
     Long idValue = (Long)defaultGenerator.generate(session, object); 
     //idValue will be assigned your entity id 
     return idValue; 
    } 

    @Override 
    public void configure(Type type, Properties params, Dialect d) throws MappingException { 
     DefaultIdentifierGeneratorFactory dd = new DefaultIdentifierGeneratorFactory(); 
     dd.setDialect(d); 
     defaultGenerator = dd.createIdentifierGenerator("sequence", type, params); 
    } 
} 

Mit CustomGenerator für id-Feld:

@Id 
@Basic(optional = false) 
@Column(name = "ID", nullable = false) 
@GenericGenerator(name = "seq_id", strategy = "com.yoncabt.abys.core.listener.CustomGenerator", parameters = { @Parameter(name = "sequence", value = "II_FIRM_DOC_PRM_SEQ") }) 
@GeneratedValue(generator = "seq_id") 
private Long id; 
8

wissen, können Sie diesen Wert nicht im Voraus mit einem @GeneratedValue Typ-ID, etwas zu tun (bevor es tatsächlich zu schreiben). Sobald Sie jedoch Ihr Bean beibehalten, wird das ID-Feld in dieser Bean-Instanz gefüllt und Sie können es erhalten, ohne eine zusätzliche Abfrage dafür durchführen zu müssen. Mit anderen Worten:

MyEntiry myEnt = new MyEntity(); //the id field is null now 
entityManager.persist(myEnt);//the id field is populated in myEnt now 
Long id = myEnt.getId(); 

Auch je nachdem, wie Ihre EntityManager konfiguriert ist, müssen Sie möglicherweise auch zuerst die Transaktion (manuell) begehen, bevor Sie diese ID bekommen.

-Update per Kommentar

Wenn Sie etwas an die Einheit abzufangen und zu tun, bevor es gespeichert wird und/oder aktualisiert werden, können Sie JPA LifeCycle Hörer verwenden (wenn Sie JPA Version 2 verwenden): Handling JPA lifecycle event using listeners and callbacks .

Grundsätzlich können Sie eine validate() Methode in Ihrem Bean machen, mit Anmerkungen versehen es mit @PrePersist und @PreUpdate und die Validierung in es tun (wenn Code es leere Menge ist zu ids Wert)

Update per 2. Kommentar

Ja, ich habe ehrlich gesagt gerade jetzt daran gedacht: Wenn die ID automatisch generiert wird, könnte sie nach dem Pre-Persist-Ereignis gefüllt werden, so dass Sie, wenn Ihr Pre-Persist-Code ausgeführt wird, immer noch nicht wissen, was die ID ist (Sie werden vielleicht auch bemerken, dass in dem Beispiel, das Sie mit der ID verknüpfen, NICHT automatisch generiert wird, sondern manuell gesetzt wird). Was Sie in diesem Fall tun können, ist ein boolesches Feld zu Ihrer Entität hinzuzufügen (mit @Transient gekennzeichnet, so dass es nicht persistent bleibt) isCodeEmpty (das ist falsch, wenn nicht speziell initialisiert). Dann prüfen Sie in Ihrer annotierten Methode @PrePersist, ob der Wert für das Codefeld leer ist und wenn ja, setzen Sie den Boolean auf True. Dann Refactoring Sie Ihre setId(...) Methode, so dass (abgesehen von dem ID-Feld Einstellung) wird es diese boolean überprüfen, und wenn sie wahr Satz des Wert des Codefeldes zu der dem ID-Feld:

public class YourEntity { 

@Transient 
private boolean isCodeEmpty; 

public void setId(Whatever id) { 
this.id = id; 
if(isCodeEmpty) { 
    this.code = id; 
    //if necessary: 
    //this.isCodeEmpty = false; 
} 
} 

@PrePersist 
public void validate() { 
if(code == null || code.isEmpty()) { 
    isCodeEmpty = true; 
} 

} 


} 
+0

Vielen Dank für Ihre Antwort. Ich habe meine Frage aktualisiert. Können Sie das überprüfen? – mstzn

+0

Ich habe versucht, Entity Listener.but in Prepersist ID Wert ist null. Ich weiß nicht, warum es null ist. Ich implementiert wie folgt = http://www.java2s.com/Tutorial/Java/0355__JPA/EntityListenersPrePersist.htm haben Sie Vorschlag oder Idee? Vielen Dank – mstzn

+1

Ihre Idee ist hervorragend, aber nach prePersist setId() -Methode funktioniert nicht.Ich habe getan, was Sie sagen. Ich debugge es, aber setId Methode nicht ausgeführt und Code-Feld nicht festgelegt.Prepersist funktioniert. – mstzn

Verwandte Themen