【问题标题】:JPA many to many with extra column带有额外列的 JPA 多对多
【发布时间】:2010-10-28 08:46:55
【问题描述】:

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

主题是一个简单的实体,它有许多远程文档(一个远程文档可能被许多主题引用,因此它应该是多对多关系)。此外,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 关联并添加额外的字段顺序。

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

【问题讨论】:

  • 您的 JPA 提供商是什么? JPA 1.0 对此没有标准化注释,但您的 JPA 提供者可能有扩展。

标签: java jpa many-to-many


【解决方案1】:

使用列表代替集合,加上@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(使用休眠和 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;

【讨论】:

  • 感谢您的回答,这正是我所需要的,只是我使用的是 JPA 1.0 而不是 JPA 2.0...所以看起来我需要迁移到 JPA 2.0
  • a) 如果它是正确的答案,你应该接受它 b) 我认为我的答案中没有关于 JPA 2 的任何具体内容。也应该与 JPA 1 一起使用。哦,OrderColumn 是 JPA 2,不知道。
【解决方案2】:

除非您允许重复,否则我会尽量避免使用 List

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

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

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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 2014-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-06
      • 2018-02-19
      • 1970-01-01
      相关资源
      最近更新 更多