admin管理员组

文章数量:1123401

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)

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)

Share Improve this question edited 14 hours ago Dalija Prasnikar 28.5k45 gold badges94 silver badges175 bronze badges asked 14 hours ago user24707318user24707318 32 bronze badges New contributor user24707318 is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct. 2
  • did you try cascade change on PersonEntity and allowing PersonEntity to be set as null? @OneToOne(fetch = FetchType.LAZY, mappedBy = "person", cascade = CascadeType.ALL, orphanRemoval = true) private RfidEntity rfid; @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "person_id", referencedColumnName = "id", nullable = true) private PersonEntity person; – Narendran Solai Sridharan Commented 14 hours ago
  • @NarendranSolaiSridharan I just tried it, but when I delete a Person it also deletes the RfidTag, which I do not want. Thanks for your help! – user24707318 Commented 14 hours ago
Add a comment  | 

2 Answers 2

Reset to default 1

Hibernate does not automatically handle ON DELETE SET NULL. You need to manually set the association to NULL before deleting the PersonEntity.

1. Update RfidEntity Mapping

@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "person_id", referencedColumnName = "id", nullable = true)
private PersonEntity person;

2. Remove Cascade from PersonEntity

@OneToOne(fetch = FetchType.LAZY, mappedBy = "person")
private RfidEntity rfid;

3. Manually Set 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);
}

4. Verify SQL Constraint

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.

Please try using the below in Person entity:

// No cascade type here; we don’t want cascading from Person to Rfid
@OneToOne(fetch = FetchType.LAZY, mappedBy = "person")
private RfidEntity rfid;

And in RfidTags

@OneToOne(fetch = FetchType.LAZY, orphanRemoval = false, cascade = {})
@JoinColumn(name = "person_id", referencedColumnName = "id", onDelete = OnDeleteAction.CASCADE)
private Person person;

本文标签: javaSpring Data JPA OneToOne ON DELETE SET NULLStack Overflow