Reputation: 53
i have product and campaign entity with ManyToMany relationship. When I define a campaign for the product, I add something like this to the product_campaigns table in the db. For example:
product_campaigns : product_id : 1 campaign_id : 1
It means that campaign with 1 id is defined for the product with 1 id. When I delete the campaign number 1, I want the lines with the number 1 campaign defined in the product_campaigns table to be deleted. But now when i delete the campaign number 1 ,it both deletes the product_campaigns row and deletes the related product object in the product table . What am i wrong ? Thx.
@Getter
@Setter
@Entity
public class Product extends BaseExtendedModel {
private String name;
private BigDecimal price;
private UUID barcode;
private String image;
@ManyToOne
private Brand brand;
@ManyToOne
private Category category;
@ManyToOne
private Seller seller;
private int stock;
private BigDecimal taxRate;
@ManyToMany
@JoinTable(name = "PRODUCT_CAMPAIGN", joinColumns = { @JoinColumn(name = "product_id") }, inverseJoinColumns = { @JoinColumn(name = "campaign_id") })
private Set<Campaign> campaigns = new HashSet<>();
}
@Entity
@Getter
@Setter
public class Campaign extends BaseModel{
private BigDecimal discountRate;
private BigDecimal discountPrice;
private String name;
private String description;
private Date startDate;
private Date endDate;
@ManyToMany(mappedBy = "campaigns",cascade = CascadeType.ALL)
private Set<Product> productSet = new HashSet<>();
}
@Component
@RequiredArgsConstructor
public class CampaignServiceImpl implements CampaignService{
private final CampaignRepository campaignRepository;
private final CampaignConverter campaignConverter;
@Override
public void create(CreateCampaignRequestDTO createCampaignRequestDTO) {
Campaign campaign = campaignConverter.toCampaign(createCampaignRequestDTO);
campaignRepository.save(campaign);
}
public Campaign getCampaign(Long campaignId){
return campaignRepository.findById(campaignId).orElseThrow(
() -> new BusinessServiceOperationException.CampaignNotFoundException("Campaign not found")
);
}
@Override
public void delete(Long campaignId) {
Campaign campaign = getCampaign(campaignId);
campaignRepository.delete(campaign);
}
}
Upvotes: 0
Views: 311
Reputation: 793
When deleting you have to pay attention to your cascade types. CascadeType.ALL
includes REMOVE
so you're telling spring data to delete all the items in the productSet
.
What you want is CascadeType.PERSIST
, also add the @JoinTable
annotation.
@Entity
public class Campaign extends BaseModel {
// your other code
@ManyToMany(mappedBy = "campaigns", cascade = CascadeType.PERSIST)
@JoinTable(
name = "PRODUCT_CAMPAIGN",
joinColumns = @JoinColumn(name = "campaign_id"),
inverseJoinColumns = @JoinColumn(name = "product_id"))
private Set<Product> productSet = new HashSet<>();
}
Link to documentation: https://openjpa.apache.org/builds/2.4.0/apache-openjpa/docs/jpa_overview_meta_field.html#jpa_overview_meta_cascade
Upvotes: 1