it-swarm.com.de

objekt verweist auf eine nicht gespeicherte transiente Instanz - Speichern Sie die transiente Instanz vor dem Leeren

Ich erhalte folgende Fehlermeldung, wenn ich das Objekt mit Ruhezustand speichere 

object references an unsaved transient instance - save the transient instance before flushing
466
Tushar Ahirrao

Sie sollten cascade="all" (bei Verwendung von xml) oder cascade=CascadeType.ALL (bei Verwendung von Anmerkungen) in Ihre Sammlungszuordnung aufnehmen.

Dies geschieht, weil Sie eine Sammlung in Ihrer Entität haben und diese Sammlung über ein oder mehrere Elemente verfügt, die nicht in der Datenbank vorhanden sind. Durch Angabe der oben genannten Optionen weisen Sie den Ruhezustand an, diese beim Speichern der übergeordneten Datenbank in der Datenbank zu speichern.

635
Bozho

Ich glaube, dass dies nur eine wiederholte Antwort sein kann, aber um es klar zu stellen, habe ich dies sowohl auf ein @OneToOne-Mapping als auch auf einen @OneToMany bekommen. In beiden Fällen war es die Tatsache, dass das Child-Objekt, das ich zum Parent-Objekt hinzufügte, noch nicht in der Datenbank gespeichert wurde. Wenn ich also Child zum Parent hinzufügte und dann das Parent speicherte, würde Hibernate beim Speichern des übergeordneten Elements die "object references an unsaved transient instance - save the transient instance before flushing"-Nachricht senden.

Durch Hinzufügen von cascade = {CascadeType.ALL} in der Parent's-Referenz zu Child wurde das Problem in beiden Fällen gelöst. Dadurch wurden die Child und die Parent gespeichert.

Sorry für alle wiederholten Antworten, wollte nur für die Leute weiter klären.

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

Dies geschieht, wenn ein Objekt gespeichert wird, wenn der Ruhezustand der Meinung ist, dass ein Objekt gespeichert werden muss, das mit dem zu speichernden Objekt verknüpft ist. 

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

Der Trick besteht darin, sicherzustellen, dass ID und VERSION im referenzierten Objekt festgelegt sind, sodass Hibernate nicht der Meinung ist, dass das referenzierte Objekt ein neues Objekt ist, das gespeichert werden muss. Das hat bei mir funktioniert.

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

50
Cookalino

Wenn Sie minimale "Kräfte" verwenden möchten (z. B. wenn Sie keine Kaskade löschen möchten), um das zu erreichen, was Sie möchten, verwenden Sie 

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;

...

@Cascade({CascadeType.SAVE_UPDATE})
private Set<Child> children;
24

In meinem Fall wurde dies durch CascadeType auf der @ManyToOne-Seite der bidirektionalen Beziehung verursacht. Genauer gesagt hatte ich CascadeType.ALL auf @OneToMany und hatte es nicht auf @ManyToOne. Durch Hinzufügen von CascadeType.ALL zu @ManyToOne wurde das Problem behoben . One-to-Many side:

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

Many-to-one (behoben durch Hinzufügen von CascadeType.PERSIST)

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

Dies trat für mich auf, wenn eine Entität beibehalten wurde, bei der der vorhandene Datensatz in der Datenbank einen NULL-Wert für das mit @Version (für optimistische Sperren) kommentierte Feld aufwies. Das Aktualisieren des NULL-Werts auf 0 in der Datenbank korrigierte dies.

14
dukethrash

Dies ist nicht der einzige Grund für den Fehler. Ich traf es gerade für einen Tippfehler in meiner Codierung, der, wie ich glaube, einen Wert einer bereits gespeicherten Entität festlegt.

X x2 = new X();
x.setXid(memberid); // Error happened here - x was a previous global entity I created earlier
Y.setX(x2);

Ich habe den Fehler entdeckt, indem ich genau herausgefunden habe, welche Variable den Fehler verursacht hat (in diesem Fall String xid). Ich habe eine catch für den gesamten Codeblock verwendet, der die Entität gespeichert und die Spuren gedruckt hat.

