Halo 開源專案學習(二):實體類與資料表

John同學發表於2022-04-23

基本介紹

Halo 專案中定義了一些實體類,用於儲存部落格中的關鍵資料,如使用者資訊、文章資訊等。在深入學習 Halo 的設計理念與實現過程之前,不妨先學習一下一個完整的部落格系統都由哪些元素組成。

實體類

Halo 中的除 BaseEntity 外的每一個實體類都對應著一個資料表,以 User 類為例,每一個 User 物件都對應 users 表中的一條記錄,每一個物件屬性的值也等於資料表中對應欄位的值。

User 類定義如下:

@Data // Lombok 註解, 自動生成 get()、set()、toString() 等方法
@Entity // JPA 註解, 宣告該類為一個實體類, 必須與 @Id 搭配使用
@Table(name = "users") // JAP 註解, 宣告該類對映到資料庫的 users 資料表
@ToString(callSuper = true) // Lombok 註解, callSuper = true 表示呼叫 toString() 方法時輸出父類的屬性
@EqualsAndHashCode(callSuper = true) // 自動生成 equals() 和 hashCode() 方法, 預設 callSuper 為 false, 為 true 表示 equals() 方法比較時會呼叫父類的 equals() 方法
public class User extends BaseEntity {

    @Id // JPA 註解, 宣告主鍵
    @GeneratedValue(strategy = GenerationType.IDENTITY) // JPA 註解, 宣告主鍵的生成策略, IDENTITY 表示使用自增 id
    @Column(name = "id") // JPA 註解, 宣告實體類的屬性 id 對映到資料表中的欄位 id
    private Integer id;

    /**
     * User name.
     */
    @Column(name = "username", columnDefinition = "varchar(50) not null")
    private String username;

    /**
     * User nick name,used to display on page.
     */
    @Column(name = "nickname", columnDefinition = "varchar(255) not null")
    private String nickname;

    /**
     * Password.
     */
    @Column(name = "password", columnDefinition = "varchar(255) not null")
    private String password;

    /**
     * User email.
     */
    @Column(name = "email", columnDefinition = "varchar(127) default ''")
    private String email;

    /**
     * User avatar.
     */
    @Column(name = "avatar", columnDefinition = "varchar(1023) default ''")
    private String avatar;

    /**
     * User description.
     */
    @Column(name = "description", columnDefinition = "varchar(1023) default ''")
    private String description;

    /**
     * Expire time.
     */
    @Column(name = "expire_time", columnDefinition = "timestamp default CURRENT_TIMESTAMP")
    @Temporal(TemporalType.TIMESTAMP)
    private Date expireTime;


    @Override
    public void prePersist() {
        super.prePersist();

        id = null;

        if (email == null) {
            email = "";
        }

        if (avatar == null) {
            avatar = "";
        }

        if (description == null) {
            description = "";
        }

        if (expireTime == null) {
            expireTime = DateUtils.now();
        }
    }
}

註解解釋:

  • @Data:Lombok 註解,自動生成 get()、set()、toString() 等方法。

  • @Entity:JPA 註解,宣告該類為一個實體類, 必須與 @Id 搭配使用。

  • @Table:JAP 註解,宣告該類對應資料庫中的某個資料表,name 指明表名。

  • @ToString:lombok 註解,callSuper = true 表示呼叫 toString() 方法時會輸出父類的屬性。

  • @EqualsAndHashCode:自動生成 equals() 和 hashCode() 方法,預設 callSuper 為 false, 為 true 表示 equals() 在方法比較時會呼叫父類的 equals()(如果父類的 equals() 返回 false,則直接返回 false,否則繼續比較)。

  • @Id:JPA 註解,宣告主鍵。

  • @GeneratedValue:JPA 註解,宣告主鍵的生成策略,IDENTITY 表示使用自增 id。

  • @Column:JPA 註解,宣告實體物件的屬性對映到資料表中的哪一個欄位,name 指定欄位名,columnDefinition 指定欄位的定義。

User 類中定義了使用者名稱、暱稱、郵箱等使用者資料,Halo 使用 JPA 將實體物件持久化到資料庫中,也就是將 User 物件的各個屬性儲存到資料表 users 的各個欄位中。JPA 支援自動建立資料表,所以啟動專案前無需建表,關於 JPA 的使用,可以參考 SpringBoot 整合 Spring Data JPA

User 類繼承了 BaseEntity,BaseEntity 類中定義了一些通用的屬性,如 createTime、updateTime 以及 deleted 等,分別指使用者的建立時間、修改時間以及是否被刪除,users 表中有對應的欄位。此外,BaseEntity 類還定義了三個方法,分別為 prePersist()、preUpdate() 和 preRemove():

  • prePersist() 方法在物件持久化到資料庫之前被呼叫。

  • preUpdate() 方法在物件的某個屬性發生變動時被呼叫,如更新實體的 update_time。

  • preRemove() 方法在物件從資料庫刪除前被呼叫。

