java - 具有复合键的单边 OneToMany 也是外键,应该使用 @IdClass 还是 @Embeddable?

标签 java hibernate jpa composite-primary-key composite-key

我很难决定是使用 @IdClass 还是 @Embeddable 来为下面所示的 OneToMany 数据库关系建模复合主键。

relationship table

user_iduser 表的主键,user_merchant 同时使用 merchant_id user_id 作为其组合键。一个用户可以与多个商家进行交易,反之亦然。 user_merchant 表跟踪用户和商家之间的关系。

由于“用户”是唯一需要了解其关系的人,而不是商家,因此我将其建模为单向一对多关系。

在用户实体中,我希望像这样建模:

@Entity
@Table(name = "user")
public class User extends Serializable{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column
    private Long userId;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private Set<Merchant> merchants;

}

对于商家实体来说,这有点棘手。

public class Merchant implements Serializable{

    @Column
    private String merchantId;

    .....

}

如果Merchant类中没有指定@Id,则运行这段代码将会失败。我不确定在这种情况下是否应该使用@IdClass或@Embedded/@Embeddable,以及其中一个相对于另一个的好处是什么。

我可以避免像大多数解决方案所示那样在 Merchant 类中引入新的 User 对象吗?因为商家并不真正需要了解用户。

@Id
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "location_id")
private User user;

User 对象首次保存时,如何填充此字段?如果可能的话,我认为我不需要在已经是同一用户对象的属性的商家对象内使用另一个用户引用。

提前致谢!

最佳答案

这是我解决这个问题的方法:

我已将这种关系确定为父对象和子对象之间单边一对多关系的情况,其中子对象的复合主键部分由父对象的外键组成。

最后,我选择使用@IdClass,因为我仍然需要访问merchantId,而且这似乎是最简单的方法。

我在 User 类中所做的唯一更改是删除 @JoinColumn(name = "user_id") 并将其替换为 @OneToMany 中的 mappedBy = "user"。如果没有此更改,第一次保留此实体效果很好,但是当我尝试更新此实体并从集合中删除商家时,它给了我一些错误。

@Entity
@Table(name = "user")
public class User extends Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column
    private Long userId;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, 
               mappedBy = "user", fetch = FetchType.LAZY)
    private Set<Merchant> merchants;

    @PrePersist
    public void prePersistUser() {
        if (this.merchants != null) {
            this.merchants.forEach(merchant-> {
            merchant.setUser(this);
            });
        }
    }

}

对于商家类,我通过@IdClass将MerchantPK.class链接到Merchant.java。

我还确保@JoinColumn内的insertableupdatable = false,因为这种关系是单方面的,并且只能从父级(用户)侧插入/更新。

@Entity
@IdClass(MerchantPK.class)
@Table(name = "user_merchant")
public class Merchant {

    @Id
    @Column(nullable = false)
    private String merchantId;


    @Id
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id", insertable = false, updatable = false)
    private UserEntity user;

}

在单边一对多关系的情况下,只需要 1 个 @JoinColumn,在本例中,它位于 @ManyToOne 所在的位置。即使使用mappedBy,带有@OneToMany的对象仍然是关系的所有者,因为我们指定了insertable = falseupdatable = false

关于java - 具有复合键的单边 OneToMany 也是外键,应该使用 @IdClass 还是 @Embeddable?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61214642/

相关文章:

JavaFX:如何选择图 block 并添加数字和边框线?

Java JPA Hibernate SqlResultSetMapping 别名

java - 计算字符串数组中每个单词最后一次出现后的单词数

java - 值引擎不是对象 android.speech.tts.TextToSpeech 的成员

触发了 hibernate 实体拦截器但设置值不保存

java - JPA:实现模型层次结构 - @MappedSuperclass 与 @Inheritance

java - JPA 事务未回滚持久调用。仅在 MySQL 上插入和提交忽略事务规则

java - JPA:在@Query 中使用 AttributeConverter

java - 如何配置Spring Boot在路由不存在时抛出404错误?

java - Hibernate session 工厂