{
   code block that performed the operation
} catch (Exception e) {
   e.printStackTrace(); // put a break-point here and inspect the 'e'
   return ERROR;
}
10
nanospeck

Wenn Ihre Sammlung nullfähig ist, probieren Sie es einfach aus: object.SetYouColection(null);

6
Joabe Lucena

Verwenden Sie nicht Cascade.All, bis Sie wirklich müssen. Role und Permission haben eine bidirektionale manyToMany-Beziehung. Dann würde der folgende Code gut funktionieren 

    Permission p = new Permission();
    p.setName("help");
    Permission p2 = new Permission();
    p2.setName("self_info");
    p = (Permission)crudRepository.save(p); // returned p has id filled in.
    p2 = (Permission)crudRepository.save(p2); // so does p2.
    Role role = new Role();
    role.setAvailable(true);
    role.setDescription("a test role");
    role.setRole("admin");
    List<Permission> pList = new ArrayList<Permission>();
    pList.add(p);
    pList.add(p2);
    role.setPermissions(pList);
    crudRepository.save(role);

wenn es sich bei dem Objekt jedoch nur um ein "neues" Objekt handelt, wird der gleiche Fehler ausgegeben.

5
Tiina

Um meine 2 Cent hinzuzufügen, habe ich dasselbe Problem, wenn ich versehentlich null als ID sende. Der folgende Code zeigt mein Szenario (und OP hat kein bestimmtes Szenario erwähnt).

Employee emp = new Employee();
emp.setDept(new Dept(deptId)); // --> when deptId PKID is null, same error will be thrown
// calls to other setters...
em.persist(emp);

Hier setze ich die vorhandene Abteilungs-ID auf eine neue Mitarbeiterinstanz, ohne zuerst die Abteilungsentität zu erhalten, da ich nicht möchte, dass eine andere Auswahlabfrage ausgelöst wird.

In einigen Szenarien kommt deptId PKID als null von der aufrufenden Methode und ich bekomme den gleichen Fehler. 

Achten Sie also auf null-Werte für PK-ID

4
manikanta

ich erhalte diesen Fehler, wenn ich benutze 

getSession().save(object)

aber es funktioniert problemlos, wenn ich benutze 

getSession().saveOrUpdate(object) 
3
acpuma

dies kann neben allen anderen guten Antworten passieren, wenn Sie merge verwenden, um ein Objekt zu persistieren und versehentlich vergessen, die zusammengeführte Referenz des Objekts in der übergeordneten Klasse zu verwenden. Betrachten Sie das folgende Beispiel

merge(A);
B.setA(A);
persist(B);

In diesem Fall führen Sie A zusammen. Vergessen Sie jedoch nicht, das zusammengeführte Objekt von A zu verwenden. Um das Problem zu lösen, müssen Sie den Code so umschreiben.

A=merge(A);//difference is here
B.setA(A);
persist(B);
3
Hossein Nasr

Der Vollständigkeit halber: A

org.hibernate.TransientPropertyValueException 

mit der Nachricht

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

tritt auch auf, wenn Sie versuchen, eine Entität mit einer Referenz auf eine andere Entität, die zufällig detached ist, persistieren/zusammenführen.

1
Ralf

Wenn Sie Spring Data JPA verwenden, kann das Problem durch die Hinzufügung der @Transactional-Anmerkung zu Ihrer Service-Implementierung behoben werden.

1
Anony

Ein anderer möglicher Grund: In meinem Fall habe ich versucht, das Kind zu retten, bevor ich das übergeordnete Element auf einer brandneuen Entität retten konnte.

Der Code war in einem User.Java-Modell so ähnlich:

this.lastName = lastName;
this.isAdmin = isAdmin;
this.accountStatus = "Active";
this.setNewPassword(password);
this.timeJoin = new Date();
create();

Die setNewPassword () -Methode erstellt einen PasswordHistory-Datensatz und fügt ihn der Verlaufssammlung in User hinzu. Da die create () - Anweisung noch nicht für das übergeordnete Element ausgeführt wurde, wurde versucht, sie in einer Sammlung einer Entität zu speichern, die noch nicht erstellt wurde. Um das Problem zu beheben, musste ich lediglich den setNewPassword () - Aufruf nach dem Aufruf von create () verschieben.

