Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing Composite (Embedded-ID) Foreign Key Relations using Spring Data JPA

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.

like image 720
Seyed Mohammad Avatar asked Sep 17 '25 06:09

Seyed Mohammad


1 Answers

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;
    ...
}
like image 133
Eklavya Avatar answered Sep 19 '25 18:09

Eklavya