首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >spring-data:外键作为主键

spring-data:外键作为主键
EN

Stack Overflow用户
提问于 2021-11-05 16:53:49
回答 2查看 80关注 0票数 0

我有一个有100个字段的表,我想把它分成3-4个表。在创建时,其中一个表的主键将变为外键,其余表的主键将变为主键。

我试过这样的方法

代码语言:javascript
复制
@Entity
public class Entity1 implements Serializable {
    @Id
    @Column(name = "id")
    private String id;
    
    ...
}

@Entity
@IdClass(Entity1.class)
public class Entity2 implements Serializable {
    @Id
    @OneToOne
    @JoinColumn(name = "id",  referencedColumnName = "id")
    private Entity1 id;
    
    ...
}


@Repository
public interface Entity1Repository extends JpaRepository<Entity1, String> {
    Optional<Entity1> findById(String id);
}

@Repository
public interface Entity2Repository extends JpaRepository<Entity2, Entity1> {
    Optional<Entity2> findById(Entity1 id);
}

它正在创建表,但将错误作为类xyz.Entity2没有定义IdClass

还查看了很少的引用,比如使用@MapsId。但不是解决方案对我有用。有投入吗?

谢谢

文卡塔·马杜

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-11-05 19:48:04

我不知道您用MapsId特性尝试了什么方法。但在这种情况下它确实能帮到你。下面是使用MapsId实现的示例代码:

代码语言:javascript
复制
@Entity
public class Entity1 implements Serializable {
    @Id
    private Long id;
    private String name;

    @OneToOne(mappedBy = "entity1")
    private Entity2 entity2;

    @OneToOne(mappedBy = "entity1")
    private Entity3 entity3;
}

这是只保存OneToOne关联引用的父类。这孩子将是这种关系的主人。

这是您的Entity2孩子:

代码语言:javascript
复制
@Entity
public class Entity2 implements Serializable {
    @Id
    private Long id;
    private String value;

    @MapsId
    @OneToOne(cascade = CascadeType.PERSIST)
    @JoinColumn(name = "id")
    private Entity1 entity1;
}

正如您所说的,您将将您的主实体拼接成多个子实体,我继续使用另一个子实体来澄清我的观点:

代码语言:javascript
复制
@Entity
public class Entity3 implements Serializable {
    @Id
    private Long id;
    private String value;

   @MapsId
   @OneToOne(cascade = CascadeType.PERSIST)
   @JoinColumn(name = "id")
   private Entity1 entity1;
}

你可能已经注意到我现在用的是:

  1. 子类中的@JoinColumn注释告诉hibernate使用子类的id列将OneToOne关系映射到Entity1类。
  2. 我在子类中使用cascadeType =持久化。

第一步是使用id执行关系映射所必需的。第二步需要将所有3个实体保存到同一事务中的数据库中。稍后再谈这个。

让我们看看现在如何将所有这些实体保存到数据库中。

代码语言:javascript
复制
@Transactional
public void saveEntities() {
    Long id = 1L;
    Entity1 entity1 = new Entity1();
    entity1.setId(id);
    entity1.setName("Test1Entity1: " + id);

    Entity2 entity2 = new Entity2();
    entity2.setValue("entity2Value: " + id);
    entity2.setEntity1(entity1);
    entity2Repository.save(entity2);
    Entity3 entity3 = new Entity3();
    entity3.setValue("Test3Entity:" + id);
    entity3.setEntity1(entity1);
    entity3Repository.save(entity3);
}

注意,我没有在存储库中保存Entity1类。它是由cascadeType=PERSIST参数保存的,我传递给了OneToOne注释操作。

这应该能够保存所有实体以及父实体。

注意:,我刚才提到了cascadeType=PERSIST,以及为什么它在这里很重要。如果不使用该方法,则必须显式调用Entity1存储库方法以将其对象保存到数据库中,然后可以将它们设置为子实体。但是如果这样做,hibernate将在对子实体执行保存操作时抛出:a different object with the same identifier value was already associated with the session异常。

票数 0
EN

Stack Overflow用户

发布于 2021-11-05 20:02:05

尝试使用@PrimaryKeyJoinColumn

代码语言:javascript
复制
@Entity
public class Entity1 {
    @Id
    @Column(name = "id")
    private String id;
    
    ...

    @OneToOne(mappedBy = "entity1")
    @PrimaryKeyJoinColumn
    private Entity2 entity2;
}

@Entity
public class Entity2 {
    @Id
    @Column(name = "entity1_id")
    private String id;
    
    ...

    @MapsId
    @OneToOne(cascade = CascadeType.PERSIST)
    @JoinColumn(name = "entity1_id)
    private Entity1 entity1;
}

public interface Entity2Repository extends JpaRepository<Entity2, String>

测试:

代码语言:javascript
复制
@Test
void save() {
    Entity1 entity1 = new Entity1();
    entity1.setId("iddddd");

    Entity2 entity2 = new Entity2();
    detail.setEntity1(entity1);

    this.entity2Repository.save(entity2);
}

参考共享主键

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69856669

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档