我的JpaRepository
生成了错误的SQL。它只更新商店而不是实体的其余部分。仔细观察后,我发现该查询对update shop set
实体campaign
内部的shop
内没有任何说明。
Inside Campaign有一家商店:
@JoinColumn(name = "SHOP_ID", referencedColumnName = "SHOP_ID", nullable = false)
@ManyToOne(cascade = CascadeType.ALL)
private Shop shop;
在店内我有一套:
@OneToMany(cascade = CascadeType.ALL, mappedBy = "shop")
private Set<Campaign> campaignSet;
使用saveAndFlush
-
update shop set created_at=?, currency=?, currency_iso_code=?, default_delivery_cost=?, delivery_cost_erp_number=?, description=?, default_language_id=?, modified_at=?, sales_organisation_id=?, code=?, valid_from=?, valid_till=? where shop_id=?
我希望保存整个广告系列,老实说我并不关心更新商店,因为在更新广告系列时我永远不会这样做。
方法更新:
@Override
@Modifying
@Transactional
public CampaignDto update(CampaignDto campaignDto) throws RequestNotFoundException {
//TODO: compare objects to see if there is a change
Campaign campaign = mapper.mapReverse(campaignDto);
if (campaign.getCampaignId() != null) {
campaign = campaignRepository.getOne(campaign.getCampaignId());
if (campaign.getCampaignId() == null) {
throw new RequestNotFoundException(
String.format("Campaign %s is not found", campaign.getKey().toString()));
}
}
Shop shop = shopRepository.getOne(campaignDto.getShopId());
if (shop.getShopId() > 0 && shop.getShopId() != null) {
shop.setCode(campaignDto.getShopCode());
shop.setCurrency(campaignDto.getShopCurrency());
shop.setCurrencyIsoCode(campaignDto.getShopCurrencyIso());
shop.setValidFrom(campaignDto.getValidFrom());
shop.setValidTill(campaignDto.getValidTill());
shop.setCreatedAt(OffsetDateTime.now());
shop.setSalesOrganisationId(campaignDto.getSalesOrganisationId());
} else {
throw new IllegalArgumentException("Must declare an existing shop to update a campaign.");
}
Language language = languageRepository.getOne(campaignDto.getLanguageId());
if (!StringUtils.isEmpty(language.getLanguageId()) && language.getLanguageId() != null) {
language.setLanguageId(campaignDto.getLanguageId());
shop.setLanguage(language);
} else {
throw new IllegalArgumentException("Must declare an existing language to update a campaign.");
}
campaign.setShop(shop);
CampaignDto updatedCampaign = mapper.map(campaign);
campaignRepository.saveAndFlush(campaign);
return updatedCampaign;
}
答案 0 :(得分:0)
老实说,我不关心更新商店,因为在更新广告系列时我永远不会这样做
为什么CascadeType.ALL
呢?你永远不应该永远使用CascadeType.ALL
与多对一关联。这是因为CascadeType.MERGE
很少有意义(你实际上是在乞求像你描述的那样的意外副作用),而CascadeType.REMOVE
只是纯粹的邪恶(通过删除孩子,你删除了父母,反过来导致其他所有孩子被删除,因为CascadeType.ALL
上有另一个Shop.campaigns
。
另外,如果您在保存Shop
时从不想更新Campaign
,以下代码的目的是什么?
if (shop.getShopId() > 0 && shop.getShopId() != null) {
shop.setCode(campaignDto.getShopCode());
shop.setCurrency(campaignDto.getShopCurrency());
shop.setCurrencyIsoCode(campaignDto.getShopCurrencyIso());
shop.setValidFrom(campaignDto.getValidFrom());
shop.setValidTill(campaignDto.getValidTill());
shop.setCreatedAt(OffsetDateTime.now());
shop.setSalesOrganisationId(campaignDto.getSalesOrganisationId());
}
如果您确实不想更新Shop
,请删除该部分。作为旁注,您可能希望交换if
子句中的条件。
最后,如果您没有看到CAMPAIGN
表的更新,可能是因为Campaign
实体没有实际更改。通常,Hibernate将检索当前状态并将其与更新的Entity
进行比较,以避免不必要的UPDATE
语句。