Cascade save model not saving relationship
Asked Answered
T

2

7

I have an Play2 application using eBean integrated with PostgreSQL database.

Basically I have a model TripRequest that as a list of Passengers . The use case is "A trip has several passengers".

For the TripRequest I have this model:

@Entity
public class TripRequest extends Model {

    enum Status {
        OPEN,
        PROCESSING,
        CLOSED,
        CANCELLED
    }

    @Id
    private UUID id;

    @ManyToOne
    @Column(nullable = false)
    private User owner;

    @OneToMany(mappedBy = "tripRequest")
    @JoinTable(name = "trip_passengers")
    private List<Passenger> passengers;
    (... other fields, getters and setters ...)

And this is my Passenger model:

@Entity
@Table(name = "trip_passenger")
public class Passenger extends Model {

    @ManyToOne(cascade = CascadeType.ALL)
    private TripRequest tripRequest;

    @Column(nullable = false)
    private String name;
    (... other fields, getters and setters)

So, I create a new instance of TripRequest, several instances of Passenger and set that list as the passengers of TripRequestinstance. Problem is that when I do tripRequest.save() everything in the main instance (TripRequest) gets saved but the relations are not (so the passengers list).

I read in the documentation and examples and everything is pointing me to the CascadeType.ALL in the @ManyToOne annotation but no "luck" at all

EDIT: if you think the complete classes are useful please let me know as I can post them. Just decided to keep the example short so I trimmed them.

Tanguay answered 23/10, 2015 at 21:10 Comment(2)
Is the result the same if the cascade is placed on the @OneToMany instead?Vesicatory
@Vesicatory I get a NullPointerException as described in gist.github.com/mribeiro/2627ecb640bf19e0adb6Tanguay
G
1

Your @OneToMany(mappedBy = "tripRequest") ... has no cascade = CascadeType.ALL (or CascadeType.PERSIST).

This means the save on TripRequest is not cascading on the list of passengers.

Gorski answered 28/10, 2015 at 21:13 Comment(0)
F
0

I think you should set tripRequest on Passenger side (cause this class actually owns the relationship) and only then save it. Something like this:

for(Passenger p : passengers){
    p.tripRequest = this;
}
Freewill answered 26/10, 2015 at 16:1 Comment(3)
I am setting the tripRequest instance on each passenger. However, when I save the tripRequest the passengers list isn't saved. A workaround I found is to save the tripRequest and then iterate thru the passengers and save each individually, but it feels "wrong"Tanguay
@MiguelRibeiro That is definitely wrong. I think everything will work without double save if you put (cascade=CascadeType.ALL) to the @OneToMany annotation of TripRequest instead of @ManyToOne of Passenger. Because this is the direction of the cascading.Freewill
Well... found the issue. I don't even need to set the tripRequest instance to the Passenger. So, 1st of all, the cascade must go to the @OneToMany. The problem is that the Passenger didn't have an ID member. I had to debug Play's code to see from where the NPE was coming.Tanguay

© 2022 - 2024 — McMap. All rights reserved.