I have two entities for RfidTags and Persons. One RfidTag is assigned to one Person. One Person can have one RfidTag. If I delete a Person that has an RfidTag, the assigned RfidTag should not get deleted, it should remain in the database, but the value for person_id should be set to NULL. I already have my SQL like this, but it is not working:
ALTER TABLE `rfid_tags`
ADD CONSTRAINT `FK_Rfid_Tag_Person`
FOREIGN KEY (`person_id`) REFERENCES `persons`(`id`)
ON DELETE SET NULL;
And here are my entities. I have already searched a lot and tried different things like changing the CascadeTypes or adding @OnDelete(onDeleteAction=SET_NULL), but nothing is working. Either the RfidTag will also get deleted (which I do not want) or I get an error like: org.hibernate.TransientObjectException: persistent instance references an unsaved transient instance of 'PersonEntity' (save the transient instance before flushing)
@Getter
@Setter
@Entity
@Table(name = "persons")
public class PersonEntity {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private String id;
@Column(nullable = false)
private String firstName;
@Column(nullable = false)
private String lastName;
@OneToOne(fetch = FetchType.LAZY, mappedBy = "person", cascade = CascadeType.DETACH)
private RfidEntity rfid;
}
@Getter
@Setter
@Entity
@Table(name = "rfid_tags")
public class RfidEntity {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private String id;
@Column(nullable = false)
private String label;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name="person_id", referencedColumnName="id")
private PersonEntity person;
}
I have already searched a lot and tried different things like changing the CascadeTypes or adding @OnDelete(onDeleteAction=SET_NULL)
Hibernate does not automatically handle ON DELETE SET NULL
. You need to manually set the association to NULL
before deleting the PersonEntity
.
RfidEntity
Mapping@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "person_id", referencedColumnName = "id", nullable = true)
private PersonEntity person;
PersonEntity
@OneToOne(fetch = FetchType.LAZY, mappedBy = "person")
private RfidEntity rfid;
person
to NULL
Before Deletion@Transactional
public void deletePerson(String personId) {
PersonEntity person = personRepository.findById(personId).orElseThrow();
if (person.getRfid() != null) {
person.getRfid().setPerson(null);
rfidRepository.save(person.getRfid());
}
personRepository.delete(person);
}
ALTER TABLE `rfid_tags`
ADD CONSTRAINT `FK_Rfid_Tag_Person`
FOREIGN KEY (`person_id`) REFERENCES `persons`(`id`)
ON DELETE SET NULL;
Note: Hibernate doesn’t enforce ON DELETE SET NULL
; it must be handled explicitly in the application logic.