使用Spring Data JPA实现复合(嵌入式ID)外键关系

huangapple go评论74阅读模式
英文:

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

现在我们需要一个联结表来链接这两个实体;但这不仅仅是一个简单的联结表。除了 actormovie 列,这个表还有一些额外的属性。我们不想通过在这里添加一个 ID 列来浪费存储空间,而是使用了由 actormovie 组成的复合键:

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

huangapple
  • 本文由 发表于 2020年10月24日 23:14:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/64514889.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定