2010-08-13 47 views
7

我已经创建了两个使用Hibernate作为具有ManyToMany关系的提供程序的JPA实体(Client,InstrumentTraded)。让Hibernate为MySQL生成表之后,似乎ManyToMany关系表不包含这两个外键的主键。这允许多对多表中的重复记录,这不是所需的结果。使用JPA与Hibernate提供程序的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映射中的两个外键列?对于像这样的常见场景所需的工作量似乎有点荒谬。谢谢!

+0

http://stackoverflow.com/questions/1212058/how-to-make-a-composite-primary-key-java-persistence-annotation/6344626#6344626 – steveeen 2011-06-14 14:14:39

+0

还值得检查,如果你意外地没有添加一个记录两次,这发生在我身上,所以'list.add(x); list.add(x);'结果在列表中重复。 – CsBalazsHungary 2014-10-30 15:58:57

回答

2

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

@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

+0

我想重写默认值,因为它将instrument_traded_id(instruments_traded_id)复数化。我有一个自定义命名策略,如果“_id”不存在于外键的末尾,则会添加“_id”。我可以删除joinColumns = @ JoinColumn。你有没有一个ManyToMany的例子,在ManyToMany表中创建一个由两个外键组成的主键? – dukethrash 2010-08-13 14:00:43

+0

@dukethrash:'您是否有一个ManyToMany的示例,在ManyToMany表中创建一个由两个外键组成的主键?'如果正确注释,这是默认行为。你有没有'joinColumn'(或上面的那个)? – 2010-08-13 14:15:26

+0

是的我试过你(除了referencedColumn实际上是referencedColumnName),它仍然没有生成主键。我甚至在InstrumentTraded上添加了以下内容,以查看是否会改变任何内容。 @ManyToMany(fetch = FetchType.LAZY,mappedBy =“instrumentsTraded”) private List clients; – dukethrash 2010-08-13 14:55:26

0

或者分裂您@ManyToMany到@OneToMany - @ManyToOne关系见here如何完成这个映射

6

下面就来解决这个问题的方法:

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中的映射更改为相同。

15

我有类似的问题。我所做的只是我从名单改变了集合类型设置:

private List<InstrumentTraded> instrumentsTraded; 

private Set<InstrumentTraded> instrumentsTraded; 

不知怎么现在的Hibernate生成的连接表的主键。

+0

“所有伟大的事情都很简单...” – 2013-02-23 08:28:36

+0

是吗?还是仅仅是Java集在内存中进行工作? – ViniciusPires 2014-08-02 19:26:02

+0

另外值得检查一下,如果你意外没有两次添加记录,这发生在我身上,所以'list.add(x); list.add(x);'结果在列表中重复。 – CsBalazsHungary 2014-10-30 15:57:26

相关问题