this.lastName = lastName;
this.isAdmin = isAdmin;
this.accountStatus = "Active";
this.timeJoin = new Date();
create();
this.setNewPassword(password);
1
Jeremy Goodell

Ich war auch mit der gleichen Situation konfrontiert. Durch Festlegen der folgenden Anmerkung oberhalb der Eigenschaft löste sie die angeforderte Ausnahme.

Die Ausnahme, der ich begegnet bin.

Exception in thread "main" Java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.model.Car_OneToMany

Zu überwinden, die Anmerkung, die ich verwendet habe.

    @OneToMany(cascade = {CascadeType.ALL})
    @Column(name = "ListOfCarsDrivenByDriver")
    private List<Car_OneToMany> listOfCarsBeingDriven = new ArrayList<Car_OneToMany>();

Was hat Hibernate dazu gebracht, die Ausnahme zu werfen:

Diese Ausnahme wird an Ihrer Konsole ausgelöst, da das untergeordnete Objekt, das ich an das übergeordnete Objekt anhebe, zu diesem Zeitpunkt nicht in der Datenbank vorhanden ist.

Durch die Bereitstellung von @OneToMany(cascade = {CascadeType.ALL}) wird Hibernate angewiesen, sie in der Datenbank zu speichern, während das übergeordnete Objekt gespeichert wird. 

1
Dulith De Costa

Es gibt eine andere Möglichkeit, die diesen Fehler im Ruhezustand verursachen kann. Sie können eine nicht gespeicherte Referenz Ihres Objekts A auf eine verbundene Entität B setzen und das Objekt C beibehalten. Auch in diesem Fall erhalten Sie den oben genannten Fehler.

1
Hossein Nasr

Ich denke, weil Sie versucht haben, ein Objekt zu persistieren, das einen Verweis auf ein anderes Objekt hat, das noch nicht persistent ist, und deshalb versuchen Sie, auf der "DB-Seite" einen Verweis auf eine Zeile zu setzen, die nicht existiert

0
CrisMon_01

Fall 1: Ich erhielt diese Ausnahme, als ich versuchte, ein übergeordnetes Objekt zu erstellen, und diesen übergeordneten Verweis auf das untergeordnete Objekt und dann eine andere DELETE/UPDATE-Abfrage (JPQL) zu speichern. Also spüle ich die neu erstellte Entität nach dem Erstellen des übergeordneten Elements und nach dem Erstellen des untergeordneten Elements mit demselben übergeordneten Verweis auf. Es hat für mich funktioniert.

Fall 2: 

Elternklasse

public class Reference implements Serializable {

    @Id
    @Column(precision=20, scale=0)
    private BigInteger id;

    @Temporal(TemporalType.TIMESTAMP)
    private Date modifiedOn;

    @OneToOne(mappedBy="reference")
    private ReferenceAdditionalDetails refAddDetails;
    . 
    .
    .
}

Kinderklasse:

public class ReferenceAdditionalDetails implements Serializable{

    private static final long serialVersionUID = 1L;

    @Id
    @OneToOne
    @JoinColumn(name="reference",referencedColumnName="id")
    private Reference reference;

    private String preferedSector1;
    private String preferedSector2;
    .
    .

}

In dem obigen Fall, in dem übergeordnetes (Referenz) und untergeordnetes (ReferenceAdditionalDetails) OneToOne-Beziehung bestehen und wenn Sie versuchen, eine Referenzentität und dann das untergeordnete Element (ReferenceAdditionalDetails) zu erstellen, erhalten Sie dieselbe Ausnahme. Um die Ausnahme zu vermeiden, müssen Sie für die untergeordnete Klasse NULL setzen und dann die übergeordnete Klasse erstellen. (Beispielcode)

.
.
reference.setRefAddDetails(null);
reference = referenceDao.create(reference);
entityManager.flush();
.
.

Sie können dieses Problem auf einfache Weise lösen, indem Sie beide Entitäten speichern. Zuerst die untergeordnete Entität und dann die übergeordnete Entität abspeichern. Da die übergeordnete Entität für den Fremdschlüsselwert von der untergeordneten Entität abhängig ist.

