springhibernatejpahibernate-mapping

How to get child entity id after saving it via parent


Searched couple of sources but did not get exact scenario. Posting only required code ... Student Entity

class Student {

    @OneToMany(mappedBy = "student", cascade = CascadeType.ALL)
    private List<Fee> feeList = new ArrayList<>();

    public void addFee(Fee fee) {
        fee.setStudent(this);
        this.feeList.add(fee);
    }

}

Fee Entity

class Fee {
    @ManyToOne
    private Student student;
}

Fetching student and adding fee to the parent entity

Student student = studentService.findByAdmissionNo(paymentDTO.getAdmissionNo());
Fee f = new Fee();
s.addFee(f);

After creating and populating objects am using jpa repository to save student(parent) entity.

//fee reference
Fee fee = new Fee(paymentDTO.getAmount(), paymentDTO.getDiscount(), dateOfPayment, paymentDTO.getTransactionID(), paymentDTO.getAcademicYear());

student.addFee(fee);
studentService.save(student);

Am able to see Student and Fee records created in DB. After the above commit, student entity got populated with the Fee reocrds for that students from DB which is expected. But the reference fee which we added to student entity before saving has not updated with Id populated as part of above commit, it still has 0(Default value). I want to fetch Fee id that is created as part of above commit. We can get the id from student entity but the catch is student entity has populate with multiple fee records of that student from DB, so do not know which records is created as part of the current transaction.

Please help.


Solution

  • Guess that you are using JpaRepository in studentService to save a student ?

    As JpaRepository will call merge() on a student instance under the cover which then cascade calling merge() on a fee instance to insert a DB record to the fee table , and the thing is

    Fee mergedFee = entityManager.merge(fee);
    

    will not update the Id of the input fee instance but only the Id of the returned fee instance will be updated .As you are now using the JpaRepository on the student instance, it will always return a student instance by design and you can never get the fee instance that is returned by merge(fee)

    It should work if you change to use the feeRepository to save the fee :

    Student student = studentService.findByAdmissionNo(xxx);
    Fee fee = new Fee();
    s.addFee(fee);
    
    feeRepository.save(fee);
    

    Or use the hibernate specific saveOrUpdate() should also work :

    Student student = studentService.findByAdmissionNo(xxx);
    Fee fee = new Fee();
    s.addFee(fee);
    
    Session session = entityManager.unwrap(Session.class);
    session.saveOrUpddate(student);
    

    Or just save the fee directly but not via the student which is the way that I prefer :

    Student student studentService.findByAdmissionNo(xxx);
    Fee fee = new Fee();
    fee.paidBy(student); //just a setter to set fee.student
    
    feeRepository.save(fee);