данные весны jpa: после обновления боковой таблицы @many, невозможно получить правильные изменения с помощью боковой таблицы findAll @one в том же методе - PullRequest
0 голосов
/ 25 июня 2019

У меня есть объект процедуры, а процедура содержит список объектов карты. Любая карта может быть перемещена между процедурами. Так что теперь, если я сделаю шаг (на самом деле установил Procedure карты в другую процедуру) и сразу же обнаружу AllAll () в следующей строке, он возвращает [] для обеих процедур.

пытался использовать saveAndFlush () вместо save () перед findAll (), но тоже не работает.

лица:

@Entity
@Table(name = "procedures")
public class Procedure {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    @OneToMany(mappedBy = "procedure", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JsonManagedReference
    private List<Card> cards = new ArrayList<>();
//...getter setter constructor
}
@Entity
@Table(name = "cards")
public class Card {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    @ManyToOne
    @JsonBackReference
    private Procedure procedure;
//...getter setter constructor
}

Контроллер

    @GetMapping("/card/move/{cid}/{nextPid}")
    @Transactional
    public List<Procedure> moveCard(@PathVariable Long cid, @PathVariable Long nextPid) {
        return cardService.moveCard(cid, nextPid);
    }

внутренняя служба

    List<Procedure> moveCard(Long cid, Long nextPid) {
        Card card = cardRepository.findById(cid).get();
        Procedure toProcedure = procedureService.findById(nextPid);

        card.setIndex(toProcedure.getCards().size());
        card.setProcedure(toProcedure);

        cardRepository.saveAndFlush(card);

        return procedureService.findAll();
    }

например. если у меня есть 1 карта в процедуре 1, после того, как я вызываю этот API, он возвращает следующее:

[
    {
        "id": 1,
        "cards": [],
    },
    {
        "id": 2,
        "cards": [],
    }
]

но я ожидаю:

[
    {
        "id": 1,
        "cards": [],
    },
    {
        "id": 2,
        "cards": [{id: 123}],
    }
]

Ответы [ 3 ]

1 голос
/ 25 июня 2019

Как намекает в другом месте, где отношения являются двунаправленными, вы должны поддерживать обе стороны.

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

public class Procedure{

    public Set<Card> cards; // or list

    public void addCard(Card Card){
        card.getProcedure().removeCard(card);
        this.cards.add(card);
        card.setProcedure(this);
    {

    public void removeCard(Card card){
        cards.remove(card);
        card.setProedure(null);
    }

    public Set<Card> getCards(){
        //force client code to use add/remove operations
        //to ensure in-memory model **always** consistent
        return Collections.unmodifiableSet(cards); // or list
    }
}

Думайте в терминахсовокупных корней (https://www.baeldung.com/spring-persisting-ddd-aggregates) и работа с процедурой:

void moveCard(Long cid, Long nextPid) {
    Card card = cardRepository.findById(cid).get();
    Procedure fromProcedure = card.getProcedure();
    Procedure toProcedure = procedureService.findById(nextPid);

    formProcedure.removeCard(card);
    toProcedure.addcard(card);

    card.setIndex(toProcedure.getCards().size()); ??

    //if method is executed in transaction then no need to call saveAndFlush
    //the following 2 lines can be removed.
    cardRepository.saveAndFlush(fromProcedure);
    cardRepository.saveAndFlush(toProcedure);
}
1 голос
/ 25 июня 2019

Вы должны поддерживать и другую сторону отношений.

Ваш код должен выглядеть так:

List<Procedure> moveCard(Long cid, Long nextPid) {
    Card card = cardRepository.findById(cid).get();

    // Remove the card from the procedure
    card.getProcedure().getCards().remove(card);

    Procedure toProcedure = procedureService.findById(nextPid);
    // Add it to the new procedure
    toProcedure.getCards().add(card);

    card.setIndex(toProcedure.getCards().size());
    card.setProcedure(toProcedure);

    cardRepository.saveAndFlush(card);

    return procedureService.findAll();
}
0 голосов
/ 26 июня 2019

Это то, что сработало для меня, единственным изменением было удаление и добавление в процедурах из / в, и вам также не нужно сбрасывать изменения прямо:

  @Transactional
  List<Procedure> moveCard(Long cid, Long nextPid) {
    Card card = cardRepository.findById(cid).get();
    Procedure toProcedure = procedureService.findById(nextPid);
    Procedure fromProcedure = card.getProcedure();

    //this keeps the object in memory updated and returned by findAll after
    fromProcedure.getCards().remove(card);
    toProcedure.getCards().add(card);

    card.setIndex(toProcedure.getCards().size());
    card.setProcedure(toProcedure);

    cardRepository.save(card);

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