911 Stimmen

Behebung des Hibernate-Fehlers "Objekt verweist auf eine nicht gespeicherte transiente Instanz - speichern Sie die transiente Instanz vor dem Flushen".

Ich erhalte folgenden Fehler, wenn ich das Objekt mit Hibernate speichere

object references an unsaved transient instance - save the transient instance before flushing

1122voto

Bozho Punkte 570413

Sie sollten enthalten cascade="all" (bei Verwendung von xml) oder cascade=CascadeType.ALL (bei Verwendung von Anmerkungen) auf Ihrer Sammlungszuordnung.

Dies geschieht, weil Sie eine Sammlung in Ihrer Entität haben und diese Sammlung ein oder mehrere Elemente enthält, die nicht in der Datenbank vorhanden sind. Durch die Angabe der oben genannten Optionen weisen Sie Hibernate an, diese Elemente in der Datenbank zu speichern, wenn Sie die übergeordneten Elemente speichern.

372voto

McDonald Noland Punkte 3339

Ich glaube, dies könnte nur eine Wiederholung der Antwort sein, aber nur um das klarzustellen, ich habe das auf einem @OneToOne Mapping sowie eine @OneToMany . In beiden Fällen war es die Tatsache, dass die Child Objekt, das ich dem Parent wurde noch nicht in der Datenbank gespeichert. Als ich also die Child zum Parent und speicherte dann die Parent würde Hibernate die "object references an unsaved transient instance - save the transient instance before flushing" Meldung beim Speichern des Elternteils.

Die Hinzufügung der cascade = {CascadeType.ALL} über die Parent's Bezugnahme auf den Child löste das Problem in beiden Fällen. Dies rettete die Child und die Parent .

Entschuldigen Sie bitte die wiederholten Antworten, ich wollte nur noch mehr Klarheit für die Leute schaffen.

@OneToOne(cascade = {CascadeType.ALL})
@JoinColumn(name = "performancelog_id")
public PerformanceLog getPerformanceLog() {
    return performanceLog;
}

210voto

Vlad Mihalcea Punkte 121171

Einführung

Bei der Verwendung von JPA und Hibernate kann sich eine Entität in einem der folgenden 4 Zustände befinden:

  • Neu - Ein neu erstelltes Objekt, das noch nie mit einer Hibernate-Sitzung (auch Persistenzkontext genannt) verknüpft war und keiner Datenbanktabellenzeile zugeordnet ist, befindet sich im Zustand "Neu" oder "Transient".

Um persistent zu werden, müssen wir entweder explizit die persist Methode oder verwenden Sie den transitiven Persistenzmechanismus.

  • Persistent - Eine persistente Entität wurde mit einer Datenbanktabellenzeile verknüpft und wird durch den aktuell laufenden Persistenzkontext verwaltet.

Jede Änderung, die an einer solchen Entität vorgenommen wird, wird erkannt und an die Datenbank weitergegeben (während der Session-Flush-Zeit).

  • Freistehend - Sobald der aktuell laufende Persistenzkontext geschlossen wird, werden alle zuvor verwalteten Entitäten abgetrennt. Aufeinanderfolgende Änderungen werden nicht mehr verfolgt und es findet keine automatische Datenbanksynchronisation statt.

  • Entfernt - Obwohl JPA verlangt, dass nur verwaltete Entitäten entfernt werden dürfen, kann Hibernate auch losgelöste Entitäten löschen (aber nur durch eine remove Methodenaufruf).

Zustandsübergänge von Entitäten

Um eine Entität von einem Zustand in einen anderen zu verschieben, können Sie die persist , remove ou merge Methoden.

JPA entity states

Behebung des Problems

Das Problem, das Sie in Ihrer Frage beschreiben:

object references an unsaved transient instance - save the transient instance before flushing

wird durch die Assoziation einer Entität mit dem Zustand der Neu an eine Einrichtung, die sich im Zustand der Verwaltet .

