Interestingly, I can't find any solution for a seemingly common scenario! So I'm asking here to learn from experienced professionals in Spring Data JPA. I'll consider using Lombok to make the sample codes more concise.
Consider a simple IMDB example web application. I've defined two simple entities as below:
@Data
@Entity
public class Movie {
@Id
@GeneratedValue
private long id;
private String title;
private int year;
private int rating;
}
@Data
@Entity
public class Actor {
@Id
@GeneratedValue
private long id;
private String firstName;
private String lastName;
private Date birthday;
private String gender;
}
Now we need a join-table to link these two entities; but this is not just a simple join-table. Other than the actor
and movie
columns, this table has some additional attributes. We didn't want to waste storage by adding an ID
column here, instead we used a composite-key consisting of actor
and movie
:
@Data
@Embeddable
public class MovieActorId implements Serializable {
private Actor actor;
private Movie movie;
}
@Data
@Entity
public class MovieActor {
@EmbeddedId
private MovieActorId id;
private int salary;
private String characterName;
}
There are two Many-to-One relations here: MovieActor >-- Actor
and MovieActor >-- Movie
.
Now my main question is: "Assuming the above design, how should I define the @ManyToOne
relationships in this design?"
NOTE: I believe if we add an additional ID
column to the MovieActor
join-table instead of the composite/embedded MovieActorId
, the JPA code will become fairly straight-forward. But suppose we have some sort of limitation, and we need to stick to this design as much as possible.
You need to use @MapsId which provides the mapping for an EmbeddedId
primary key in @ManyToOne
relation
@Data
@Embeddable
public class MovieActorId implements Serializable {
private long actorId;
private long movieId;
// constructor, setter, etc
}
@Data
@Entity
public class MovieActor {
@EmbeddedId
private MovieActorId id;
@ManyToOne(cascade = CascadeType.ALL)
@MapsId("actorId")
private Actor actor;
@ManyToOne(cascade = CascadeType.ALL)
@MapsId("movieId")
private Movie movie;
...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With