IllegalArgumentException: expecting IdClass mapping

@IdClass annotation is used to define the Class that contains the id. i.e. This is generally used in case defining a compound key. i.e. a key composite of more than one attribute. If that is the case, than this is how we do. take a look at following example.. we define a class as IdClass and use @Id's to define varrious Ids for thisIdClass`.

Example :

@Entity
@IdClass(AssignedRoleId.class)
public class AssignedRole
{
  @Id
  @ManyToOne
  private User userId;

  @Id
  @ManyToOne  
  private Role roleId;

  private Date dateAssigned;
}

Hope this helps.


Elaborating further on @Mukul correct answer the @IdClass should have the following properties:

  1. It should implement Serializable
  2. It should have a constructor that takes the ids (i.e. the fields associated with @Id)
  3. It should override equals and hashCode

It's sometime useful to make this class as a static inner class of the entity, here's an example:

@Entity 
@IdClass(AssignedRoleId.class)
public class AssignedRole
{ 
    @Id
    @ManyToOne
    private User userId;

    @Id
    @ManyToOne
    private Role roleId;

    private Date dateAssigned;

    public static class AssignedRoleId implements Serializable {

        private User userId;
        private Role roleId;

        public AssignedRoleId() {}

        public AssignedRoleId(User userId, Role roleId) {
            this.userId = userId;
            this.roleId = roleId;
        }

        @Override
        public boolean equals(Object o) {

            if (o == this) {
                return true;
            }
            if (!(o instanceof AssignedRole)) {
                return false;
            }
            AssignedRole assignedRole = (AssignedRole) o;
            return Objects.equals(userId, assignedRole.getUserId()) &&
                   Objects.equals(roleId, assignedRole.getRoleId());
        }

        @Override
        public int hashCode() {
            return Objects.hash(userId, roleId);
        }
   }
}