当前位置: 首页 > 知识库问答 >
问题:

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

沈俊晤
2023-03-14

有趣的是,对于一个看似常见的场景,我找不到任何解决方案!所以,我在这里要求向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;
}

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

@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

现在我的主要问题是:“假设上述设计,我应该如何定义这个设计中的@ManyToOne关系?”

注意:我相信如果我们在MovieActor连接表中添加一个额外的ID列,而不是复合/嵌入的MovieActorId,JPA代码将变得相当简单。但是假设我们有某种限制,我们需要尽可能地坚持这种设计。


共有1个答案

庾远航
2023-03-14

您需要使用@MapsId,它为关系中的嵌入ID主键提供映射

@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;
    ...
}
 类似资料:
  • 我为这个特殊的问题找了很多,但我没有找到任何具体的解决办法。我在一个表中有一个复合主键,这个复合主键的一个字段是另一个表的复合主键的一部分。您可以说这个特定的字段是第二个表中的外键,但是在表定义中没有定义任何独占外键约束。对于第一个表中的每个rec,第二个表中可能有多条记录。我试图使用SPringBoot-JPA-Hibernate实现这一点,但无法实现。有人能帮我吗。以下是德泰:- 我有一个US

  • 问题内容: 如何使用复合主键作为外键?看来我的尝试无效。 问题答案: 该行: 是错的。您不能那样使用,这只是父表中PK约束的名称。要将复合主键用作外键,您必须向子表中添加相同数量(组成PK)的相同数据类型的列,然后在定义中使用这些列的组合:

  • 如何将复合主键用作外键?看来我的尝试没有成功。

  • 我发现很难创建复合外键。我想要一个会话表,它同时具有'movieid'和'cinemaid'作为复合外键。这是因为一个会话需要电影和电影院位置。 我当前的模式如下所示: Schema::create('session',函数(Blueprint$表){ }); 关于如何在laravel中创建复合外键,我找不到太多信息。我发现的最好的事情是: http://www.geexie.com/compos

  • 问题内容: 我想做这样的事情: 对象ReportingFile可以是LogRequest或LogReport文件。(两者结构相同) 一个对象Reporting,其中包含一个logRequest,其中包含带日期的logReport列表。 我试图设置一个EmbededId,这将是logRequest的属性。这就是我遇到的问题。我没有来管理嵌入式ID。(http://docs.jboss.org/hib

  • 我有一些实体: 当我试图保存新的cbonus记录时,出现异常: org.postgresql.util.PSQLException: ERROR: null值在列"bank_id"的关系"cBonus"违反了非空约束详细信息:失败的行包含(773, gp3, null, null, f)。 和查询 DEBUG 24817-[nio-8080-exec-4]org . hibernate . SQL