Nachfolgend einfache Prüfung einer Eins-zu-Eins-Beziehung

insert into Department (name, numOfemp, Depno) values (?, ?, ?)
Hibernate: insert into Employee (SSN, dep_Depno, firstName, lastName, middleName, empno) values (?, ?, ?, ?, ?, ?)

Session session=sf.openSession();
        session.beginTransaction();
        session.save(dep);
        session.save(emp);
0
shashigura

Es gibt so viele Möglichkeiten dieses Fehlers, einige andere Möglichkeiten gibt es auch auf Seite hinzufügen oder Seite bearbeiten. In meinem Fall habe ich versucht, ein Objekt AdvanceSalary zu speichern. Das Problem ist, dass AdvanceSalary employee.employee_id bei der Bearbeitung null ist, da bei der Bearbeitung die employee.employee_id nicht festgelegt wurde. Ich habe ein verstecktes Feld erstellt und gesetzt. Mein Code funktioniert absolut gut.

    @Entity(name = "ic_advance_salary")
    @Table(name = "ic_advance_salary")
    public class AdvanceSalary extends BaseDO{

        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "id")
        private Integer id;

        @ManyToOne(fetch = FetchType.EAGER)
        @JoinColumn(name = "employee_id", nullable = false)
        private Employee employee;

        @Column(name = "employee_id", insertable=false, updatable=false)
        @NotNull(message="Please enter employee Id")
        private Long employee_id;

        @Column(name = "advance_date")
        @DateTimeFormat(pattern = "dd-MMM-yyyy")
        @NotNull(message="Please enter advance date")
        private Date advance_date;

        @Column(name = "amount")
        @NotNull(message="Please enter Paid Amount")
        private Double amount;

        @Column(name = "cheque_date")
        @DateTimeFormat(pattern = "dd-MMM-yyyy")
        private Date cheque_date;

        @Column(name = "cheque_no")
        private String cheque_no;

        @Column(name = "remarks")
        private String remarks;

        public AdvanceSalary() {
        }

        public AdvanceSalary(Integer advance_salary_id) {
            this.id = advance_salary_id;
        }

        public Integer getId() {
            return id;
        }

        public void setId(Integer id) {
            this.id = id;
        }

        public Employee getEmployee() {
            return employee;
        }

        public void setEmployee(Employee employee) {
            this.employee = employee;
        }


        public Long getEmployee_id() {
            return employee_id;
        }

        public void setEmployee_id(Long employee_id) {
            this.employee_id = employee_id;
        }

    }
0
Ravindra

Eine mögliche Fehlerursache ist das Fehlen der Einstellung des Wertes der übergeordneten Entität. Für eine Abteilung-Mitarbeiter-Beziehung müssen Sie beispielsweise Folgendes schreiben, um den Fehler zu beheben:

Department dept = (Department)session.load(Department.class, dept_code); // dept_code is from the jsp form which you get in the controller with @RequestParam String department
employee.setDepartment(dept);
0
pheromix

Ich war mit dieser Ausnahme konfrontiert, als ich das übergeordnete Objekt nicht beharrte, aber das Kind rettete. Um das Problem zu beheben, behielt ich in derselben Sitzung sowohl das untergeordnete als auch das übergeordnete Objekt bei und verwendete CascadeType.ALL für das übergeordnete Objekt. 

0
tadtab

Dieses Problem ist mir passiert, als ich eine neue Entität und eine zugehörige Entität in einer als @Transactional markierten Methode erstellt und dann vor dem Speichern eine Abfrage ausgeführt habe. Ex

@Transactional
public someService() {
    Entity someEntity = new Entity();
    AssocaiatedEntity associatedEntity = new AssocaitedEntity();
    someEntity.setAssociatedEntity(associatedEntity);
    associatedEntity.setEntity(someEntity);

    // Performing any query was causing hibernate to attempt to persist the new entity. It would then throw an exception
    someDao.getSomething();

    entityDao.create(someEntity);
}

Um das Problem zu beheben, habe ich die Abfrage ausgeführt, bevor ich die neue Entität erstellt habe. 

0
mad_fox