Как добавить значения ко многим сторонам в весенней загрузке отношений «один ко многим»

#java #hibernate #spring-boot

#java #спящий режим #spring-boot

Вопрос:

У меня есть торговые и адресные таблицы. у одного продавца может быть несколько адресов, а у одного адреса есть один продавец (отношение «один ко многим»).При добавлении значения продавца с адресом я получаю эту ошибку. Как решить эту ошибку? Это ошибка.

 {
    "timestamp": 1554878673504,
    "status": 500,
    "error": "Internal Server Error",
    "message": "could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement",
    "path": "/merchant-service/save-merchant"
}
  

Это мои входные значения:

  {
        "idNo": null,
        "idType": null,
        "emailId": "email@gmail.com",
        "name": null,
        "status": true,
        "createdBy": null,
        "modifiedBy": null,
        "createdDate": null,
        "modifiedDate": null,
        "contacts": [
            {"contactNo": "0766601122"}],
        "addresses": [
            {"line1": "manipay"},
            {"line1": "suthumalai"}
            ]
    }
  

это мой код в торговой модели:

  @OneToMany(fetch = FetchType.LAZY,cascade = {CascadeType.ALL}, mappedBy = "merchant")
    private Set<Address> addresses = new HashSet<Address>(
            0);
  

это мой код в адресной модели:

  @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "merchant_id", nullable = false)
//    @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
//    @Getter(onMethod = @__( @JsonIgnore))
//    @Setter
    private Merchant merchant;
  

это мой сервис:

 public Merchant saveMerchant(Merchant merchant) {
       merchant = merchantRepository.save(merchant);
       return merchant;
    }
  

Комментарии:

1. Вы не опубликовали полную трассировку стека исключения, но я предполагаю, что у вас есть ненулевое ограничение для address.merchant_id , и поскольку ваш код никогда не устанавливает address.merchant в ненулевое значение перед вставкой merchant и его адресов, Hibernate сохраняет null в merchant_id, вызываянарушение ограничений.

2. @JBNizet когда я одновременно добавляю продавца, я хочу добавить адреса к этому идентификатору продавца. Есть ли у вас какое-либо решение?

3. ДА. Установите поле merchant для адресов: merchant.getAddresses().forEach(address -> address.setMerchant(merchant)) .

Ответ №1:

В вашей торговой модели вы устанавливаете cascade = {CascadeType.ALL} атрибут addresses . Это означает, что в этом случае, если вы хотите сохранить объект Merchant с некоторыми адресами, режим гибернации проверит, существуют ли эти адреса; если нет, он создаст их раньше. Но в вашей модели адресов вы устанавливаете nullabel = false атрибут merchant, который означает, что объект Address не может сохраняться без существующего продавца. Затем, когда спящий режим пытается сохранить продавца и найти адрес, который еще не сохранен, он пытается сохранить этот адрес раньше, он также находит нулевой объект продавца, а затем выдает это исключение org.hibernate.exception.ConstraintViolationException .

Вы должны выбрать одно из этих предложений:

  • Удалите nullable = false ограничение в атрибуте продавца в адресной модели. если вы это сделаете, адрес будет сохранен без продавца. Затем, когда вы сохраняете спящий режим продавца, он обновит адрес.

  • Измените cascade = {CascadeType.ALL} на все другие каскады, кроме СОХРАНЕНИЯ в атрибуте addresses торговой модели. Если вы это сделаете, вы должны сохранить продавца перед собой, а затем сохранить адрес у существующего продавца.

Комментарии:

1. Можете ли вы изменить мой код, потому что я не смог понять ваш ответ.

2. Попробуйте этот @JoinColumn(name = «merchant_id») вместо @JoinColumn(name = «merchant_id», nullable = false)

3. { «отметка времени»: 1554885216731, «статус»: 500, «ошибка»: «Внутренняя ошибка сервера», «сообщение»: «не удалось выполнить инструкцию; SQL [n / a]; ограничение [null]; вложенным исключением является org.hibernate.exception. ConstraintViolationException: не удалось выполнить оператор», «path»: «/ merchant-service /save-merchant» }

4. в журнале загрузки spring: java.sql.SQLIntegrityConstraintViolationException: столбец ‘merchant_id’ не может быть нулевым

5. Я уверен, что в таблице адресов поле merchant_id не имеет ограничения null. Вы также должны удалить его.

Ответ №2:

В таблице Merchent:

   @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE}, mappedBy = "merchant")
    private Set<Address> addresses = new HashSet<Address>(
            0);
  

В адресной таблице:

  @ManyToOne(fetch = FetchType.LAZY)
        @JoinColumn(name = "merchant_id")
        @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
        @Getter(onMethod = @__( @JsonIgnore))
        @Setter
        private Merchant merchant;
  

В сервисе:

 public Merchant saveMerchant(Merchant merchant) {
       merchant = merchantRepository.save(merchant);
        Merchant finalMerchant = merchant;
        merchant.getAddresses().forEach(address -> {
           address.setMerchant(finalMerchant);
           addressRepository.save(address);
       });
       return merchant;
    }
  

Он отлично работает.

Комментарии:

1. Вы не должны создавать нового продавца для каждого адреса. Вы должны установить уникального продавца в каждом адресе.

2. @JBNizet Здесь я делаю вот так.

3. Я даю один идентификатор продавца на все адреса.

4. Предполагается, что все адреса имеют одного и того же продавца. Итак, почему вы создаете нового продавца для каждого адреса. Просто установите один и тот же объект merchant на каждый адрес.

5. Это пустой объект merchant, и после добавления merchant я получаю этот идентификатор и устанавливаю идентификатор в объект merchant и прикрепляю к address.setMerchant. Это работает для меня. если у вас есть какие-либо сомнения, я отправлю свой ответ.

Ответ №3:

В нем говорится, что у вас ошибка нарушения ограничений, что означает, что вы, возможно, установили для любой переменной в сущности значение not null, и вы пытаетесь сохранить значение null.

Комментарии:

1. здесь идентификатор продавца не задан. Я знаю этот момент, но мой сценарий, когда при добавлении продавца одновременно адреса хотят добавляться в таблицу адресов с идентификатором продавца.

2. почему бы вам сначала не получить адреса, сохранить их в таблице адресов, а затем использовать merchant.getAddresses.set(addresses)