BaseEntity 並沒有對應某一個資料表,它被 @MappedSuperclass 修飾, @MappedSuperclass 屬於 JPA 註解,應用於實體類的父類中, 該註解作用的類不會對映到資料表,但其屬性都將對映到子類所對應的資料表。也就是說不同實體類的通用屬性可在相同的父類中定義,子類繼承父類後,父類中的這些通用屬性會持久化到子類對應的資料表中。

BaseEntity 類定義如下:

@Data
@ToString
@MappedSuperclass // JPA 註解, 應用於實體類的父類中, 該註解作用的類不會對映到資料表,但其屬性都將對映到子類的資料表
@EqualsAndHashCode
public class BaseEntity {

    /**
     * Create time.
     */
    @Column(name = "create_time", columnDefinition = "timestamp default CURRENT_TIMESTAMP")
    @Temporal(TemporalType.TIMESTAMP)
    private Date createTime;

    /**
     * Update time.
     */
    @Column(name = "update_time", columnDefinition = "timestamp default CURRENT_TIMESTAMP")
    @Temporal(TemporalType.TIMESTAMP)
    private Date updateTime;

    /**
     * Delete flag.
     */
    @Column(name = "deleted", columnDefinition = "TINYINT default 0")
    private Boolean deleted = false;

    @PrePersist // @PrePersist 事件在實體物件插入到資料庫的過程中發生
    protected void prePersist() {
        deleted = false;
        Date now = DateUtils.now();
        if (createTime == null) {
            createTime = now;
        }

        if (updateTime == null) {
            updateTime = now;
        }
    }

    @PreUpdate // @PreUpdate 事件在實體的狀態同步到資料庫之前觸發
    protected void preUpdate() {
        updateTime = new Date();
    }

    @PreRemove // @PreRemove 事件在實體從資料庫刪除之前觸發
    protected void preRemove() {
        updateTime = new Date();
    }
}

資料表

專案啟動成功後,JPA 會為實體類自動生成對應的資料表。可以使用 Navicat 檢視 MySQL 中庫名為 'halodb' 的資料庫(自己配置的庫名),發現自動建立瞭如下資料表:

資料表

下面介紹不同資料表的作用以及對應的欄位含義,由於許多實體類都繼承自 BaseEntity,所以不同資料表中會有一些通用的欄位,如:

  • id:主鍵(雖不在 BaseEntity 中定義,但每個子類中都存在)。

  • crate_time:建立時間。

  • deleted:是否已經刪除。

  • update_time:更新時間。

下面介紹各個資料表中,特定欄位的具體含義:

1. attachments:附件表,用於存放圖片和檔案。

  • file_key:檔案的 key,可以根據 file_key 刪除檔案。

  • height:圖片高度。

  • media_type:媒體型別,如 text/html、image/jpeg 等。

  • name:附件的名字。

  • path:附件的儲存路徑。

  • size:附件的大小。

  • suffix:附件的字尾,如 png、html 等。

  • thumb_path:縮圖的訪問路徑,該路徑指定的資源可用作為封面圖。

  • type:附件的上傳型別,如上傳到本地(type 為 0)、阿里雲(type 為 4)。

  • width:圖片寬度。

2. categories:文章分類目錄表,釋出文章時可設定文章所屬的分類。

  • decryption:描述。

  • name:分類名。

  • parent_id:父目錄 id。

  • password:密碼。

  • slug:別名。

  • slug_name:專案中沒有用到。

  • thumbnail:分類的封面圖。

3. comment_black_list:評論黑名單表,用於禁止某個 ip 進行評論。

  • ban_time:封禁時間。

  • ip_address:封禁的 ip。

4. comments:評論表,可對文章進行評論,也可對評論進行回覆,還可以對頁面(友情連結、相簿、日誌等)進行評論。

  • type:給文章進行評論時 type 為 0,給頁面進行評論時 type 為 1。

  • allow_notification:是否允許通知。

  • author:評論者的姓名。

  • author_url:評論者的 url。

  • content:評論內容。

  • email:評論者的 email。

  • gravatar_md5:評論者的頭像。

  • ip_address:評論者的 ip。

  • is_admin:評論者是否為博主。

  • parent_id:如果回覆某個評論,則 parent_id 為該評論的 id;如果評論文章,則 parent_id 為 0。

  • post_id:哪篇文章或哪個頁面的評論。

  • status:評論的狀態,0 表示已釋出,1 表示待發布,2 表示新增到了回收站。

  • top_priority:是否置頂。

  • user_agent:使用者代理,例如瀏覽器。

