英文:
Implementing Composite (Embedded-ID) Foreign Key Relations using Spring Data JPA
问题
有趣的是,我找不到任何关于这个看似常见情景的解决方案!因此,我在这里提问,希望能从 Spring Data JPA 的经验丰富的专业人士那里学习。我会考虑使用 Lombok 来使示例代码更加简洁。
考虑一个简单的 IMDB 示例 Web 应用程序。我已经定义了两个简单的实体如下:
@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;
}
现在我们需要一个联结表来链接这两个实体;但这不仅仅是一个简单的联结表。除了 actor
和 movie
列,这个表还有一些额外的属性。我们不想通过在这里添加一个 ID
列来浪费存储空间,而是使用了由 actor
和 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;
}
这里有两个多对一关系:MovieActor >-- Actor
和 MovieActor >-- Movie
。
现在我主要的问题是:“在上述设计的基础上,我应该如何定义 @ManyToOne
关系?”
**注意:**我认为,如果我们在 MovieActor
联结表中添加一个额外的 ID
列,而不是使用复合/嵌入式的 MovieActorId
,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.
答案1
得分: 4
你需要使用 @MapsId,它提供了在 @ManyToOne
关系中映射 EmbeddedId
主键的功能。
@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;
...
}
英文:
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;
...
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论