java - portugues - resolva os problemas




objeto referencia uma instância transiente não salva-salve a instância transiente antes de liberar (16)

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

Recebo o seguinte erro ao salvar o objeto usando o Hibernate

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

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

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.


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

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

Eu recebo este erro quando eu uso

getSession().save(object)

mas funciona sem problemas quando uso

getSession().saveOrUpdate(object) 

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.


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

    }

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.


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;

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


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


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


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

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.