JPA繼承方式
在JPA中,實體繼承關係的映射策略共有三種:單表繼承策略(SINGLE_TABLE)、Joined策略和Table_PER_Class策略。
關聯註解
@Inheritance
用來配置父類
InheritanceType.SINGLE_TABLE
單表模式:將所有實現類的所有字段映射到一個表裏。InheritanceType.TABLE_PER_CLASS
獨立表模式: 將每個實現類合併基類的字段映射到單獨的表裏,每個表相關獨立且沒有關聯。InheritanceType.JOINED
關聯表模式:將基類和每個實現類分別映射到獨立的表裏,並使用主鍵進行關聯,實現類只包含自己獨有的字段。
-
@DiscriminatorColumn(name = "member_type")
用來做實現類區別標識的字段,如果不指定name,則會自動新建dtype字段。此字段系統會自動賦值,不需要人爲指定。 -
@DiscriminatorValue("wexin")
實現類區別的標識值,jpa會根據具體標識值將數據持久化到對應的表中,查詢語句也可自動識別類型
操作
- 所有的實現類都可視爲一個整體,可直接使用某個子類的屬性做查詢條件,可以有子類的返回值,也可以設置基類返回值。
- 如果返回值爲基類Member,jpa則返回Hibernate的代理類,需要
Hibernate.unproxy(member)
才能得到具體的實現類 - 如果返回值爲實現類則可以直接使用
- 寫入和刪除操作,jpa都視爲一個整體,可以直接使用memberRepository默認的方法
關聯表模式如何保留審計字段或同名字段
Jpa在關聯表模式下,對子類中與父類同名的字段不進行管理,導致自定義的軟刪除字段不會生效,也不生成對應的表字段,解決這個問題,可以創建一個不同名屬性,映射到指定的字段,實現功能。
/**
* 計量容器基礎表
* @author xxm
* @date 2020/7/22
*/
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "mms_bd_container_base")
@DiscriminatorColumn(name = "containerType")
@SQLDelete(sql = "update mms_bd_container_base set deleted=" + AppConst.FLAG_DELETED + " where id=?")
@Where(clause = "deleted=" + AppConst.FLAG_NOT_DELETED)
public class ContainerDo extends BaseEntity{
/** 編號 */
@Column(unique = true)
private String no;
/** 容器類型 */
@Column(insertable = false,updatable = false)
private String containerType;
/** 容器狀態 */
private String containerStatus;
/** 識別碼 */
private String identifier;
/** 識別碼類型 */
private String identifierType;
}
/**
* 容器(車輛)
* @author xxm
* @date 2020/7/22
*/
@Entity
@Table(name = "mms_bd_container_vehicle")
@DiscriminatorValue("vehicle")
@SQLDelete(sql = "update mms_bd_container_vehicle set deleted=" + AppConst.FLAG_DELETED + " where id=?")
@Where(clause = "deleted=" + AppConst.FLAG_NOT_DELETED)
public class ContainerVehicleDo extends ContainerDo implements EntityBaseFunction<containervehicledto> {
/** 車輛名稱 */
private String vehicleName;
/** 重量 */
private Double weight;
/** 計量時間 */
private LocalDateTime weighingTime;
/** 重量有效期類型 */
private String validPeriod;
/** 刪除標誌(父類同名屬性) */
@Column(name = "deleted")
private boolean deleted0;
}