object faz referência a uma instância transitória não salva – salva a instância transitória antes da limpeza

Eu recebo seguinte erro quando eu salvo o object usando o Hibernate

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

Você deve include cascade="all" (se estiver usando xml) ou cascade=CascadeType.ALL (se estiver usando annotations) no mapeamento de sua coleção.

Isso acontece porque você tem uma coleção em sua entidade e essa coleção tem um ou mais itens que não estão presentes no database. Ao especificar as opções acima, você diz ao hibernate para salvá-las no database ao salvar seus pais.

Eu acredito que isso pode ser apenas repetir a resposta, mas só para esclarecer, eu tenho isso em um mapeamento @OneToOne , bem como um @OneToMany . Em ambos os casos, foi o fato de o object Child eu estava adicionando ao Parent não ter sido salvo no database ainda. Então, quando eu adicionei o Child ao Parent , em seguida, salvei o Parent , o Hibernate lançaria a mensagem "object references an unsaved transient instance - save the transient instance before flushing" ao salvar o Parent.

Adicionando a cascade = {CascadeType.ALL} na referência Parent's para o Child resolveu o problema em ambos os casos. Isso salvou a Child e o Parent .

Desculpe por quaisquer respostas repetidas, só queria esclarecer ainda mais para as pessoas.

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

Isso acontece quando se salva um object quando o Hibernate pensa que precisa salvar um object que está associado ao que você está salvando.

Eu tive esse problema e não queria salvar as alterações para o object referenciado, então eu queria que o tipo de cascata fosse NONE.

O truque é garantir que o ID e a VERSION no object referenciado sejam definidos para que o Hibernate não pense que o object referenciado é um novo object que precisa ser salvo. Isso funcionou para mim.

Examine todos os relacionamentos da class que você está salvando para calcular os objects associados (e os objects associados dos objects associados) e assegure-se de que o ID e VERSION estejam definidos em todos os objects da tree de objects.

Ou, se você quiser usar “poderes” mínimos (por exemplo, se você não quiser uma exclusão em cascata) para obter o que deseja, use

 import org.hibernate.annotations.Cascade; import org.hibernate.annotations.CascadeType; ... @Cascade({CascadeType.SAVE_UPDATE}) private Set children; 

No meu caso, foi causado por não ter CascadeType no lado CascadeType do relacionamento bidirecional. Para ser mais preciso, eu tinha o CascadeType.ALL no lado @OneToMany e não o tinha no @OneToMany . Adicionando CascadeType.ALL para CascadeType.ALL resolveu o problema. Um-para-muitos lado:

 @OneToMany(cascade = CascadeType.ALL, mappedBy="globalConfig", orphanRemoval = true) private SetgcScopeSet; 

Muitos-para-um lado (causou o problema)

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

Muitos-para-um (corrigido adicionando CascadeType.PERSIST )

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

Isso ocorreu para mim ao persistir uma entidade na qual o registro existente no database tinha um valor NULL para o campo anotado com @Version (para bloqueio otimista). A atualização do valor NULL para 0 no database corrigiu isso.

Esta não é a única razão para o erro. Eu encontrei agora apenas para um erro de digitação na minha codificação, que, creio eu, definir um valor de uma entidade que já foi salvo.

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

Eu localizei o erro encontrando exatamente qual variável causou o erro (neste caso String xid ). Eu usei uma catch em todo o bloco de código que salvou a entidade e imprimiu os rastreios.

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

Se sua coleção for anulável, tente: object.SetYouColection(null);

Não use Cascade.All até que você realmente precise. Role e a Permission têm uma relação bidirecional de manyToMany . Então o código a seguir funcionaria bem

  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 pList = new ArrayList(); pList.add(p); pList.add(p2); role.setPermissions(pList); crudRepository.save(role); 

enquanto se o object é apenas um “novo”, então ele lançaria o mesmo erro.

Para adicionar 2 centavos, recebi o mesmo problema quando acidentalmente enviei null como ID. Abaixo, o código descreve meu cenário (e o OP não mencionou nenhum cenário específico) .

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

Aqui estou definindo o ID de departamento existente para uma nova instância de funcionário sem realmente obter a entidade de departamento primeiro, pois não quero que outra consulta de seleção seja triggersda.

