Search code examples
jpajakarta-eeentity

@OneToMany Relationship in JPA doesn't work properly


Hi there I have the following relationship:

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

and in my Bean class I have this code:

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

which doesn't work since after I call the method addAthleteIntoWaitingList the Column CLOSETWAITING in the table Athlete is always null.

Am I doing something wrong here? Any suggestion for a solution?

EDIT:

In order to understand what is going on behind the code I activated the logging properties of eclipse in the persistence.xml. So here is what I am getting when I call the method:

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

That means that JPA is getting the Athlete with Id=12 and then finds the closet with Id=5. But then it totally ignores the rest of the code where the Athlete is being added into the waitingList and doesn't persist it into the database.

Show now the real question is why is this happening?

SOLUTION:

Except for the solution of @Peter which it worked perfectly I did the following changes without adding any cascade type and more important without calling the merge method:

I changed the way my method gets the object Athlete. Instead of giving to it as a parameter, I instead get it over EntityManager.find() inside my EJB Bean. Here is how it looks:

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

Can anyone explain to me why this one worked? I guess because I manipulate an Ahtlete Object inside a transaction or not?


Solution

  • Without @OneToMany(cascade=CascadeType.ALL) collection will be not saved if saving parent entity.

    If you change entity property in transaction, no need to explicitly call merge. If entity goes outside of transaction it gets DETACHED. Detached entity is singleAthlete. Merge is needed. Transaction is automatically commited by container exiting last EJB method.

    Call explicitly entityManager.merge(closet).