Ich erhalte folgende Fehlermeldung, wenn ich das Objekt mit Ruhezustand speichere
object references an unsaved transient instance - save the transient instance before flushing
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.
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;
}
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.
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;
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;
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.
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;
}
Wenn Ihre Sammlung nullfähig ist, probieren Sie es einfach aus: object.SetYouColection(null);
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.
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
ich erhalte diesen Fehler, wenn ich benutze
getSession().save(object)
aber es funktioniert problemlos, wenn ich benutze
getSession().saveOrUpdate(object)
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);
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.
Wenn Sie Spring Data JPA verwenden, kann das Problem durch die Hinzufügung der @Transactional
-Anmerkung zu Ihrer Service-Implementierung behoben werden.
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);
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.
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.
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
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);
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;
}
}
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);
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.
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.