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

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

{
    "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 protected]",
        "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;
    }

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

JB Nizet 10.04.2019 08:53

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

Majutharan Majutharan 10.04.2019 08:59

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

JB Nizet 10.04.2019 09:05
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
3
1 362
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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

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

Majutharan Majutharan 10.04.2019 09:02

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

Mohendra Amatya 10.04.2019 09:04

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

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

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

  • Измените cascade = {CascadeType.ALL} на все остальные каскады, кроме PERSIST в атрибуте адресов модели Merchant. Если вы это сделаете, вы должны сохранить Merchant перед собой, а затем сохранить Address с существующим Merchant.

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

Majutharan Majutharan 10.04.2019 10:13

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

Kenany 10.04.2019 10:27

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

Majutharan Majutharan 10.04.2019 10:34

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

Majutharan Majutharan 10.04.2019 10:35

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

Kenany 10.04.2019 13:46

Я решил эту проблему. Я добавил этот ответ здесь.

Majutharan Majutharan 10.04.2019 13:47
Ответ принят как подходящий

В таблице продавца:

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

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

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

JB Nizet 10.04.2019 18:44

@JBNizet Вот я так и делаю.

Majutharan Majutharan 11.04.2019 07:47

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

Majutharan Majutharan 11.04.2019 07:48

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

JB Nizet 11.04.2019 08:43

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

Majutharan Majutharan 11.04.2019 09:06

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

Majutharan Majutharan 11.04.2019 09:06

Работает, но излишне сложно и неэффективно, и неправильно, так как, повторюсь, на всех адресах должен стоять мерчант тоже самое: тот, который вы сохраняете при старте метода.

JB Nizet 11.04.2019 09:31

@JBNizet Я обновил этот ответ, пожалуйста, не могли бы вы его проверить?

Majutharan Majutharan 11.04.2019 10:00

Это гораздо лучше. Вы можете сделать это еще проще, настроив продавца на адреса перед сохранением продавца и удалив вызов addressRepository.save(address), поскольку у вас есть каскад, и сохранение продавца, таким образом, сохранит адреса.

JB Nizet 11.04.2019 10:52

Давайте продолжить обсуждение в чате.

Majutharan Majutharan 11.04.2019 12:20

Другие вопросы по теме