前言
在平时开发中,在模型设计的时候,会有一些通用的字段,比如id,创建时间,更新时间等通用的字段。在模型设计时就可以不用考虑这些字段,直接写一个父类继承就行,往往一般这些公司框架已经写好一个通用的父类了,那我还有一些字段需要抽出来怎么办,那就再加一层,没有什么是加一层解决不了的。
儿子-->父亲-->爷爷
坑来了。儿子可以正常持久化,爷爷可以正常持久化,父亲持久化的数据全部为 null。怎么回事?
正文
实体类
通用实体类
java
@DynamicInsert
@DynamicUpdate
@MappedSuperclass
@Data
public class BaseDomainEntity {
@Id
@Column(name = "id")
@ApiModelProperty(value = "唯一标识")
protected String id;
@Column(name = "created_by")
@ApiModelProperty(value = "创建人")
protected String createdBy;
@Column(name = "created_date")
@ApiModelProperty(value = "创建时间")
protected Date createdDate;
@Column(name = "last_modified_by")
@ApiModelProperty(value = "最后修改人")
protected String lastModifiedBy;
@Column(name = "last_modified_date")
@ApiModelProperty(value = "最后更新时间")
protected Date lastModifiedDate;
}
父亲
java
@Data
@ApiModel(value = "父亲")
public class Parent {
@Column(name = "name")
@ApiModelProperty(value = "姓名")
private String name;
@Column(name = "age")
@ApiModelProperty(value = "年龄")
private String age;
@Column(name = "sex")
@ApiModelProperty(value = "性别")
private String sex;
}
儿子
java
@Data
@Entity
@Table(name = "son")
@ApiModel(value = "儿子")
public class Son {
@Column(name = "interest")
@ApiModelProperty(value = "兴趣")
private String interest;
@Column(name = "hobby")
@ApiModelProperty(value = "爱好")
private String hobby;
}
service
java
public void test() {
Son son = new Son();
son.setHobby("打篮球");
son.setInterest("打篮球");
initParent(son);
repository.save(son);
}
private void initParent(Parent parent) {
parent.setAge("18");
parent.setName("小明");
parent.setSex("男");
}
- 因为通用实体字段有@DynamicInsert、@DynamicUpdate这两个注解,且已经实现了自动填充,所以通用的实体已经成功持久化,Son 儿子也已经成功持久化,唯独 Parent 这个父类的字段全部为 null 的。为什么?
重点就是@MappedSuperclass这个注解
@MappedSuperclass的作用
- 标识父类:这个注解通常用于标识一个类是其他实体类的父类。
- 代码复用和模型分离:在项目开发中,如果多个实体类有共同的属性,可以使用@MappedSuperclass注解将这些属性封装到一个父类中。例如,数据库表中都需要id来表示编号,id是这些映射实体类的通用的属性,交给jpa统一生成主键id编号,那么使用一个父类来封装这些通用属性,并用@MappedSuperclass标识。
- 不映射到数据库表:标注为@MappedSuperclass的类将不是一个完整的实体类,他将不会映射到数据库表,但是他的属性都将映射到其子类的数据库字段中。
- 不能再标注@Entity或@Table注解:标注为@MappedSuperclass的类不能再标注@Entity或@Table注解,也无需实现序列化接口。
- 这样可以提高代码的复用性和可维护性,减少代码重复。
修改父类
java
@Data
@ApiModel(value = "父亲")
@MappedSuperclass
public class Parent {
@Column(name = "name")
@ApiModelProperty(value = "姓名")
private String name;
@Column(name = "age")
@ApiModelProperty(value = "年龄")
private String age;
@Column(name = "sex")
@ApiModelProperty(value = "性别")
private String sex;
}