Em alguns cenários, o deptId PKID está vindo como null do método de chamada e estou recebendo o mesmo erro.

Então, observe null valores null para o PK ID

Eu recebo este erro quando eu uso

 getSession().save(object) 

mas funciona sem problemas quando uso

 getSession().saveOrUpdate(object) 

além de todas as outras boas respostas, isso pode acontecer se você usar a merge para persistir um object e, acidentalmente, esquecer de usar a referência mesclada do object na class pai. considere o seguinte exemplo

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

Nesse caso, você mescla A mas esquece de usar o object mesclado de A para resolver o problema, você deve rewrite o código como este.

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

Um outro motivo possível: no meu caso, eu estava tentando salvar a criança antes de salvar o pai, em uma nova entidade.

O código era algo assim em um modelo User.java:

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

O método setNewPassword () cria um registro PasswordHistory e o adiciona à coleção de histórico no User. Como a instrução create () ainda não havia sido executada para o pai, ela tentava salvar em uma coleção de uma entidade que ainda não havia sido criada. Tudo o que eu tinha que fazer para consertá-lo era mover a chamada setNewPassword () após a chamada para create ().

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

Existe outra possibilidade que pode causar esse erro no modo de hibernação. Você pode definir uma referência não salva do seu object A para uma entidade anexada B e desejar persistir o object C Mesmo neste caso, você receberá o erro acima mencionado.

Se você estiver usando o Spring Data JPA, a anotação @Transactional adicionada à sua implementação de serviço resolveria o problema.

Por uma questão de completude:

 org.hibernate.TransientPropertyValueException 

com mensagem

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

também ocorrerá quando você tentar persistir / mesclar uma entidade com uma referência a outra entidade que, por acaso, estiver desanexada .

Eu também enfrentei a mesma situação. Ao definir a anotação seguinte acima, a propriedade fez com que resolvesse a exceção solicitada.

A exceção que enfrentei.

 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 

Para superar, a anotação que usei.

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

O que fez o Hibernate lançar a exceção:

Essa exceção é lançada no seu console porque o object filho que eu append ao object pai não está presente no database naquele momento.

Ao fornecer @OneToMany(cascade = {CascadeType.ALL}) , ele diz ao Hibernate para salvá-los no database enquanto salva o object pai.

A maneira simples de resolver esse problema é salvar a entidade de ambos. primeiro salve a entidade filho e salve a entidade pai. Porque uma entidade pai é depende da entidade de criança para o valor de chave estrangeiro.

Abaixo simples exame de um para um relacionamento

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

Uma causa possível do erro é a inexistência da configuração do valor da entidade pai; por exemplo, para um relacionamento departamento-funcionários, você deve escrever isso para corrigir o erro:

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

Existem tantas possibilidades desse erro que outras possibilidades também estão em adicionar página ou editar página. No meu caso eu estava tentando salvar um object AdvanceSalary. O problema é que, em edição, o AdvanceSalary employee.employee_id é null. Porque, na edição, eu não estava definido como employee.employee_id. Eu fiz um campo oculto e o configurei. meu código funcionando perfeitamente bem.

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

Enfrentei essa exceção quando não mantive o object pai, mas estava salvando o filho. Para resolver o problema, na mesma session, persisti os objects filho e pai e usei o CascadeType.ALL no pai.

Eu acho que é porque você tentou persistir um object que tem uma referência a outro object que não é ainda persistir, e por isso tente no “lado do database” para colocar uma referência a uma linha que não existe

Caso 1: Eu estava recebendo essa exceção quando estava tentando criar um pai e salvando essa referência pai para seu filho e, em seguida, alguma outra consulta DELETE / UPDATE (JPQL). Então eu apenas libero () a entidade recém-criada depois de criar pai e depois de criar filho usando a mesma referência pai. Isso funcionou para mim.

Caso 2:

Classe dos pais

 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; . . . } 

Classe Infantil:

 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; . . } 

No caso acima, onde pai (referência) e filho (ReferenceAdditionalDetails) com relação OneToOne e quando você tenta criar entidade de referência e, em seguida, seu filho (ReferenceAdditionalDetails), ele lhe dará a mesma exceção. Portanto, para evitar a exceção, você precisa definir nulo para a class filho e, em seguida, criar o pai.

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