I have a scenario in which I have a ManyToMany mapping between a Policy and a County entity tables. Here is the entity code-
InsurancePolicy.java-
@Entity
@Table(name = "insurance_policy")
public class InsurancePolicy {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="policy_id")
private long policyId;
@Column(name="policy_name",nullable = false,unique = true)
private String policyName;
//Short description
@Column(name="policy_description",nullable = false)
private String policyDescription;
//Long description
@Column(name="choose_description",nullable = false)
private String chooseDescription;
//many policies can belong to one category
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "company_id", nullable = false)
private Company company;
//many policies can belong to one category
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="category_id",nullable=false)
private Category category;
@ManyToMany(mappedBy = "queriedPolices",fetch = FetchType.LAZY,cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
private Set<User> usersQueried=new HashSet<>();
@OneToMany(mappedBy = "policy", cascade = {CascadeType.MERGE,CascadeType.PERSIST,CascadeType.REMOVE},fetch = FetchType.LAZY)
private Set<PolicyCounty> policyCounties = new HashSet<>();
PolicyCounty.java- (Relationship table)
@Data
@Entity
@Table(name="policy_county")
public class PolicyCounty {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="policy_county_id")
private long policyStateId;
@ManyToOne
@JoinColumn(name="policy_id")
private InsurancePolicy policy;
@ManyToOne
@JoinColumn(name = "county_id")
private County county;
@Column(name="cost",nullable = false)
private double cost;
}
County.java-
@Entity
@Data
@Table(name="county")
public class County {
@Id
@Column(name="countyid")
@GeneratedValue(strategy = GenerationType.AUTO)
private long countyId;
@Column(name="countyname",nullable = false,unique = true)
private String countyName;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "adminId", nullable = false)
private Admin admin;
@OneToMany(mappedBy = "county", cascade = {CascadeType.MERGE,CascadeType.PERSIST},fetch = FetchType.LAZY)
private Set<PolicyCounty> policyStates = new HashSet<>();
}
Problem-
I want to delete the InsurancePolicy entity and also delete the corressponding entities in the PolicyCounty table. For it, I write the delete method-
@Override
public long deletePolicy(long policyId) {
boolean isPresent=insurancePolicyRepository.existsById(policyId);
if(isPresent){
insurancePolicyRepository.deleteById(policyId);
return insurancePolicyRepository.count();
}
throw new ResourceNotFoundException("Policy with id "+policyId+" not found");
}
Now, when I try to delete, the entities do not get deleted from the table. I am not getting any exception during this operation. I doubt that the problem is with the Cascade Types used with entities. Please help me understand this.
in your code you should have an filed in InsurancePolicy that links to County
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
@JoinTable(name = "policy_county",
joinColumns = @JoinColumn(name = "insurance_policy_id"),
inverseJoinColumns = @JoinColumn(name = "county_id"))
private Set<County> counties= new HashSet<>();
and you should have filed in county like this
@ManyToMany(mappedBy = "insurance_policy", fetch = FetchType.LAZY)
private Set<InsurancePolicy > students = new HashSet<>();
hibernate does not now you have many to many relation if you dont have it.
but If you have extra fields in your join table, such as a cost field, Hibernate will not automatically delete the corresponding entries from the join table when you delete a entity. Instead, you need to manually delete the entries from the join table using a native SQL query or Hibernate's Criteria API.
another option is convert many to many relation into 2 one to many relation like this :
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String name;
@OneToMany(mappedBy = "student", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<Enrollment> enrollments = new HashSet<>();}
public class Course {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String name;
@OneToMany(mappedBy = "course", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<Enrollment> enrollments = new HashSet<>();}
public class Enrollment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
private Student student;
@ManyToOne(fetch = FetchType.LAZY)
private Course course;
@Column(name = "cost")
private BigDecimal cost;}
In the above example, the "Student" entity has a one-to-many relationship with the "Enrollment" entity, and the "Course" entity also has a one-to-many relationship with the "Enrollment" entity. Both relationships have cascading deletes set up using the CascadeType.ALL option, which will cause associated "Enrollment" entities to be deleted automatically when a "Student" or "Course" entity is deleted. The orphanRemoval attribute is set to true, which will remove any "Enrollment" entities that are no longer associated with a "Student" or "Course" entity.
With cascading deletes set up, you can delete a "Student" or "Course" entity and all associated "Enrollment" entities will be deleted automatically: