2

I searched the internet, tried many methods but I still have a problem during the removal.Please give me any directions because I want to understand what I'm doing wrong.

I have several entities but in brief:

public class PetOwner extends User {
    private String address;
    private String telefon;

    @OneToMany(cascade={CascadeType.REMOVE})
    private List<Appointment> appointments;
}


public class Appointment {
    @Id
    @GeneratedValue
    private long id;

    @ManyToOne(cascade={CascadeType.PERSIST})
    @JoinColumn(name = "owner_id")
    private PetOwner petOwner;
}

When i try delete the Appointment with this method(JpaRepository)

@Transactional
    public void delete(Appointment appointment){
        appointmentRepository.delete(appointment);
    }

Spring throws a exception:

MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails

Only way is set in Appointment.class

@ManyToOne(cascade={CascadeType.ALL})
    @JoinColumn(name = "owner_id")
    private PetOwner petOwner;

But then in addition to the meeting also removes PetOwner. Please for directions on how to handle.

Adamo
  • 586
  • 1
  • 9
  • 28

2 Answers2

1

First of all you should only cascade on @OneToMany. Secondly the error appears to be from the DB, not from JPA. Your foreign key appears to be set up wrong.

Refer to this answer for FK: FK restriction

The proper way to set up what you are trying to do is :

 @OneToMany(cascade={CascadeType.DELETE},mappedBy = "petOwner")
 private List<Appointment> appointments;

and

@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name = "owner_id")
private PetOwner petOwner;
Community
  • 1
  • 1
alambrache
  • 108
  • 1
  • 9
1

Without entering in the debate about creating a hierarchy to reflect properties (not nature), you can use two approaches here.

First, you can write your relationships better. I don't know what's your JPA implementation of choice, but sometimes they mess the tables creating unnecessary linked tables. So, better safe than sorry:

On PetOwner, use:

@OneToMany(cascade={CascadeType.REMOVE}, mappedBy="petOwner")
private List<Appointment> appointments;

Second approach is to make explicit your owner does not have the appointment prior the removal, so:

@Transactional
public void delete(Appointment appointment){
    appointment.getPetOwner().getAppointments().remove(appointment);
    appointmentRepository.delete(appointment);
}

This one is really bad because you can have a huge performance problem when an owner have to much appointments.

Paulo Araújo
  • 539
  • 3
  • 12