I want to implement Soft Delete in my Spring Boot project which has @OneToOne and @OneToMany relations. Whenever I soft delete a parent entity, the soft delete should propagate to the child entities too. Additionally, I also want to store the deletion reason in the Parent entity. I have tried with the code below but the soft deletion doesn't propagate to the child entities. I can't used @SQLDelete either since I have two parameters in my delete operation.
@Entity
@Table(name="personal_details")
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder(toBuilder = true)
@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
public class PersonalDetail extends Auditable<String> implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private String idNo;
private String gender;
private String name;
// If the record has been soft-deleted
private Boolean deleted;
// Storing the reason why the record was deleted
private String deletionReason;
// For Address
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "address_id_no", referencedColumnName = "idNo")
private Address address;
// For Devices Received
@JsonManagedReference
@OneToMany(fetch = FetchType.LAZY, mappedBy = "personalDetail", cascade = CascadeType.ALL)
private List<DevicesReceived> devicesReceivedList;
// For Devices Required
@JsonManagedReference
@OneToMany(fetch = FetchType.LAZY, mappedBy = "personalDetail", cascade = CascadeType.ALL)
private List<DevicesRequired> devicesRequiredList;
// For Benefits
@JsonManagedReference
@OneToMany(fetch = FetchType.LAZY, mappedBy = "personalDetail", cascade = CascadeType.ALL)
private List<Benefit> benefitList;
}
@Entity
@Table(name = "address")
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder(toBuilder = true)
@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
public class Address extends Auditable<String> implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private String idNo;
private String address;
// If the record has been soft-deleted
private Boolean deleted;
}
@Entity
@Table(name="devices_received")
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder(toBuilder = true)
@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
public class DevicesReceived extends Auditable<String> implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Integer id;
private String idNo;
private String device;
@JsonBackReference
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "personal_details_id_no", nullable = false)
private PersonalDetail personalDetail;
// If the record has been soft-deleted
private Boolean deleted;
}
@Repository
public interface PersonalDetailRepository extends JpaRepository<PersonalDetail, String> {
@Transactional
@Modifying
@Query(nativeQuery = true, value = "UPDATE personal_details SET deleted = TRUE, deletion_reason = (?2) WHERE id_no = (?1);")
void delete(String idNo, String deletionReason);
}
In terms of Hibernate your deletion is not deletion, but just update
, so it doesn't have to propagate this operation to the associated entities. I recommend you to consider using Hibernate's out-of-box soft delete.
Also, don't use Lombok's @Data
for entities, it implicitly generates equals/hashcode which use fields-associations and may cause unexpected behavior.