简体   繁体   English

JPA很多都有额外的列

[英]JPA many to many with extra column

I have a following problem that I need to solve. 我有一个我需要解决的问题。 The core issues is that I want to add additional column into JoinTable for ManyToMany relation in JPA. 核心问题是我想在JPA中为JoinTable for ManyToMany关系添加额外的列。 In my case I have following entities. 就我而言,我有以下实体。

The Topic is a simple entity which has many RemoteDocument's (one RemoteDocument may be refered by many Topic's, hence it should be ManyToMany relation). 主题是一个简单的实体,它有许多RemoteDocument(一个RemoteDocument可能被许多主题引用,因此它应该是ManyToMany关系)。 Also RemoteDocument entity is read only because it may be read only from Oracle Materialized View moreover any altering of this Materialized View is forbidden. 此外,RemoteDocument实体是只读的,因为它可能只能从Oracle物化视图中读取,而且禁止更改此物化视图。 So I want to store order of RemoteDocuments related to some Topic. 所以我想存储与某些主题相关的RemoteDocuments的顺序。 In fact I can do something like that with additional entity: 事实上,我可以使用其他实体做类似的事情:

@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;
}

In this case additional entity TopicToRemoteDocument helps me to replace ManyToMany association with OneToMany and add extra field order. 在这种情况下,附加实体TopicToRemoteDocument帮助我用OneToMany替换ManyToMany关联并添加额外的字段顺序。

But I want to have ManyToMany relation but with configured additional column in join table 但我想拥有ManyToMany关系,但在连接表中配置了额外的列

Use list instead of set, together with the @OrderColumn annotation and JPA will automatically take care of the order: 使用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;
    }

}

Generated DDL (using hibernate and HSQL): 生成的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;

I would try to avoid using a List unless you allow duplicates. 我会尽量避免使用List除非你允许重复。

There is a @OrderColumn annotation that automatically does this. 有一个@OrderColumn注释可以自动执行此操作。 Have you tried it? 你试过吗?

@Entity
public class Topic {
 @Id
 private Long id;
 @Basic
 private String name;

 @OneToMany
 @OrderColumn
 private Set<TopicToRemoteDocument> association;
}

One technique that is useful when creating the many-to-many mapping class entity is to attribute the id's in the class along with @ManyToOne designation which makes this class act as the composite key class: 在创建多对多映射类实体时,一种有用的技术是将类中的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;
  }
}

This allows you to have the composite primary key defined within the same class without having to have a separate primary key class. 这允许您在同一个类中定义复合主键,而无需具有单独的主键类。 You also need to make the class serializable. 您还需要使类可序列化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM