JPA 多对多,带有额外列

发布于 2024-09-29 16:33:16 字数 856 浏览 0 评论 0原文

我有一个需要解决的问题。 核心问题是我想在 JPA 中的 ManyToMany 关系的 JoinTable 中添加额外的列。就我而言,我有以下实体。

Topic是一个简单的实体,它有许多RemoteDocument(一个RemoteDocument可能被许多Topic引用,因此它应该是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 关联并添加额外的字段顺序。

但我想要拥有多对多关系,但在连接表中配置了附加列

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. 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). 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. So I want to store order of RemoteDocuments related to some Topic. 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.

But I want to have ManyToMany relation but with configured additional column in join table

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

漆黑的白昼 2024-10-06 16:33:17

我会尽量避免使用 List 除非你允许重复。

有一个 @OrderColumn 注释可以自动执行此操作。你尝试过吗?

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

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

I would try to avoid using a List unless you allow duplicates.

There is a @OrderColumn annotation that automatically does this. Have you tried it?

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

 @OneToMany
 @OrderColumn
 private Set<TopicToRemoteDocument> association;
}
黯淡〆 2024-10-06 16:33:17

创建多对多映射类实体时有用的一种技术是将类中的 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;
  }
}

这允许您定义复合主键在同一个类中,无需有单独的主键类。您还需要使该类可序列化。

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:

@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.

轮廓§ 2024-10-06 16:33:16

使用列表而不是集合,再加上@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;

Use list instead of set, together with the @OrderColumn annotation and JPA will automatically take care of the order:

@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):

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文