@OneToMany Отношения в JPA не работают должным образом - PullRequest
1 голос
/ 25 марта 2019

Привет, у меня есть следующие отношения:

@Entity
public class Athlete implements Serializable {

    private static final long serialVersionUID = 1L;

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

    @ManyToOne
    @JoinColumn(name="closetWaiting")
    private Closet closetWaiting; 
....

 @Entity
public class Closet implements Serializable {

    private static final long serialVersionUID = 1L;

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

    @OneToMany(mappedBy="closetWaiting")
    private List<Athlete> waitingList;
 ....

, и в моем классе Бинов у меня есть этот код:

  public void addAthleteIntoWaitingList(String closetId, Athlete singleAthlete ) {
        Closet singleCloset=entityManager.find(Closet.class,Integer.parseInt(closetId));

        List<Athlete> waitingList=singleCloset.getWaitingList();        
        waitingList.add(singleAthlete);     
        singleCloset.setWaitingList(waitingList);

        singleAthlete.setClosetWaiting(singleCloset);
    }

, который не работает с тех пор, как я вызываю методaddAthleteIntoWaitingList Столбец CLOSETWAITING в таблице Атлет всегда равен нулю.

Я что-то здесь не так делаю?Любое предложение для решения?

РЕДАКТИРОВАТЬ:

Чтобы понять, что происходит за кодом, я активировал свойства ведения журнала eclipse в файле persistence.xml.Итак, вот что я получаю, когда я вызываю метод:

2019-03-26T10:37:16.862+0100|Fein: SELECT ATHLETEID, FIRSTNAME, GENDER, LASTNAME, PHONENUMBER, closetWaiting FROM ATHLETE WHERE (ATHLETEID = ?)
    bind => [12]
2019-03-26T10:37:16.871+0100|Fein: SELECT CLOSETID, CLOSETRANK, GENDER, ISBROKEN, ISOCCUPIED, RESERVATIONENDED, RESERVATIONSTARTED, athleteId FROM CLOSET WHERE (CLOSETID = ?)
    bind => [5]
2019-03-26T10:37:16.876+0100|Fein: SELECT CLOSETID, CLOSETRANK, GENDER, ISBROKEN, ISOCCUPIED, RESERVATIONENDED, RESERVATIONSTARTED, athleteId FROM CLOSET

Это означает, что JPA получает Атлета с Id = 12, а затем находит шкаф с Id = 5.Но затем он полностью игнорирует остальную часть кода, где Атлет добавляется в waitList, и не сохраняет его в базе данных.

Покажите теперь реальный вопрос: почему это происходит?

РЕШЕНИЕ:

За исключением решения @PeterЭто работало отлично. Я внес следующие изменения, не добавляя каскадный тип и, что более важно, не вызывая метод слияния:

Я изменил способ, которым мой метод получает объект Athlete.Вместо того чтобы указывать его в качестве параметра, я получаю его через EntityManager.find () внутри моего EJB-компонента.Вот как это выглядит:

public void addAthleteIntoWaitingList(String closetId, String athleteId ) {
    Closet singleCloset=entityManager.find(Closet.class, Integer.parseInt(closetId));

    Athlete singleAthlete=entityManager.find(Athlete.class, Integer.parseInt(athleteId));

    List<Athlete> waitingList=singleCloset.getWaitingList();        
    waitingList.add(singleAthlete);     
    singleCloset.setWaitingList(waitingList);

    singleAthlete.setClosetWaiting(singleCloset);
}

Может кто-нибудь объяснить мне, почему этот работал?Я думаю, потому что я манипулирую объектом Ahtlete внутри транзакции или нет?

Ответы [ 2 ]

1 голос
/ 25 марта 2019

Без @OneToMany(cascade=CascadeType.ALL) коллекция не будет сохранена при сохранении родительского объекта.

Если вы изменяете свойство объекта в транзакции, нет необходимости явно вызывать слияние. Если сущность выходит за пределы транзакции, она становится ОТДЕЛЕННОЙ Отдельная сущность singleAthlete. Слияние необходимо. Транзакция автоматически фиксируется контейнером, выходящим из последнего метода EJB.

Вызовите явно entityManager.merge (шкаф).

0 голосов
/ 26 марта 2019

Я думаю, что перед добавлением «singleAthlete» в список вы должны сохранить его в базе данных, поэтому, прежде чем waitList.add (singleAthlete), попробуйте: entityManager.persist (singleAthlete); Конечно, не забудьте объединить singleCloset и зафиксировать результаты: так вы наконец-то вызовете: entityManager.merge (singleCloset); entityManager.getTransaction () совершить ();.

...