5. journals:使用者日誌表,在 Halo 中使用者可以對外分享日誌(記錄生活的日誌),日誌的資訊儲存在 journals 表中。

  • content:日誌內容。

  • likes:點贊量。

  • source_content:原始內容。

  • type:日誌型別,公開日誌的 type 為 0,私密日誌的 type 為 1。

6. links:友情連結表,用於訪問其他部落格或資源。

  • description:描述。

  • logo:標誌。

  • name:名稱。

  • priority:排序編號。

  • team:所屬分組。

  • url:連結。

7. logs:系統日誌表,記錄使用者的操作。

  • content:日誌內容。

  • ip_address:操作者的 ip。

  • log_key:log_key 通常為操作物件的標識,例如釋出文章時 log_key 是文章的 id,使用者登入時 log_key 是使用者的 userName。

  • type:日誌型別,例如發表文章時 type 為 5,登入時 type 為 25。

8. menus:選單表,部落格的主頁有多個選單,且每個選單都可以是多級選單。

  • icon:圖示。

  • name:名稱

  • parent_id:父級選單的 id。

  • priority:優先順序,用於部落格首頁上選單的排序。

  • target:可選 _self 和 _blank,_self 表示在當前頁面開啟選單所指向的連結;_blank 表示在新的頁面開啟連結。

  • team:所屬分組。

  • url:選單所指向的連結。

9. metas:後設資料表,用於設定文章或頁面的屬性,可在釋出文章或頁面時的 "高階" 選項中進行操作。

  • type:設定文章的後設資料時 type 為 0,設定頁面的後設資料時 type 為 1。

  • mate_key:後設資料 key 可以設定文章是否支援點贊、是否支援複製等。

  • mate_value:key 對應的值

  • post_id: 文章或頁面的 id。

10. options:部落格設定表,或者稱為選項表,用於儲存系統設定的相關資訊。使用者可在 Dashboard 介面的 "系統" -> "部落格設定" 中進行配置。

  • option_key:部落格的選項,例如部落格標題 blog_title、主題 theme、是否已安裝 is_installed 等。

  • type:部落格的內部選項的 type 為 0,自定義選項的 type 為 1。

  • option_value:選項對應的值。

11. photos:圖片表,Halo 可以設定相簿,相簿頁面的圖片存放在 photos 表中。

  • description:描述。

  • likes:點贊量。

  • location:拍攝地點。

  • name:名稱。

  • take_time:拍攝日期。

  • team:所屬分組。

  • thumbnail:縮圖地址。

  • url:圖片連結。

12. post_categories:文章 - 分類的關係表,記錄每個文章屬於哪個分類。

  • category_id:分類 id。

  • post_id:文章 id。

13. post_tags:文章標籤表,記錄文章的標籤。

  • post_id:文章 id。

  • tag_id:標籤 id。

14. posts:文章表,也用來儲存頁面。

  • type:文章的 type 為 0,頁面的 type 為 1。

  • disallow_comment:是否關閉評論。

  • edit_time:編輯時間。

  • editor_type:編輯器型別。

  • format_content:格式化後的內容。

  • likes:點贊量。

  • meta_description:自定義描述。

  • meta_keywords:自定義關鍵詞。

  • original_content:原始內容。

  • password:密碼。

  • slug:別名。

  • status:狀態,0 表示已釋出,1 表示待發布,2 表示位於回收站,3 表示私密文章或頁面。

  • summary:文章摘要。

  • template:自定義的模板,新增頁面時可設定模板。

  • thumbnail:封面圖。

  • title:標題。

  • top_priority:是否置頂。

  • url:連結。

  • visits:訪問量。

  • word_count:字數統計。

15. tags:標籤表,釋出文章時,可為文章設定標籤。

  • name:標籤名稱。

  • slug:別名。

  • slug_name:專案中沒有用到。

  • thumbnail:標籤的封面圖。

16. theme_settings:主題設定表,設定部落格主題。

  • setting_key:主題中可設定的選項,例如文章標題是否大寫 post_title_uppper、部落格首頁的郵箱 email 等。

  • theme_id:主題的 id。

  • setting_value:setting_key 對應的值。

17. users:使用者表,記錄使用者資訊。

  • avatar:頭像。

  • decription:描述。

  • email:郵箱。

  • expire_time:過期時間,嚴格來說應該稱為賬號的起始有效時間,當前時間超過 expire_time 時,該賬號才能正常登入。

  • maf_key:兩步驗證碼的 key。

  • maf_type:是否開啟了兩步驗證碼,0 表示未開啟(預設),1 表示開啟。

  • nickname:暱稱。

  • password:密碼。

  • username:使用者名稱。

相關文章