title: JPA - class does not define an IdClass - IllegalArgumentException
body: <p>I have a base JPA entity and all other entities derive from that. But when I start application, it gives IllegalArgumentException: This class [class demo.rbacapp.entity.UserAccountRole] does not define an IdClass.</p>
  
  <p>I am trying to create many-to-many relation between UserAccount and Role using @Embeddable primary key UserAccountRolePk. </p>
  
  <p>Can anyone point me if I am missing something ? What is the reason to complain about missing IdClass when I am having EmbeddedId here.</p>
  
  <pre><code>@MappedSuperclass
  public class BaseEntity implements Serializable {
      private static final long serialVersionUID = 1L;
  
      @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) 
      @Column(name = "id", nullable = false)
      private long id;
  
      @UpdateTimestamp @Column(name = "update_timestamp", nullable = false)
      @Temporal(TemporalType.TIMESTAMP)
      private Date updateTimestamp;
  
      public long getId() {
          return id;
      }
  
      public void setId(long id) {
          this.id = id;
      }
  
      public Date getUpdateTimestamp() {
          return updateTimestamp;
      }
  
      public void setUpdateTimestamp(Date updateTimestamp) {
          this.updateTimestamp = updateTimestamp;
      }
  }
  </code></pre>
  
  <p>These are the actual entities.</p>
  
  <pre><code>@Entity @Table(name = "USER_ACCOUNT")
  @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
  @AttributeOverride(name = "id", column = @Column(name="user_id"))
  public class UserAccount extends BaseEntity {
      private static final long serialVersionUID = 1234567890L;
  
      @Column(name = "username", unique = true)   //username has to be unique
      private String username;
  
      @Column(name = "first_name")
      private String firstName;
  
      @Column(name = "last_name")
      private String lastName;
  
      @Column(name = "age")
      private int age;
  
      @Column(name = "gender")
      private String gender;
  
      @Column(name = "password")
      private String password;
  
      @OneToMany(mappedBy = "userAccountRolePk.role", cascade = CascadeType.ALL)
      private Set&lt;UserAccountRole&gt; userAccountRoles = new HashSet&lt;&gt;();
  
      public Set&lt;UserAccountRole&gt; getUserAccountRoles() {
          return userAccountRoles;
      }
  
      public void setUserAccountRoles(Set&lt;UserAccountRole&gt; r) {
          this.userAccountRoles = r;
      }
  
      public void addUserAccountRoles(UserAccountRole r) {
          this.userAccountRoles.add(r);
      }
  
      public String getPassword() {
          return password;
      }
  
      public void setPassword(String password) {
          this.password = password;
      }
  
      public String getUsername() {
          return username;
      }
  
      public void setUsername(String username) {
          this.username = username;
      }
  
      public String getFirstName() {
          return firstName;
      }
  
      public void setFirstName(String firstName) {
          this.firstName = firstName;
      }
  
      public String getLastName() {
          return lastName;
      }
  
      public void setLastName(String lastName) {
          this.lastName = lastName;
      }
  
      public int getAge() {
          return age;
      }
  
      public void setAge(int age) {
          this.age = age;
      }
  
      public String getGender() {
          return gender;
      }
  
      public void setGender(String gender) {
          this.gender = gender;
      }
  }
  
  @Entity
  @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
  @AttributeOverride(name = "id", column = @Column(name="role_id"))
  public class Role extends BaseEntity {
      private static final long serialVersionUID = 1234567893L;
  
      @Column(name = "name")
      private String name;
  
      @Column(name = "description")
      private String description;
  
      /* if true, then cannot be updated by users or rest api */
      @Column(name = "immutable")
      private boolean immutable;  
  
      @OneToMany(mappedBy = "rolePriviledgePk.role", cascade = CascadeType.ALL)
      private Set&lt;RolePriviledge&gt; rolePriviledges = new HashSet&lt;&gt;();
  
      public Set&lt;RolePriviledge&gt; getRolePriviledges() {
          return rolePriviledges;
      }
  
      public void setRolePriviledges(Set&lt;RolePriviledge&gt; rolePriviledges) {
          this.rolePriviledges = rolePriviledges;
      }
  
      public void addRolePriviledges(RolePriviledge rolePriviledge) {
          this.rolePriviledges.add(rolePriviledge);
      }
  
      public String getName() {
          return name;
      }
  
      public void setName(String name) {
          this.name = name;
      }
  
      public String getDescription() {
          return description;
      }
  
      public void setDescription(String description) {
          this.description = description;
      }
  
      public boolean isImmutable() {
          return immutable;
      }
  
      public void setImmutable(boolean immutable) {
          this.immutable = immutable;
      }
  
      public static long getSerialversionuid() {
          return serialVersionUID;
      }
  }
  </code></pre>
  
  <p>This is the join class (many-to-many).</p>
  
  <pre><code>@Entity
  @Table(name = "USERACCOUNT_ROLES")
  @AssociationOverrides(
      { @AssociationOverride(name = "userAccountRolePk.userAccount",
          joinColumns = @JoinColumn(name = "USER_ID")),
      @AssociationOverride(name = "userAccountRolePk.role",
          joinColumns = @JoinColumn(name = "ROLE_ID")) 
  })
  @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
  public class UserAccountRole extends BaseEntity {
      //composite primary key
      @EmbeddedId
      private UserAccountRolePk userAccountRolePk = new UserAccountRolePk();
  
      //additional fields if any (updateTimeStamp inherited from BaseEntity)
      private boolean immutable;
  
      public UserAccountRolePk getUserAccountRolePk() {
          return userAccountRolePk;
      }
  
      public void setUserAccountRolePk(UserAccountRolePk pk) {
          this.userAccountRolePk = pk;
      }
  
      @Transient 
      public UserAccount getUserAccount() {
          return getUserAccountRolePk().getUserAccount();
      }
  
      public void setUserAccount(UserAccount u) {
          getUserAccountRolePk().setUserAccount(u);
      }
  
      @Transient 
      public Role getRole() {
          return getUserAccountRolePk().getRole();
      }
  
      public void setRole(Role p) {
          getUserAccountRolePk().setRole(p);
      }
  
      public boolean isImmutable() {
          return immutable;
      }
  
      public void setImmutable(boolean immutable) {
          this.immutable = immutable;
      }
  }
  </code></pre>
  
  <p>This is the primary key class.</p>
  
  <pre><code>@Embeddable 
  public class UserAccountRolePk {
      @ManyToOne(cascade = CascadeType.ALL) 
      private UserAccount userAccount;
  
      @ManyToOne(cascade = CascadeType.ALL) 
      private Role role;
  
      public Role getRole() {
          return role;
      }
  
      public void setRole(Role role) {
          this.role = role;
      }
  
      public UserAccount getUserAccount() {
          return userAccount;
      }
  
      public void setUserAccount(UserAccount x) {
          this.userAccount = x;
      }
  
      public boolean equals(Object o) {
          if(o == null || o.getClass() != this.getClass()) {
              return false;
          }
  
          UserAccountRolePk pk = (UserAccountRolePk) o;
          if(this.getRole().equals(pk.getRole()) &amp;&amp; this.getUserAccount().equals(pk.getUserAccount())) {
              return true;
          }
  
          return false;
      }
  
      public int hashCode() {
          return new Long(this.getRole().getId() + this.getUserAccount().getId()).hashCode();
      }
  }
  </code></pre>
  
  <p>Exception received while startup:</p>
  
  <pre><code>java.lang.IllegalArgumentException: This class [class demo.rbacapp.entity.UserAccountRole] does not define an IdClass
      at org.hibernate.jpa.internal.metamodel.AbstractIdentifiableType.getIdClassAttributes (AbstractIdentifiableType.java:183)
      at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation$IdMetadata.&lt;init&gt; (JpaMetamodelEntityInformation.java:253)
      at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.&lt;init&gt; (JpaMetamodelEntityInformation.java:84)
      at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getEntityInformation (JpaEntityInformationSupport.java:68)
      at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation (JpaRepositoryFactory.java:173)
      at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository (JpaRepositoryFactory.java:106)
      at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository (JpaRepositoryFactory.java:88)
      at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository (RepositoryFactorySupport.java:198)
      at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn (RepositoryFactoryBeanSupport.java:277)
      at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet (RepositoryFactoryBeanSupport.java:263)
      at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet (JpaRepositoryFactoryBean.java:101)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods (AbstractAutowireCapableBeanFactory.java:1687)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean (AbstractAutowireCapableBeanFactory.java:1624)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean (AbstractAutowireCapableBeanFactory.java:555)
  </code></pre>