Halo 開源項目學習(二):實體類與數據表

基本介紹

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:用戶名。