java resolva objeto referencia uma instância transiente não salva-salve a instância transiente antes de liberar




resolva os problemas (20)

Recebo o seguinte erro ao salvar o objeto usando o Hibernate

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

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

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

Eu recebo este erro quando eu uso

getSession().save(object)

mas funciona sem problemas quando uso

getSession().saveOrUpdate(object) 

Uma causa possível do erro é a inexistência da configuração do valor da entidade pai; por exemplo, para um relacionamento entre departamentos e funcionários, é necessário 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);

Eu acho que é porque você tentou persistir um objeto que tem uma referência a outro objeto que não é persistir ainda, e por isso tente no "lado do banco de dados" para colocar uma referência a uma linha que não existe


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 traços.

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

Você deve incluir cascade="all" (se usar xml) ou cascade=CascadeType.ALL (se estiver usando anotações) 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 banco de dados. Ao especificar as opções acima, você diz ao hibernate para salvá-las no banco de dados ao salvar seus pais.


Caso 1: Eu estava recebendo essa exceção quando eu 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 classe filho e, em seguida, criar o pai (código de exemplo).

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

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 configurando o ID de departamento existente para uma nova instância de funcionário sem obter primeiro a entidade de departamento, pois não quero que outra consulta de seleção seja disparada.

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


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


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


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

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

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

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


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


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 objeto Child eu estava adicionando ao Parent não ter sido salvo no banco de dados ainda. Então, quando 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;
}

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


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 objeto AdvanceSalary. O problema é que na edição do AdvanceSalary employee.employee_id é null porque na edição eu não estava definido o 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;
        }

    }

Não use Cascade.All até que você realmente precise. Role e Permission têm relação bidirecional 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<Permission> pList = new ArrayList<Permission>();
    pList.add(p);
    pList.add(p2);
    role.setPermissions(pList);
    crudRepository.save(role);

enquanto se o objeto é apenas um "novo", então ele lançaria o mesmo erro.


Ou, se você quiser usar "poderes" mínimos (por exemplo, se 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<Child> 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 a CascadeType.ALL resolveu o problema. Um-para-muitos lado:

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

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;

Esse problema aconteceu comigo quando criei uma nova entidade e uma entidade associada em um método marcado como @Transactional , em seguida, @Transactional uma consulta antes de salvar. 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);
}

Para corrigir, executei a consulta antes de criar a nova entidade.


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 estrangeira.

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