复合主键即使用表中多个字段做为主键Id,正常情况下一般一张表只有一个字段作为主键Id,而有时我们需要关联多张表或单个主键Id在业务中无法区分时使用复合主键可以比较容易解决这些问题。
Hibernate注解官方文档:Hibernate Annotations
实体类注解详解:JPA常见注解及使用
1.多主键定义
单一复合主键:
定义复合主键PK类,使用@IdClass主键引入该类即可使用。
//定义复合主键PK
public class CommonPK implements Serializable {
private static final long serialVersionUID = 4360987061459461270L;
private String userId;
private String twoId;
}
//使用@IdClass主键引入复合主键:
@Entity
@Table(name = "TBL_USER")
@IdClass(CommonPK.class)
public class TblUser implements Serializable {
private static final long serialVersionUID = 4360987061459461270L;
@Column(nullable = false, name = "NAME")
private String name;
@Column(name = "Age")
private Integer age;
@Id
@Column(nullable = false, name = "ID")
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "uuid2")
private String userId;
@Id
@Column(nullable = false, name = "TWOID")
private String twoId;
}
复合主键中依赖其他表复合主键:
复合主键中依赖外键:其他表的复合主键:作为主键。如下:
public class ManyPK implements Serializable {
private static final long serialVersionUID = 4360987061459461270L;
@Column(name = "TASK_ID", length = 36, nullable = false)
private String taskId;
@Column(name = "USER_ID",length = 36)
private String userEntityId;
@Column(name = "USER_ID_TASK_ID",length = 36)
private String userIdTaskId;
@Column(name = "VALUE_ID",length = 36)
private String valueEntityId;
@Column(name = "VALUE_TASK_ID",length = 36)
private String valueIdTaskId;
}
@Entity
@Table(name = "TBL_USER")
@IdClass(ManyPK.class)
public class TblMany implements Serializable {
private static final long serialVersionUID = 4360987061459461270L;
@Column(nullable = false, name = "NAME")
private String name;
@Column(name = "NUM")
private Integer num;
@Id
@Column(name = "USER_ID",length = 36)
private String userEntityId;
@Id
@Column(name = "USER_ID_TASK_ID",length = 36)
private String userIdTaskId;
@Id
@Column(name = "VALUE_ID",length = 36)
private String valueEntityId;
@Id
@Column(name = "VALUE_TASK_ID",length = 36)
private String valueIdTaskId
@ManyToOne
@JoinColumns({
@JoinColumn(name = "USER_ID", referencedColumnName = "ID", insertable = false, updatable = false),
@JoinColumn(name = "USER_TASK_ID", referencedColumnName = "TASK_ID", insertable = false, updatable = false)
})
private TblUser userId;
@ManyToOne
@JoinColumns({
@JoinColumn(name = "VALUE_ID", referencedColumnName = "ID", insertable = false, updatable = false),
@JoinColumn(name = "VALUE_TASK_ID", referencedColumnName = "TASK_ID", insertable = false, updatable = false)
})
private TblValue valueId;
}
jpa复合主键常见报错问题:
1.如果使用@IdClass主键,同时又使用双层@MappedSuperclass注解会报错,无法获取属性
如下代码:继承了两个@MappedSuperclass注解类,运行时会报错。
@Entity
@Table(name = "TBL_USER")
@IdClass(CommonPK.class)
public class TblUser extends DatetimeEntity implements Serializable {
private static final long serialVersionUID = 4360987061459461270L;
@Column(nullable = false, name = "NAME")
private String name;
@Column(name = "Age")
private Integer age;
}
@MappedSuperclass
public DatetimeEntity extends CommonEntity implements Serializable{
private static final long serialVersionUID = 4360987061459461270L;
@Column(nullable = false, name = "CREATE_DATE")
private LocalDateTime createDate;
}
@MappedSuperclass
public CommonEntity implements Serializable{
private static final long serialVersionUID = 4360987061459461270L;
@Id
@Column(nullable = false, name = "ID")
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "uuid2")
private String id;
}
@MappedSuperclass注解:
一般作为基类的注解,
@MappedSuperclass注解,通过这个注解,我们可以将该实体类当成基类实体,它不会隐射到数据库表,但继承它的子类实体在隐射时会自动扫描该基类实体的隐射属性,添加到子类实体的对应数据库表中。
使用环境:
1.@MappedSuperclass注解使用在父类上面,是用来标识父类的
2.@MappedSuperclass标识的类表示其不能映射到数据库表,因为其不是一个完整的实体类,但是它所拥有的属性能够隐射在其子类对用的数据库表中
3.@MappedSuperclass标识的类不能再有@Entity或@Table注解
2.复合主键中依赖其他表复合主键按以下代码写法会报错
public class ManyPK implements Serializable {
private static final long serialVersionUID = 4360987061459461270L;
@Column(name = "TASK_ID", length = 36, nullable = false)
private String taskId;
@ManyToOne
@JoinColumns({
@JoinColumn(name = "USER_ID", referencedColumnName = "ID", insertable = false, updatable = false),
@JoinColumn(name = "USER_TASK_ID", referencedColumnName = "TASK_ID", insertable = false, updatable = false)
})
private TblUser userId;
@ManyToOne
@JoinColumns({
@JoinColumn(name = "VALUE_ID", referencedColumnName = "ID", insertable = false, updatable = false),
@JoinColumn(name = "VALUE_TASK_ID", referencedColumnName = "TASK_ID", insertable = false, updatable = false)
})
private TblValue valueId;
}
@Entity
@Table(name = "TBL_USER")
@IdClass(ManyPK.class)
public class TblMany implements Serializable {
private static final long serialVersionUID = 4360987061459461270L;
@Column(nullable = false, name = "NAME")
private String name;
@Column(name = "NUM")
private Integer num;
@Id
@ManyToOne
@JoinColumns({
@JoinColumn(name = "USER_ID", referencedColumnName = "ID", insertable = false, updatable = false),
@JoinColumn(name = "USER_TASK_ID", referencedColumnName = "TASK_ID", insertable = false, updatable = false)
})
private TblUser tblUser;
@Id
@ManyToOne
@JoinColumns({
@JoinColumn(name = "VALUE_ID", referencedColumnName = "ID", insertable = false, updatable = false),
@JoinColumn(name = "VALUE_TASK_ID", referencedColumnName = "TASK_ID", insertable = false, updatable = false)
})
private TblUser tblUser;
}
报错如下:可按上面示例写法解决该问题
-Cannot convert value of type 'com.test.entity.ManyPK' to required type 'com.test.entity.TblMany' for property 'userId':
no matching editors or conversion strategy found"