Dies kann passieren, wenn Sie eine untergeordnete Entität mit einer One-to-Many-Sammlung in der übergeordneten Entität verknüpfen und die Sammlung nicht cascade die Zustandsübergänge der Entitäten.

Sie können dieses Problem beheben, indem Sie der Entitätszuordnung, die diesen Fehler ausgelöst hat, wie folgt eine Kaskade hinzufügen:

Le site @OneToOne Verein

@OneToOne(
    mappedBy = "post",
    orphanRemoval = true,
    cascade = CascadeType.ALL)
private PostDetails details;

Beachten Sie die CascadeType.ALL Wert, den wir für die cascade Attribut.

Le site @OneToMany Verein

@OneToMany(
    mappedBy = "post", 
    orphanRemoval = true,
    cascade = CascadeType.ALL)
private List<Comment> comments = new ArrayList<>();

Auch hier gilt, dass die CascadeType.ALL ist geeignet für die bidirektionale @OneToMany Vereinigungen.

Damit die Kaskade in einem bidirektionalen System richtig funktioniert, müssen Sie auch sicherstellen, dass die über- und untergeordneten Assoziationen synchronisiert sind.

Le site @ManyToMany Verein

@ManyToMany(
    mappedBy = "authors",
    cascade = {
        CascadeType.PERSIST, 
        CascadeType.MERGE
    }
)
private List<Book> books = new ArrayList<>();

In einem @ManyToMany Assoziation, können Sie nicht verwenden CascadeType.ALL ou orphanRemoval da dadurch der Zustandsübergang "Entität löschen" von einer übergeordneten Entität auf eine andere übergeordnete Entität übertragen wird.

Daher ist für @ManyToMany Assoziationen, kaskadieren Sie normalerweise die CascadeType.PERSIST ou CascadeType.MERGE Operationen. Alternativ können Sie das auch erweitern auf DETACH ou REFRESH .

88voto

Cookalino Punkte 1469

Dies geschieht beim Speichern eines Objekts, wenn Hibernate denkt, dass es ein Objekt speichern muss, das mit dem zu speichernden Objekt verbunden ist.

Ich hatte dieses Problem und wollte keine Änderungen an dem referenzierten Objekt speichern, also wollte ich, dass der Kaskadentyp NONE ist.

Der Trick besteht darin, sicherzustellen, dass die ID und VERSION im referenzierten Objekt gesetzt sind, damit Hibernate nicht denkt, dass das referenzierte Objekt ein neues Objekt ist, das gespeichert werden muss. Das hat bei mir funktioniert.

Gehen Sie alle Beziehungen in der zu speichernden Klasse durch, um die zugehörigen Objekte (und die zugehörigen Objekte der zugehörigen Objekte) zu ermitteln, und stellen Sie sicher, dass die ID und VERSION in allen Objekten des Objektbaums gesetzt sind.

34voto

allap Punkte 599

In meinem Fall wurde es dadurch verursacht, dass ich keine CascadeType über die @ManyToOne Seite der bidirektionalen Beziehung. Um genauer zu sein, hatte ich CascadeType.ALL auf @OneToMany Seite und hatte sie nicht an @ManyToOne . Hinzufügen von CascadeType.ALL まで @ManyToOne das Problem behoben. Eins-zu-viele Seite:

@OneToMany(cascade = CascadeType.ALL, mappedBy="globalConfig", orphanRemoval = true)
private Set<GlobalConfigScope>gcScopeSet;

Viele-zu-eins-Seite (verursachte das Problem)

@ManyToOne
@JoinColumn(name="global_config_id")
private GlobalConfig globalConfig;

Viele-zu-eins (behoben durch Hinzufügen von CascadeType.PERSIST )

@ManyToOne(cascade = CascadeType.PERSIST)
@JoinColumn(name="global_config_id")
private GlobalConfig globalConfig;

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X