使用JPA和Hibernate提供程序的ManyToMany关系不会创建主键

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用JPA和Hibernate提供程序的ManyToMany关系不会创建主键相关的知识,希望对你有一定的参考价值。

我使用Hibernate作为具有ManyToMany关系的提供程序创建了两个JPA实体(Client,InstrumentTraded)。让Hibernate为mysql生成表后,看起来ManyToMany关系表不包含两个外键的主键。这允许多对多表中的重复记录,这不是期望的结果。

生成的表:

client(id,name)  
instrument_traded(id,name)  
client_instrument_traded(FK client_id, FK instrument_traded_id)

首选表格:

client_instrument_traded(PK,FK client_id, PK,FK instrument_traded_id)

实体:

@Entity
public class Client extends AbstractEntity<Integer> {

    private static final long serialVersionUID = 1L;

    @Basic(optional = false)
    @Column(nullable = false, length = 125)
    private String name;

    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(joinColumns = {
        @JoinColumn}, inverseJoinColumns = {
        @JoinColumn(name = "instrument_traded_id")}, uniqueConstraints =
    @UniqueConstraint(name = "UK_client_instruments_traded_client_id_instrument_traded_id",
    columnNames = {"client_id", "instrument_traded_id"}))
    @ForeignKey(name = "FK_client_instruments_traded_client_id",
    inverseName = "FK_client_instruments_traded_instrument_traded_id")
    private List<InstrumentTraded> instrumentsTraded;

    public Client() {
    }

    public List<InstrumentTraded> getInstrumentsTraded() {
        return instrumentsTraded;
    }

    public void setInstrumentsTraded(List<InstrumentTraded> instrumentsTraded) {
        this.instrumentsTraded = instrumentsTraded;
    }

    ...
}



@Entity
@Table(uniqueConstraints = {
    @UniqueConstraint(name = "UK_instrument_traded_name", columnNames = {"name"})})
public class InstrumentTraded extends AbstractEntity<Integer> {

    private static final long serialVersionUID = 1L;

    @Basic(optional = false)
    @Column(nullable = false, length = 50)
    private String name;

    @ManyToMany(mappedBy = "instrumentsTraded", fetch = FetchType.LAZY)
    private List<Client> clients;

    public InstrumentTraded() {
    }

    public List<Client> getClients() {
        return clients;
    }

    public void setClients(List<Client> clients) {
        this.clients = clients;
    }

    ...

}

在做了一些研究后,看起来唯一的解决方案是mapping a join table with additional columns使用@OneToMany @IdClass和复合主键类,当我不需要额外的列时。除了我在上面的代码中包含的那个之外,这是唯一的解决方案,它使用@UniqueConstraint@ManyToMany映射中的两个外键列吗?像这样的常见场景所需的工作量似乎有点荒谬。谢谢!

答案

我遇到了类似的问题。我所做的只是将集合类型从List更改为Set:

private List<InstrumentTraded> instrumentsTraded;

private Set<InstrumentTraded> instrumentsTraded;

不知何故,Hibernate现在为连接表生成主键。

另一答案

这是解决问题的方法:

client.Java:

 @ManyToMany(fetch = FetchType.EAGER,cascade = CascadeType.ALL)
 @JoinTable(
        joinColumns = {@JoinColumn(name = "client_id")},
        inverseJoinColumns = {@JoinColumn(name = "instrument_traded_id")},
        uniqueConstraints = {@UniqueConstraint(
            columnNames = {"client_id", "instrument_traded_id"})}
)
 private List<InstrumentTraded> instrumentsTraded;

这适用于单向映射。如果需要双向关系,请将InstrumentTraded.class中的映射更改为相同。

另一答案

您的映射看起来很奇怪(特别是joinColumn注释的@JoinTable部分)。我希望这样的事情:

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(
    joinColumns= 
        @JoinColumn(name="CLIENT_ID", referencedColumnName="ID"), 
    inverseJoinColumns=
        @JoinColumn(name="instrument_traded_id", referencedColumnName="ID"),
    uniqueConstraints=
        @UniqueConstraint(
            name="UK_client_instruments_traded_client_id_instrument_traded_id",
            columnNames = {"client_id", "instrument_traded_id"}
        )
)
@ForeignKey(name = "FK_client_instruments_traded_client_id",
inverseName = "FK_client_instruments_traded_instrument_traded_id")
private List<InstrumentTraded> instrumentsTraded;

但除非你想覆盖默认值(我猜你这样做),我会跳过@JoinTable

另一答案

或者将@ManyToMany拆分为@OneToMany - @ManyToOne关系请参阅here如何完成此映射

以上是关于使用JPA和Hibernate提供程序的ManyToMany关系不会创建主键的主要内容,如果未能解决你的问题,请参考以下文章

使用JPA和Hibernate提供程序的ManyToMany关系不会创建主键

Spring,JPA,Hibernate,Atomikos - 奇怪的启动错误

如何将 Hibernate 配置为 Payara/Glassfish 4.1 的 JPA 提供程序? [关闭]

如何使用休眠将mysql与Java连接?例外:没有名为 org.hibernate.tutorial_jpa 的 EntityManager 的持久性提供程序 [关闭]

Spring Data JPA 是不是在内部使用 Hibernate 以及如果我不提供方言属性,为啥我的应用程序正在运行?

如何使用 Hibernate JPA 和 Spring Framework 启用加载时间/运行时编织