Hibernate中的复合ID如何映射Key类

时间:2017-05-15 10:46:32

标签: java spring hibernate jpa hibernate-mapping

如何实现复合键,让我们为参与事件的用户提供一个非常简单的示例,三个数据库表:User,Event,Users_Attending_Events这最后一个表有三个列:userID,eventID;它们与另外两个表的相应ID和成功相关联,这决定了用户是否参加了活动。

我希望参加一个单独的课程,并且不要直接加入用户和活动,因为出席会议包含"成功"信息,必须单独管理。

我的实施

用户对象:

@Entity
@Table(name = "[users]")
public class User implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer userID;
    @JsonIgnore
    @OneToMany(mappedBy = "attend", targetEntity = Attending.class, fetch = FetchType.LAZY)
    private Set<Attending> attendEvents = new HashSet<Attending>();
...
// setters, getters, constructors, equal and hash ...
}

事件:

@Entity
@Table(name = "events")
public class Event implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer eventID;
    @JsonIgnore
    @OneToMany(mappedBy = "attend", targetEntity = Attending.class, fetch = FetchType.LAZY)
    private Set<Attending> participants = new HashSet<Attending>();
...
// setters, getters, constructors, equal and hash ...
}

参加课程:

@Entity
@Table(name = "users_attending_events")
public class Attending implements Serializable {

        @EmbeddedId
        protected AttendingID attend;

        private Integer success;
    ...
    // setters, getters, constructors, equal and hash ...
    }

AttendingID类,用于复合键:

  @Embeddable
  public class AttendingID implements Serializable {

        @ManyToOne(targetEntity = User.class, fetch = FetchType.LAZY)
        @JoinColumn(name = "users_userID", referencedColumnName = "userID")
        private Integer user;

        @ManyToOne(targetEntity = Event.class, fetch = FetchType.LAZY)
        @JoinColumn(name = "events_eventID", referencedColumnName = "eventID")
        private Integer event;
    ...
    // setters, getters, constructors, equal and hash ...
    }

跑步时我得到一个例外:

org.hibernate.MappingException: Foreign key (FKlerh9fv4q1rjiusg0ful3m15j:users_attending_events [events_eventID,users_userID])) must have same number of columns as the referenced primary key (users [userID])

我错过了什么?

1 个答案:

答案 0 :(得分:1)

<强>问题:

Exception非常直截了当地说映射的外键不是预期的类型,而你的问题是你试图在@ManyToOne类型的属性中映射Integer关系。错误的部分在这里。

<强>解决方案:

@ManyToOne注释应引用您案例EntityUser中的映射Event,而不是原始类型或实体的主键。

但是要定义Embeddable主键,您可以在此处选择两个选项:

  1. 仅使用已映射的实体主键作为Embeddable类中的属性。
  2. 您的代码将是:

    @Embeddable
    public class AttendingID implements Serializable {
    
        @Column(name = "users_userID")
        private Integer userID;
    
        @Column(name = "events_eventID")
        private Integer eventID;
    
        ...
        // setters, getters, constructors, equal and hash ...
    }
    
    1. 或者使用两个Mapped实体作为Embeddable Primary键中的属性,并使用@ManyToOne注释引用它们。
    2. 因此,在您的代码中,您只需要更改user

      的类型
      @Embeddable
      public class AttendingID implements Serializable {
      
          @ManyToOne(targetEntity = User.class, fetch = FetchType.LAZY)
          @JoinColumn(name = "users_userID", referencedColumnName = "userID")
          private User user;
      
          @ManyToOne(targetEntity = Event.class, fetch = FetchType.LAZY)
          @JoinColumn(name = "events_eventID", referencedColumnName = "eventID")
          private Event event;
      
          ...
          // setters, getters, constructors, equal and hash ...
      }
      

      <强>文档

      如需进一步阅读和更多选项,您可以查看它显示的5.1.2.1. Composite identifier Section in Hibernate Mapping Documentation,并清楚地解释映射复合主键的所有可能情况。

      编辑:

      重新阅读你的问题后,更好地关注问题,并从设计的角度思考问题,我认为用 a {{1}可以更好地说明你的情况ManyToManyUser实体之间的关系,加入表Event具有额外列Attending ,它将更好地处理您的情况并解决问题。< / p>

      我建议你看看这个Hibernate Many-to-Many Association with Extra Columns in Join Table Example tutorial它显示了一个类似的success解决方案。