我有一个我需要解决的问题。 核心问题是我想在JPA中为JoinTable for ManyToMany关系添加额外的列。就我而言,我有以下实体。
主题是一个简单的实体,它有许多RemoteDocument(一个RemoteDocument可能被许多主题引用,因此它应该是ManyToMany关系)。此外,RemoteDocument实体是只读的,因为它可能只能从Oracle物化视图中读取,而且禁止更改此物化视图。所以我想存储与某些主题相关的RemoteDocuments的顺序。事实上,我可以使用其他实体做类似的事情:
@Entity
public class Topic {
@Id
private Long id;
@Basic
private String name;
@OneToMany
private Set<TopicToRemoteDocument> association;
}
@Entity
public class RemoteDocument {
@Id
private Long id;
@Basic
private String description;
}
@Entity
public class TopicToRemoteDocument {
@OneToOne
private Topic topic;
@OneToOne
private RemoteDocument remoteDocument;
@Basic
private Integer order;
}
在这种情况下,附加实体TopicToRemoteDocument帮助我用OneToMany替换ManyToMany关联并添加额外的字段顺序。
但是我想拥有ManyToMany关系,但是在连接表中配置了额外的列
答案 0 :(得分:10)
使用list而不是set,以及@OrderColumn
注释,JPA将自动处理订单:
@MappedSuperclass
public class BaseEntity{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
public Long getId(){
return id;
}
public void setId(final Long id){
this.id = id;
}
}
@Entity
public class Topic extends BaseEntity{
@ManyToMany(mappedBy = "topics")
@OrderColumn
private List<Document> documents = new ArrayList<Document>();
public List<Document> getDocuments(){
return documents;
}
public void setDocuments(final List<Document> documents){
this.documents = documents;
}
}
@Entity
public class Document extends BaseEntity{
@ManyToMany
@OrderColumn
private List<Topic> topics = new ArrayList<Topic>();
public List<Topic> getTopics(){
return topics;
}
public void setTopics(final List<Topic> topics){
this.topics = topics;
}
}
生成的DDL(使用hibernate和HSQL):
create table Document (
id bigint generated by default as identity (start with 1),
primary key (id)
);
create table Document_Topic (
documents_id bigint not null,
topics_id bigint not null,
topics_ORDER integer not null,
documents_ORDER integer not null,
primary key (documents_id, topics_ORDER)
);
create table Topic (
id bigint generated by default as identity (start with 1),
primary key (id)
);
alter table Document_Topic
add constraint FK343B5D0B481100B2
foreign key (documents_id)
references Document;
alter table Document_Topic
add constraint FK343B5D0B558627D0
foreign key (topics_id)
references Topic;
答案 1 :(得分:2)
除非您允许重复,否则我会尽量避免使用List
。
有一个@OrderColumn
注释会自动执行此操作。你试过吗?
@Entity
public class Topic {
@Id
private Long id;
@Basic
private String name;
@OneToMany
@OrderColumn
private Set<TopicToRemoteDocument> association;
}
答案 2 :(得分:0)
在创建多对多映射类实体时,一种有用的技术是将类中的id与@ManyToOne指定一起归属,这使得该类充当复合键类:
@Entity
@Table(name = "market_vendor")
public class MarketVendor implements Serializable
{
@Id
@ManyToOne
@JoinColumn(name = "market_id")
private Market market;
@Id
@ManyToOne
@JoinColumn(name = "vendor_id")
private Vendor vendor;
@Basic
@Column(name="active")
private boolean active;
public MarketVendor(Market market, Vendor vendor, boolean active)
{
this.market = market;
this.vendor = vendor;
this.active = active;
}
}
这允许您在同一个类中定义复合主键,而不必拥有单独的主键类。您还需要使类可序列化。