JPA / hibernate генерирует неправильный оператор SQL - PullRequest
0 голосов
/ 30 апреля 2018

My JpaRepository генерирует неправильный SQL. Он только обновляет магазин, а не всю сущность. Посмотрев поближе, я заметил, что запрос говорит update shop set ничего о campaign сущности, в которой shop находится внутри.

Внутри Кампании есть магазин:

 @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;
}

1 Ответ

0 голосов
/ 30 апреля 2018

Честно говоря, я не забочусь об обновлении магазина, потому что никогда не сделаю этого при обновлении кампании

Почему тогда 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...