使用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 以及如果我不提供方言属性,为啥我的应用程序正在运行?