【问题标题】:How to create a foreign key to columns of an ElementCollection in JPA?如何在 JPA 中为 ElementCollection 的列创建外键?
【发布时间】:2020-11-09 14:58:13
【问题描述】:

给定以下类模型:

package demo;

import java.util.Map;
import java.util.Set;
import javax.persistence.*;

@Embeddable
class Address {
  String street;
}

@Embeddable
class AddressDetails {
  byte[] photo;
}

@MappedSuperclass
abstract class User {
  @Id Long id;
  @ElementCollection(fetch = FetchType.EAGER) Set<Address> addresses;
  @ElementCollection Map<Address, AddressDetails> addressDetails; // wanted: FK to addresses
}

@Entity
class Sub1 extends User {}

@Entity
class Sub2 extends User {}

我试图告诉 JPA addressDetails 引用来自 addresses 的行。我该怎么做?

这是我想转换为注释的外键约束:

ALTER TABLE sub1_address_details
    ADD CONSTRAINT FK_sub1_address_address_details
        FOREIGN KEY (sub1_id, address_id)
            REFERENCES sub1_addresses
            ON DELETE CASCADE;

这是Hibernate当前生成的外键约束:

    alter table vblife_pv.sub1_addresses 
       add constraint FKdm58cvoq5gqndtlpr4t7auyct 
       foreign key (sub1_id) 
       references sub1

我尝试添加

@CollectionTable(joinColumns = {@JoinColumn(table = "addresses", referencedColumnName = "id")})

到addressDetails,但这不会改变 Hibernate 的 DDL 输出。

我使用的是 Hibernate 5.4.21。

【问题讨论】:

  • ElementCollection 的整个想法是使用基本类型而不需要过多的 JPA 映射,但如果您想使用 Address 作为适当的实体(@OneToMany 与 AddressDetails 的关系)那么使用ElementCollection 没有任何意义。
  • 这个例子是一个真实商业案例的简化。 Address 强烈依赖于 User,AddressDetails 是对 Address 的每个用户的附加。 Address 和 AddressDetails 在用户上下文之外都没有意义,因此没有身份。
  • 可能是这样,但这不是ElementCollection 的重点,在我看来,模拟这种行为比让Address 成为引用@987654336 的ElementCollection 的实体要努力得多@

标签: java hibernate jpa foreign-keys


【解决方案1】:

如果你真的想要,你可能应该使用以下内容:

@Entity
@Table(name = "addresses")
public class UserAddress {
    @EmbeddedId
    UserAddressId id;
    @ManyToOne(LAZY)
    @JoinColumn(name = "address_id", insertable = false, updatable = false)
    Address address;
    @ManyToOne(LAZY)
    @JoinColumn(name = "user_id", insertable = false, updatable = false)
    User user;
    @OneToOne(mappedBy = "userAddress")
    AddressDetails details;
}
@Embeddable
public class UserAddressId {
    int addressId;
    int userId;
}
@Entity
@Table(name = "address_details")
public class AddressDetails {
    @EmbeddedId
    UserAddressId id;
    @OneToOne
    @JoinColumns({
    @JoinColumn(name = "user_id", referencedColumn = "user_id", insertable = false, updatable = false),
    @JoinColumn(name = "address_id", referencedColumn = "address_id", insertable = false, updatable = false)
    })
    UserAddress userAddress;
}

【讨论】:

  • 非常感谢您的建议。不幸的是,我意识到我正在寻找的外键约束无效(从业务逻辑的角度来看)为时已晚,所以我无法验证您的建议是否能解决我的问题。
猜你喜欢
  • 1970-01-01
  • 2012-12-17
  • 2020-07-04
  • 1970-01-01
  • 1970-01-01
  • 2018-08-14
  • 1970-01-01
  • 2012-08-08
  • 1970-01-01
相关资源
最近更新 更多