Как сохранить родительский объект, содержащий дочерний объект, с помощью весенней загрузки в однонаправленном отображении @ManyToOne? - PullRequest
1 голос
/ 18 февраля 2020

Я новенький в весенней загрузке. У меня есть два модельных класса Party (родительский) и PartyCategory (дочерний). PartyCategory успешно хранит данные id, labelAr и labelEn.

Теперь я передаю дочерний идентификатор в запросе json и получаю нулевые значения для labelAr и labelEn в ответе json, как показано ниже. Может кто-нибудь, пожалуйста, помогите, что и делать не так здесь

Я также вставил свой код.

Json Запрос:

{

    "name": "Party A",
    "description": "Description of Party A",
    "category": {
        "id": 1
    }
}

Json ответ;

{
    "id": 6,
    "name": "Party A",
    "description": "Description of Party A",
    "category": {
        "id": 1,
        "labelAr": null,
        "labelEn": null
    }
}

Вечеринка . java:

   public class Party {

        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Integer id;
        private String name;
        private String description;
        @ManyToOne(cascade = CascadeType.MERGE, fetch = FetchType.EAGER)
        @JoinColumn(name = "category_id")
        private PartyCategory category;

        ....setters and getters
   }

PartyCategory. java: -

public class PartyCategory {

    @Id
    @GeneratedValue
    private Integer id;
    private String labelAr;
    private String labelEn;

    ...setters and getters..

Хранилища:

public interface PartyCategoryRepository extends JpaRepository<PartyCategory, Integer> {

}

public interface PartyRepository extends JpaRepository<Party, Integer> {

}

Услуги:

public class PartyServiceImpl {
    @Autowired
    PartyRepository partyRepository;

public Party saveParty(Party party) {

        return partyRepository.save(party);
    }

Контроллер:

@RestController
public class PartyController {

    @Autowired
    PartyServiceImpl partyServiceIml;


    @PostMapping(value = "/party/save")
    public Party saveParty(@RequestBody Party party ) {
        Party returnedParty = partyServiceIml.saveParty(party);
        return returnedParty;
    }
}

Ответы [ 2 ]

1 голос
/ 18 февраля 2020

Проблема в том, что публикуемая вами категория не распознается как существующая категория.

Затем вы можете сделать что-то подобное ниже. Во-первых, создайте класс преобразователя Джексона, чтобы настроить десериализацию Json. Я не был уверен, что это Spring, но они таковы, что вы можете затем вставить необходимый репозиторий.

import com.fasterxml.jackson.databind.util.StdConverter;

@Component
public class CategoryConverter extends StdConverter<Integer, PartyCategory> {

    @Autowired
    private PartyCategoryRepository repo;

    @Override
    public PartyCategory convert(Integer value) {
        return repo.findById(value).get();
    }
}

Затем обновите вашу сущность следующим образом, чтобы свойство category Json было обработано с помощью конвертер создан выше. Обратите внимание, что на самом деле я бы использовал смешивание Джексона для применения этого пользовательского десериализатора, поскольку это позволило бы избежать «загрязнения» класса сущностей инструкциями обработки Json. Вы можете посмотреть, как это сделать.

@Entity
public class Party {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    private String name;

    private String description;

    @ManyToOne
    @JoinColumn(name = "category_id")
    @JsonDeserialize(converter = CategoryConverter.class) //in real life use a 'mix-in'
    private PartyCategory category;
}

Затем вы можете опубликовать JSON, как показано ниже, где мы просто указываем идентификатор существующей категории:

{

    "name": "Party A",
    "description": "Description of Party A",
    "category": 1
}

. Решение использовать встраиваемые модули, как предложено, тогда можно затем четко отделить модель представления от модели объекта, не создавая слой DTO, который, как правило, будет в значительной степени дублировать модель объекта и который потребует утомительного кода отображения для обработки преобразований.

0 голосов
/ 18 февраля 2020

Прежде всего, не рекомендуется использовать одну и ту же сущность для базы данных, а также для остальных служб. Они должны быть отдельными объектами, обычно объекты для остальных служб называются DTO (объекты доступа к данным).

Теперь, что касается вашей проблемы, это нормально, что происходит в вашем коде, потому что вы перезаписываете PartyCategory labelAr и labelEn, связанный с идентификатором 1 с нулевыми значениями при сохранении новой партии, поскольку вы не указали никакого значения для этих двух меток.

return partyRepository.save(party);

Если вы хотите избежать этой проблемы, вам нужно получить Данные PartyCategory сначала из базы данных, устанавливаются в сущность Party, а затем сохраняются в базе данных. Как то так:

public class PartyServiceImpl {
    @Autowired
    PartyRepository partyRepository;

    @Autowired
    PartyCategoryRepository partyCategoryRepository;

    public Party saveParty(Party party) {
        PartyCategory partyCategory = partyCategoryRepository.findById(party.getPartyCategory().getId());

        party.setPartyCategory(partyCategory);

        return partyRepository.save(party);
    }
...