How to fix the Hibernate “object references an unsaved transient instance - save the transient instance before flushing” error

前端 未结 30 1087
既然无缘
既然无缘 2020-11-22 07:11

I receive following error when I save the object using Hibernate

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


        
相关标签:
30条回答
  • 2020-11-22 07:17

    Don't use Cascade.All until you really have to. Role and Permission have bidirectional manyToMany relation. Then the following code would work fine

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

    while if the object is just a "new" one, then it would throw the same error.

    0 讨论(0)
  • 2020-11-22 07:17

    For the sake of completeness: A

    org.hibernate.TransientPropertyValueException 
    

    with message

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

    will also occur when you try to persist / merge an entity with a reference to another entity which happens to be detached.

    0 讨论(0)
  • 2020-11-22 07:17

    Simple way of solving this issue is save the both entity. first save the child entity and then save the parent entity. Because parent entity is depend on child entity for the foreign key value.

    Below simple exam of one to one relationship

    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 讨论(0)
  • 2020-11-22 07:18

    In my case it was caused by not having CascadeType on the @ManyToOne side of the bidirectional relationship. To be more precise, I had CascadeType.ALL on @OneToMany side and did not have it on @ManyToOne. Adding CascadeType.ALL to @ManyToOne resolved the issue. One-to-many side:

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

    Many-to-one side (caused the problem)

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

    Many-to-one (fixed by adding CascadeType.PERSIST)

    @ManyToOne(cascade = CascadeType.PERSIST)
    @JoinColumn(name="global_config_id")
    private GlobalConfig globalConfig;
    
    0 讨论(0)
  • 2020-11-22 07:19

    There are so many possibilities of this error some other possibilities are also on add page or edit page. In my case I was trying to save a object AdvanceSalary. The problem is that in edit the AdvanceSalary employee.employee_id is null Because on edit I was not set the employee.employee_id. I have make a hidden field and set it. my code working absolutely fine.

        @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 讨论(0)
  • 2020-11-22 07:19

    In my case using Cascade.ALL was adding unnecessary entry to the table, which already had same object (Generating a child value without an id does just that). So I would have to work around with getting child object from repository first, and setting it into the main object instead of the one causing the issue.

    Student s = studentRepo.findByName(generatedObject.getStudent().getName())
    generatedObject.student(s);   
    
    0 讨论(0)
提交回复
热议问题