国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Spring Boot實(shí)現(xiàn)高質(zhì)量的CRUD-1

這篇具有很好參考價(jià)值的文章主要介紹了Spring Boot實(shí)現(xiàn)高質(zhì)量的CRUD-1。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

1、前言

?	在Spring Boot的SMM框架(SpringBoot+Mysql+Mybatis)的WEB項(xiàng)目中,CRUD(增刪改查)大致占了50%-70%左右的工作量。提高CRUD的代碼質(zhì)量,提高CRUD的開發(fā)效率,是一件值得探討的事項(xiàng)。
?	一般認(rèn)為,CRUD是一件體力活。在SMM框架項(xiàng)目開發(fā)中,項(xiàng)目團(tuán)隊(duì)通常將這類CRUD的開發(fā)任務(wù)交由知道如何寫Mybatis腳本的初中級(jí)Java工程師來做,一般往往僅僅是業(yè)務(wù)層面的交代。實(shí)踐表明,如果不在一開始制定CRUD的開發(fā)規(guī)范,得到的結(jié)果往往差強(qiáng)人意。由于缺乏整體規(guī)劃,不同工程師的代碼風(fēng)格迥異,方法命名,參數(shù)命名,五花八門,檢查項(xiàng)也不完整,代碼臃腫,重復(fù)性高,后期常常需要大量修修補(bǔ)補(bǔ),維護(hù)成本高得驚人。	?	
?	而基于CRUD開發(fā)規(guī)范,則可大大提高了CRUD代碼的易維護(hù)性、接口的可用性和健壯性、用戶友好性,以及功能擴(kuò)展靈活性。多個(gè)項(xiàng)目實(shí)踐顯示,使用CRUD開發(fā)規(guī)范至少可以提高20%的開發(fā)效率,考慮包括后期維護(hù)成本,可以有效降低開發(fā)成本超過30%。

2、CRUD的常規(guī)功能

?	CRUD的常規(guī)功能如下:
?	1)增加單個(gè)對(duì)象;    
?	2)批量增加對(duì)象;
?	3)修改單個(gè)對(duì)象;
?	4)批量修改對(duì)象;
?	5)刪除單個(gè)對(duì)象;
?	6)批量刪除對(duì)象;
?	7)前端分頁查詢;    
?	8)獲取指定對(duì)象;    
?	9)根據(jù)條件查詢對(duì)象;    
?	10)導(dǎo)入Excel數(shù)據(jù);
?	11)導(dǎo)出Excel數(shù)據(jù)。

?	其中,導(dǎo)入Excel數(shù)據(jù)是批量增加或修改對(duì)象的一種方式,導(dǎo)出Excel數(shù)據(jù)是數(shù)據(jù)查詢的一種形式。Excel作為最方便的辦公文件格式,在數(shù)據(jù)交換中使用十分廣泛。
?	根據(jù)代碼分層開發(fā)思想,CRUD將涉及8個(gè)文件:
?	1)實(shí)體類Entity,基本與表結(jié)構(gòu)字段進(jìn)行映射對(duì)應(yīng);簡單起見,可忽略其它POJO對(duì)象,在實(shí)體類中添加其它需要的屬性。
?	2)數(shù)據(jù)訪問對(duì)象類Dao,這個(gè)在SMM框架中,為支持Mybatis或Mybatis-Plus的接口類。
?	3)Dao實(shí)現(xiàn)類Mybatis,為xml腳本文件,使用Mybatis腳本語言實(shí)現(xiàn)Dao的相關(guān)接口。
?	4)服務(wù)接口類Service,定義Controller層接口所需的各種CRUD接口形式,以及內(nèi)部處理所需的其它接口形式。
?	5)服務(wù)接口實(shí)現(xiàn)類ServiceImpl,實(shí)現(xiàn)Service的相關(guān)接口。
?	6)服務(wù)單元測(cè)試類ServiceTest,使用JUnit,實(shí)現(xiàn)Service的相關(guān)接口的單元測(cè)試。
?	7)業(yè)務(wù)方法接口類Controller,也可稱為API接口類,提供HTTP接口服務(wù)。    
?	8)API接口文檔,格式比較靈活,當(dāng)然使用YAPI導(dǎo)出的格式最好,但錄入很費(fèi)時(shí)間。當(dāng)然不管使用哪種格式,API接口相關(guān)的要素說明都要有。    

3、數(shù)據(jù)庫設(shè)計(jì)規(guī)范

?	由于CRUD與數(shù)據(jù)庫表結(jié)構(gòu)高度相關(guān)?,因此先簡單說明一下表結(jié)構(gòu)的設(shè)計(jì)規(guī)范。

3.1、表結(jié)構(gòu)設(shè)計(jì)例子

?	先看2個(gè)表結(jié)構(gòu)的DDL(Data Definition Language,數(shù)據(jù)庫定義語言)腳本例子。
-- ----------------------------
-- Table structure for exa_users
-- 用戶表
-- ----------------------------
DROP TABLE IF EXISTS exa_users;
CREATE TABLE exa_users
(
  user_id			BIGINT(20)        NOT NULL DEFAULT 0	COMMENT '用戶ID',

  -- 登錄信息
  user_name			VARCHAR(80)		UNIQUE NOT NULL DEFAULT '' COMMENT '用戶名',
  -- 加密算法:md5(concat(md5(密碼明文),salt));
  -- 前端發(fā)送一次md5的值到服務(wù)器,服務(wù)器添加salt值,計(jì)算二次md5(32)大寫值,與passwd值比較
  password			VARCHAR(64)		NOT NULL DEFAULT '' COMMENT '用戶密碼',
  -- salt,可用記錄生成的時(shí)間
  salt				VARCHAR(64)		NOT NULL DEFAULT '' COMMENT '加鹽md5算法中的鹽',
  user_type			TINYINT(4)		NOT NULL DEFAULT 3  COMMENT '用戶類型,1-系統(tǒng)管理員、2-公司內(nèi)部用戶、3-外部用戶,由系統(tǒng)參數(shù)表user_type類別定義',
  org_id			INT(11)			NOT NULL DEFAULT 0  COMMENT '組織ID',

  -- 用戶資料
  real_name			VARCHAR(64)		NOT NULL DEFAULT '' COMMENT '真實(shí)姓名',
  email				VARCHAR(100)    	NOT NULL DEFAULT '' COMMENT 'Email',
  phone_number  		VARCHAR(20)		NOT NULL DEFAULT '' COMMENT '手機(jī)號(hào)碼',
  sex				TINYINT(4)		NOT NULL DEFAULT 1  COMMENT '性別,1-無值、2-男、3-女、4-其它,由系統(tǒng)參數(shù)表sex類別定義',
  birth				DATETIME		DEFAULT NULL COMMENT '生日',
  id_no				VARCHAR(30)		NOT NULL DEFAULT '' COMMENT '身份證號(hào)碼',

  open_id			VARCHAR(40)		NOT NULL DEFAULT "" COMMENT '微信小程序的openid',
  woa_openid    		VARCHAR(40)		NOT NULL DEFAULT "" COMMENT '微信公眾號(hào)openid',
  remark			VARCHAR(200)	NOT NULL DEFAULT '' COMMENT '備注',

  -- 記錄操作信息
  operator_name		VARCHAR(80)		NOT NULL DEFAULT '' COMMENT '操作人賬號(hào)',
  delete_flag		TINYINT(4)		NOT NULL DEFAULT 0  COMMENT '記錄刪除標(biāo)記,0-正常、1-禁用,由系統(tǒng)參數(shù)表delete_flag類別定義',
  create_time		DATETIME		NOT NULL DEFAULT NOW() COMMENT '創(chuàng)建時(shí)間',
  update_time		DATETIME		DEFAULT NULL ON UPDATE NOW() COMMENT '更新時(shí)間',
  PRIMARY KEY (user_id)
) ENGINE = InnoDB DEFAULT CHARSET = utf8 COMMENT '用戶表';

-- ----------------------------
-- Table structure for exa_user_roles
-- 用戶和角色關(guān)系表
-- 用戶和角色是多對(duì)多關(guān)系
-- ----------------------------
DROP TABLE IF EXISTS exa_user_roles;
CREATE TABLE exa_user_roles
(
  user_id			BIGINT(20)		NOT NULL DEFAULT 0  COMMENT '用戶ID',
  role_id			INT(11)			NOT NULL DEFAULT 0  COMMENT '角色I(xiàn)D',

  -- 記錄操作信息
  operator_name		VARCHAR(80)		NOT NULL DEFAULT '' COMMENT '操作人賬號(hào)',
  delete_flag		TINYINT(4)		NOT NULL DEFAULT 0  COMMENT '記錄刪除標(biāo)記,保留字段',
  create_time		DATETIME		NOT NULL DEFAULT NOW() COMMENT '創(chuàng)建時(shí)間',
  update_time		DATETIME 		DEFAULT NULL ON UPDATE NOW() COMMENT '更新時(shí)間',
  PRIMARY KEY (user_id, role_id)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8 COMMENT ='用戶和角色關(guān)系表';

3.2、表結(jié)構(gòu)設(shè)計(jì)規(guī)范

?	1)表名使用項(xiàng)目簡稱前綴,這個(gè)前綴一般為3-4個(gè)字符,使用了表名前綴,數(shù)據(jù)表屬于哪個(gè)項(xiàng)目一目了然。由于不同項(xiàng)目,有一些如用戶表,角色表等通用的表,對(duì)于測(cè)試團(tuán)隊(duì)而言,有了表的前綴,只需一個(gè)測(cè)試數(shù)據(jù)庫,就可以支持多個(gè)項(xiàng)目的測(cè)試。表名一般使用復(fù)數(shù)形式后綴,因?yàn)閿?shù)據(jù)表是對(duì)象或關(guān)系的集合。
?	2)字段名采用下劃線規(guī)則,小寫字母,使用英文詞匯或易理解的英文縮寫,不能使用漢語拼音或漢語拼音縮寫,那樣會(huì)令人費(fèi)解。
?	3)字符串類型使用VARCHAR類型,長文本考慮TEXT或更長的TEXT類型。
?	4)枚舉類型一般使用TINYINT類型,更長的可考慮INT類型,且枚舉類型均在系統(tǒng)參數(shù)表定義,不建議使用字符串作為枚舉值。
?	5)除DATETIME、BLOB和TEXT類型外,均使用NOT NULL DEFAULT 形式。
?	6)TIMESTAMP類型,為4字節(jié),有至多到2038年問題,為避免類似于千年蟲問題,不再使用,使用DATETIME類型。如果需要精確到毫秒,可以用DATETIME(3),NOW默認(rèn)值對(duì)應(yīng)為NOW(3)。
?	7)所有字段都要有注釋,即有COMMENT部分。
?	8)所有表都要有記錄操作信息部分,即有operator_name、delete_flag、create_time、update_time這4個(gè)字段。operator_name值為空串,表示系統(tǒng)內(nèi)部生成的記錄(如統(tǒng)計(jì)記錄);delete_flag字段,對(duì)于對(duì)象表(如用戶表),通過delete_flag字段的值,啟用或禁用對(duì)象,不做記錄的物理刪除;對(duì)于關(guān)系表(如用戶和角色關(guān)系表),則支持物理刪除,delete_flag字段保留。create_time和update_time用于標(biāo)記記錄的生成時(shí)間和最后修改時(shí)間,insert和update時(shí)無需考慮,由數(shù)據(jù)庫自動(dòng)維護(hù),這2個(gè)字段在記錄的增量使用時(shí),非常有用,如表記錄的定時(shí)同步,或采樣數(shù)據(jù)的增量統(tǒng)計(jì)和分析。
?	9)對(duì)象表的主鍵ID字段,使用全局ID,不建議使用自增ID,因?yàn)樽栽鯥D在進(jìn)行數(shù)據(jù)庫的集群或分布式擴(kuò)容以及數(shù)據(jù)遷移時(shí),會(huì)遇到很大麻煩。
?	10)ID字段名稱,應(yīng)盡量使用符合對(duì)象身份的ID名稱,如user_id、org_id等,而不應(yīng)隨便都用id或rec_id這樣的通用名稱(特殊情況除外),這樣處理一方面可降低溝通成本,另外在多表聯(lián)結(jié)時(shí),也不必考慮字段別名以及別名與實(shí)體類屬性的映射,可降低開發(fā)成本。另外,ID字段盡量使用INTEGER或BIGINT類型,而避免使用字符串類型,這樣多表聯(lián)結(jié)查詢有性能優(yōu)勢(shì)。
?	11)要有主鍵字段定義。
?	12)要有表名注釋。
?	13)關(guān)于數(shù)據(jù)庫引擎,使用InnoDB,目前阿里云數(shù)據(jù)庫已取消了對(duì)MYISAM的支持,因?yàn)閮烧咝阅芤巡顒e不大,而MYISAM不支持事務(wù)處理,顯然不如統(tǒng)一使用InnoDB。
?	14)關(guān)于字符集,一般使用utf8,特殊場(chǎng)景,如需支持微信表情,則可考慮utf8mb4。
?	15)密碼字段,考慮信息安全,簽名密碼可使用簽名算法如MD5,第三方系統(tǒng)的賬號(hào)密碼如郵箱密碼等,使用AES算法存儲(chǔ)。
?	16)如果本表涉及數(shù)據(jù)權(quán)限,則應(yīng)添加相關(guān)數(shù)據(jù)權(quán)限字段,以方便數(shù)據(jù)權(quán)限控制,這將在數(shù)據(jù)權(quán)限討論中詳細(xì)展開。

?	表結(jié)構(gòu)設(shè)計(jì),必須有字段說明,對(duì)于Mysql數(shù)據(jù)庫而言,字段和表注釋可以直接在建表語句中加入,這樣即使不查閱表結(jié)構(gòu)設(shè)計(jì)文檔,也可利用數(shù)據(jù)庫訪問工具如Navicat等,通過查看表的DDL腳本了解各字段的含義和用處。對(duì)于如Hibernate、Golang等支持ORM(Object-Relation Mapping,對(duì)象關(guān)系映射)的框架,可以在代碼中直接添加字段,這個(gè)原則上是不允許的。沒有字段描述的表結(jié)構(gòu)DDL腳本,是不可取的,只會(huì)給后人留下太多的坑,從而大大提高了維護(hù)成本。

3.3、使用系統(tǒng)參數(shù)表管理字段枚舉值

?	關(guān)于系統(tǒng)參數(shù)表,表結(jié)構(gòu)及記錄的例子如下:
-- ----------------------------
-- Table structure for exa_sys_parameters
-- 系統(tǒng)參數(shù)表
-- ----------------------------
DROP TABLE IF EXISTS exa_sys_parameters;
CREATE TABLE exa_sys_parameters
(
  class_id			INT(11)			NOT NULL DEFAULT 0  COMMENT '參數(shù)類別ID',
  class_key			VARCHAR(60)		NOT NULL DEFAULT '' COMMENT '參數(shù)類別key',
  class_name		VARCHAR(60)		NOT NULL DEFAULT '' COMMENT '參數(shù)類別名稱',
  item_id			INT(11)			NOT NULL DEFAULT 0  COMMENT '參數(shù)類別下子項(xiàng)ID',
  item_key			VARCHAR(200)	NOT NULL DEFAULT '' COMMENT '子項(xiàng)key',
  item_name			VARCHAR(60)		NOT NULL DEFAULT '' COMMENT '子項(xiàng)名稱',
  item_value		VARCHAR(200)	NOT NULL DEFAULT '' COMMENT '子項(xiàng)值',
  item_desc			VARCHAR(512)	NOT NULL DEFAULT '' COMMENT '子項(xiàng)描述',

  -- 記錄操作信息
  operator_name		VARCHAR(80)		NOT NULL DEFAULT '' COMMENT '操作人賬號(hào)',
  delete_flag		TINYINT(4)		NOT NULL DEFAULT 0  COMMENT '記錄刪除標(biāo)記,0-正常、1-已刪除',
  create_time		DATETIME		NOT NULL DEFAULT NOW() COMMENT '創(chuàng)建時(shí)間',
  update_time		DATETIME		DEFAULT NULL ON UPDATE NOW() COMMENT '更新時(shí)間',
  PRIMARY KEY (class_id, item_id)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8 COMMENT '系統(tǒng)參數(shù)表';

CREATE INDEX exa_sys_parameters_class_key_item_key ON exa_sys_parameters (class_key, item_key);

-- 10001-10099 保留給基礎(chǔ)表,即用戶、權(quán)限相關(guān)的類型定義

INSERT INTO exa_sys_parameters(class_id, class_key, class_name, item_id, item_key, item_name,item_value, item_desc)
VALUES (10001, 'user_type', '用戶類型', 1, '1', 'admin','系統(tǒng)管理員', '');
INSERT INTO exa_sys_parameters(class_id, class_key, class_name, item_id, item_key, item_name,item_value, item_desc)
VALUES (10001, 'user_type', '用戶類型', 2, '2', 'internal person','公司內(nèi)部用戶', '');
INSERT INTO exa_sys_parameters(class_id, class_key, class_name, item_id, item_key, item_name,item_value, item_desc)
VALUES (10001, 'user_type', '用戶類型', 3, '3', 'external person','外部用戶', '');

INSERT INTO exa_sys_parameters(class_id, class_key, class_name, item_id, item_key, item_name,item_value, item_desc)
VALUES (10002, 'sex', '性別', 1, '1', 'none','無值', '');
INSERT INTO exa_sys_parameters(class_id, class_key, class_name, item_id, item_key, item_name,item_value, item_desc)
VALUES (10002, 'sex', '性別', 2, '2', 'male','男', '');
INSERT INTO exa_sys_parameters(class_id, class_key, class_name, item_id, item_key, item_name,item_value, item_desc)
VALUES (10002, 'sex', '性別', 3, '3', 'female','女', '');
INSERT INTO exa_sys_parameters(class_id, class_key, class_name, item_id, item_key, item_name,item_value, item_desc)
VALUES (10002, 'sex', '性別', 4, '4', 'other','其它', '');
?	關(guān)于系統(tǒng)參數(shù)表的作用,參見:(<a  target="_blank">使用系統(tǒng)參數(shù)表,提升系統(tǒng)的靈活性</a>)。
?	系統(tǒng)參數(shù)也可以復(fù)用,如true_false類別,0表示否,1表示是,這個(gè)系統(tǒng)參數(shù)類別可以為多個(gè)表的枚舉字段使用。
?	系統(tǒng)參數(shù)表的item_name可用于Java的枚舉類的枚舉項(xiàng)的名稱,這樣可提高代碼的可讀性,在接口參數(shù)校驗(yàn)時(shí),對(duì)于枚舉字段,需要使用枚舉類型進(jìn)行值的合法性檢查。在后面提到的單元測(cè)試隨機(jī)構(gòu)造測(cè)試樣本時(shí),枚舉字段的取值受此枚舉類約束。

3.4、關(guān)于全局ID算法

?	全局ID可以有多種生成方法,如基于Redis的算法,雪花算法等,此處提供了一種基于Mysql數(shù)據(jù)庫的全局ID方案,包括2張表和一個(gè)函數(shù)。
-- ----------------------------
-- Table structure for exa_table_code_config
-- ID編碼配置表
-- ----------------------------
DROP TABLE IF EXISTS exa_table_code_config;
CREATE TABLE exa_table_code_config
(
  table_id			INT(11)			NOT NULL DEFAULT 0  COMMENT '表ID',
  table_name		VARCHAR(80)		NOT NULL DEFAULT '' COMMENT '表名稱',
  field_name		VARCHAR(80)		NOT NULL DEFAULT '' COMMENT 'ID字段名稱',

  -- 格式化編碼使用,如15編碼為HR000015,即數(shù)字前面用0填補(bǔ)。
  prefix			VARCHAR(20)		NOT NULL DEFAULT '' COMMENT '編碼前綴字符串',
  prefix_len		TINYINT(4)		NOT NULL DEFAULT 0  COMMENT '編碼前綴字符串長度',
  seqno_len			TINYINT(4)		NOT NULL DEFAULT 0  COMMENT '序列號(hào)長度',
  PRIMARY KEY (table_id)
) ENGINE = Innodb
  DEFAULT CHARSET = utf8 COMMENT 'ID編碼配置表';

CREATE INDEX exa_table_code_config_table_name ON exa_table_code_config(table_name);

-- 本系統(tǒng)的table_id以10001開始
INSERT INTO exa_table_code_config(table_id,table_name,field_name) 
VALUES(10001,'exa_users','user_id');
INSERT INTO exa_table_code_config(table_id,table_name,field_name) 
VALUES(10002,'exa_roles','role_id');
INSERT INTO exa_table_code_config(table_id,table_name,field_name) 
VALUES(10004,'exa_orgnizations','org_id');
INSERT INTO exa_table_code_config(table_id,table_name,field_name) 
VALUES(10005,'exa_functions','func_id');

-- ----------------------------
-- Table structure for exa_table_id_allocate
-- ID最新可用值表
-- ----------------------------
DROP TABLE IF EXISTS exa_table_id_allocate;
CREATE TABLE exa_table_id_allocate
(
  table_id			INT(11)			NOT NULL DEFAULT 0 COMMENT '表ID',
  last_id			BIGINT(20)		NOT NULL DEFAULT 0 COMMENT '最新可用ID值',
  PRIMARY KEY (table_id)
) ENGINE = Innodb
  DEFAULT CHARSET = utf8 COMMENT 'ID最新可用值表';

-- 初始記錄
-- exa_users 預(yù)留10個(gè)賬號(hào),保留給內(nèi)部系統(tǒng)使用
INSERT INTO exa_table_id_allocate(table_id,last_id) VALUES(10001,11);
INSERT INTO exa_table_id_allocate(table_id,last_id) VALUES(10002,4);
INSERT INTO exa_table_id_allocate(table_id,last_id) VALUES(10004,2);
INSERT INTO exa_table_id_allocate(table_id,last_id) VALUES(10005,1000);

-- ----------------------------------------------------------------------
-- 函數(shù):獲取全局ID
-- tableid: 表ID
-- record_count: 需要分配ID的記錄條數(shù),大于等于1
-- return: 第一條記錄的ID
-- ----------------------------------------------------------------------
DELIMITER ;
DROP FUNCTION IF EXISTS exa_get_global_id;
CREATE FUNCTION exa_get_global_id(tableid INT(11), record_count INT(11))
  RETURNS BIGINT(20)
  DETERMINISTIC
BEGIN
  UPDATE exa_table_id_allocate
  SET
    last_id = (@exaid := last_id) + record_count
  WHERE table_id = tableid;
  RETURN @exaid;
END;
?	經(jīng)過測(cè)試,這種方法獲取的全局ID約為1000條/秒,而自增ID的獲取速度約為600-800條/秒,另外當(dāng)表的字段越多,自增ID的性能越差,而此方法的性能不受字段數(shù)目影響。
?	當(dāng)有高頻記錄ID需要處理時(shí),針對(duì)這類ID,可由服務(wù)器每次批量領(lǐng)取一定數(shù)目的ID,如1000個(gè)連續(xù)ID,服務(wù)器內(nèi)部使用內(nèi)存分發(fā)ID,這樣就可以達(dá)到100萬條/秒的處理性能,有點(diǎn)類似于雪花算法了,這與服務(wù)器是否分布式部署無關(guān)。
?	注意:@exaid為Mysql的全局變量,因此不同項(xiàng)目需要使用不同的變量名。

3.5、關(guān)于字段名下劃線到屬性字段駝峰的映射

?	Java的實(shí)體類屬性字段名,一般使用駝峰規(guī)則。這樣就涉及到下劃線到駝峰的映射。
?	首先,配置文件需要設(shè)置mybatis使用下劃線轉(zhuǎn)駝峰的映射:
mybatis.configuration.map-underscore-to-camel-case=true
?	這樣,表字段名可以映射實(shí)體類的屬性名。
?	另外,需要注意的是,對(duì)于返回類型為Map<String, Object>或List<Map<String, Object>>的查詢,字段名不會(huì)從下劃線轉(zhuǎn)為駝峰(參見:<a  target="_blank">mybatis Map查詢結(jié)果下劃線轉(zhuǎn)駝峰的實(shí)例</a>)。
?	這里提供另外一種解決思路,即開發(fā)下列三個(gè)公共方法:
	// 下劃線字符串轉(zhuǎn)為駝峰字符串
	public static String underlineToCamel(String input);

	// key為下劃線字符串轉(zhuǎn)為key為駝峰字符串的字典
	public static Map<String, Object> underlineToCamel(Map<String, Object> map);

	// key為下劃線字符串轉(zhuǎn)為key為駝峰字符串的字典列表
	public static List<Map<String, Object>> underlineToCamel(List<Map<String, Object>> mapList);

?	對(duì)于返回類型為Map<String, Object>或List<Map<String, Object>>的查詢結(jié)果,先調(diào)用underlineToCamel方法處理,然后就可以用屬性名訪問了。

3.6、權(quán)限管理

?	權(quán)限管理與數(shù)據(jù)庫設(shè)計(jì)有關(guān)。
?	權(quán)限管理分兩個(gè)層面,一個(gè)是功能權(quán)限,一個(gè)是數(shù)據(jù)權(quán)限。

3.6.1、功能權(quán)限管理

?	功能權(quán)限是用戶可以觀察和操作的頁面元素的權(quán)限,包括菜單權(quán)限和功能操作權(quán)限,這個(gè)通常是基于RBAC(Role-Based Access Control),即基于角色的訪問控制,就是角色表、功能表、角色與功能關(guān)系表、用戶與角色關(guān)系表,來定義功能項(xiàng),角色項(xiàng),每種角色可以操作的功能集合,用戶擁有的角色集合,從而得到用戶可以操作的功能集合。
?	下面是相關(guān)表結(jié)構(gòu):
-- ----------------------------
-- Table structure for exa_functions
-- 功能表
-- ----------------------------
DROP TABLE IF EXISTS exa_functions;
CREATE TABLE exa_functions
(
  func_id			INT(11)			NOT NULL DEFAULT 0  COMMENT '功能ID',
  func_name			VARCHAR(100)	NOT NULL DEFAULT '' COMMENT '功能名稱',
  parent_id			INT(11)			NOT NULL DEFAULT 0  COMMENT '父功能ID',
  level				TINYINT(4)		NOT NULL DEFAULT 0  COMMENT '功能所在層級(jí)',
  order_no			INT(11)			NOT NULL DEFAULT 0  COMMENT '顯示順序',
  url				VARCHAR(80)		NOT NULL DEFAULT '' COMMENT '訪問接口url',
  dom_key			VARCHAR(80)		NOT NULL DEFAULT '' COMMENT 'dom對(duì)象的ID',
  img_tag			VARCHAR(80)		NOT NULL DEFAULT '' COMMENT '節(jié)點(diǎn)icon名稱',

  remark			VARCHAR(200)	NOT NULL DEFAULT '' COMMENT '備注',

  -- 記錄操作信息
  operator_name		VARCHAR(80)		NOT NULL DEFAULT '' COMMENT '操作人賬號(hào)',
  delete_flag		TINYINT(4)		NOT NULL DEFAULT 0  COMMENT '記錄刪除標(biāo)記,0-正常、1-已刪除',
  create_time		DATETIME		NOT NULL DEFAULT NOW() COMMENT '創(chuàng)建時(shí)間',
  update_time		DATETIME		DEFAULT NULL ON UPDATE NOW() COMMENT '更新時(shí)間',
  PRIMARY KEY (func_id)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8 COMMENT ='功能表';

-- ----------------------------
-- Table structure for exa_roles
-- 角色表
-- ----------------------------
DROP TABLE IF EXISTS exa_roles;
CREATE TABLE exa_roles
(
  role_id			INT(11)			NOT NULL DEFAULT 0  COMMENT '角色I(xiàn)D',
  role_name			VARCHAR(40)		NOT NULL DEFAULT '' COMMENT '角色名稱',
  role_type			TINYINT(4)		NOT NULL DEFAULT 0  COMMENT '角色類型,參見系統(tǒng)參數(shù)表',
  remark			VARCHAR(100)	NOT NULL DEFAULT '' COMMENT '描述',

  operator_name		VARCHAR(80)		NOT NULL DEFAULT '' COMMENT '操作人賬號(hào)',
  delete_flag		TINYINT(4)		NOT NULL DEFAULT 0  COMMENT '記錄刪除標(biāo)記,0-正常、1-已刪除',
  create_time		DATETIME		NOT NULL DEFAULT NOW() COMMENT '創(chuàng)建時(shí)間',
  update_time		DATETIME		DEFAULT NULL ON UPDATE NOW() COMMENT '更新時(shí)間',
  PRIMARY KEY (role_id)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8 COMMENT ='角色表';

INSERT INTO exa_roles(role_id,role_name,role_type) VALUES(1,'系統(tǒng)管理員',1);
INSERT INTO exa_roles(role_id,role_name,role_type) VALUES(2,'賬號(hào)管理員',2);
INSERT INTO exa_roles(role_id,role_name,role_type) VALUES(3,'運(yùn)維人員',3);

-- ----------------------------
-- Table structure for exa_role_func_rights
-- 角色和功能權(quán)限關(guān)系表
-- 角色和功能權(quán)限是多對(duì)多關(guān)系
-- ----------------------------
DROP TABLE IF EXISTS exa_role_func_rights;
CREATE TABLE exa_role_func_rights
(
  role_id			INT(11)			NOT NULL DEFAULT 0  COMMENT '角色I(xiàn)D',
  func_id			INT(11)			NOT NULL DEFAULT 0  COMMENT '功能ID',
  sub_full_flag		TINYINT(4)		NOT NULL DEFAULT 0  COMMENT '是否包含全部子節(jié)點(diǎn)權(quán)限,0-否,1-是',

  operator_name		VARCHAR(80)		NOT NULL DEFAULT '' COMMENT '操作人賬號(hào)',
  delete_flag		TINYINT(4)		NOT NULL DEFAULT 0  COMMENT '記錄刪除標(biāo)記,保留字段',
  create_time		DATETIME		NOT NULL DEFAULT NOW() COMMENT '創(chuàng)建時(shí)間',
  update_time		DATETIME 		DEFAULT NULL ON UPDATE NOW() COMMENT '更新時(shí)間',
  PRIMARY KEY (role_id, func_id)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8 COMMENT ='角色和功能權(quán)限關(guān)系表';  
?	功能表的URL字段,用于后端訪問控制,一般使用AOP來實(shí)現(xiàn)。前端使用dom_key字段(即element的id屬性),對(duì)于Vue等單頁面框架,不同模塊可以重復(fù)使用相同的dom_key值,如新增按鈕都使用"add";對(duì)于非單頁面框架,如bootstrap的js框架等,要注意確保dom_key值的唯一性。
?	關(guān)于Vue前端的訪問控制,參見:<a  target="_blank">Vue前端訪問控制方案</a>和<a  target="_blank">Vue 前端權(quán)限控制的優(yōu)化改進(jìn)版</a>。
?	功能權(quán)限管理與CRUD關(guān)系不大,各個(gè)模塊無需維護(hù)。

3.6.2、數(shù)據(jù)權(quán)限管理

?	對(duì)于某項(xiàng)功能,如果有功能權(quán)限時(shí),所有用戶看到或操作的數(shù)據(jù)集如果是一樣的,則無需數(shù)據(jù)權(quán)限控制,只需要功能權(quán)限控制即可。如果不同用戶,使用相同的功能,可訪問的數(shù)據(jù)集不同,則需要數(shù)據(jù)權(quán)限。
?	數(shù)據(jù)權(quán)限是用戶可以觀察和操作的數(shù)據(jù)集的權(quán)限,這個(gè)也稱為RBAC(Resource-Based Access Control),即基于資源的訪問控制,為了區(qū)別于基于角色的訪問控制,我將之定義為R2BAC。
?	如果不同組織有各自的賬號(hào)管理員,其可以分配管理自己組織的用戶賬號(hào),但不能看到和操作其它組織的用戶賬號(hào),這就是數(shù)據(jù)權(quán)限的典型例子。
?	數(shù)據(jù)權(quán)限,有“功能+行+列”3個(gè)維度。功能維度,即不同操作功能可訪問的數(shù)據(jù)集不同,如某類賬號(hào)管理員可以查詢本組織的所有賬號(hào),但只能編輯由其創(chuàng)建的那些賬號(hào)。行維度,為數(shù)據(jù)記錄集合,即可以訪問哪些記錄。列維度,為字段集合,如對(duì)某些用戶,可以看到全部字段;對(duì)另外一些用戶,某些字段不顯示。
?	功能維度,對(duì)于大部分應(yīng)用,不需要,即增刪改查的數(shù)據(jù)集是相同的(撇開功能權(quán)限)。如需要,配置數(shù)據(jù)權(quán)限的功能ID。
?	行維度,即數(shù)據(jù)篩選,實(shí)際上是定義數(shù)據(jù)過濾的條件。數(shù)據(jù)過濾條件可以非常復(fù)雜,復(fù)雜的過濾條件一般直接用代碼層面控制,而常用的數(shù)據(jù)過濾條件一般是記錄的某個(gè)或某幾個(gè)ID字段的取值范圍,相當(dāng)于sql語句的"in (...)",下面給出的設(shè)計(jì)方案是ID字段的行維度數(shù)據(jù)權(quán)限訪問控制。
?	列維度,可以用數(shù)據(jù)權(quán)限字段過濾表來定義,但由于不大常用,一般也不用,而是直接用代碼層面控制,將相關(guān)過濾的屬性值設(shè)置為null即可。
?	在CRUD代碼實(shí)現(xiàn)時(shí),需要加入數(shù)據(jù)權(quán)限的校驗(yàn)和過濾。如對(duì)組織的賬號(hào)管理員,新增時(shí),需要判斷orgId是否在許可集中;編輯時(shí),原記錄的orgId是否在許可集中,如修改了orgId,新的orgId是否在許可集中;刪除時(shí),需要判斷orgId是否在許可集中;查詢時(shí),需要將權(quán)限許可的orgIdList加入查詢條件,或查詢后,檢查orgId是否在許可集中。
?	下面是數(shù)據(jù)權(quán)限行維度訪問控制的相關(guān)表:
-- ----------------------------
-- Table structure for exa_dr_fields
-- 數(shù)據(jù)權(quán)限相關(guān)字段表
-- 為簡化處理,要求權(quán)限相關(guān)字段,在所有表中具有相同的定義和含義
-- ----------------------------
DROP TABLE IF EXISTS exa_dr_fields;
CREATE TABLE exa_dr_fields
(
  field_id			INT(11)			NOT NULL DEFAULT 0  COMMENT '字段ID',
  field_name		VARCHAR(80)		NOT NULL DEFAULT '' COMMENT '字段名稱',
  prop_name			VARCHAR(80)		NOT NULL DEFAULT '' COMMENT '屬性名稱',
  invalid_value		VARCHAR(20)		NOT NULL DEFAULT '' COMMENT '無效值,用于ID字段無權(quán)限時(shí)的查詢條件',
  has_sub			TINYINT(4)		NOT NULL DEFAULT 0  COMMENT '是否有下級(jí)對(duì)象,0-否,1-是',
  is_user_prop		TINYINT(4)		NOT NULL DEFAULT 0  COMMENT '是否為用戶屬性字段,0-否,1-是',
  is_id				TINYINT(4)		NOT NULL DEFAULT 0  COMMENT '是否為ID字段,即起源表的主鍵,0-否,1-是',
  remark			VARCHAR(200)	NOT NULL DEFAULT '' COMMENT '備注',

  -- 記錄操作信息
  operator_name		VARCHAR(80)		NOT NULL DEFAULT '' COMMENT '操作人賬號(hào)',
  delete_flag		TINYINT(4)		NOT NULL DEFAULT 0  COMMENT '記錄標(biāo)記,,0-正常、1-已刪除',
  create_time		DATETIME		NOT NULL DEFAULT NOW() COMMENT '創(chuàng)建時(shí)間',
  update_time		DATETIME		DEFAULT NULL ON UPDATE NOW() COMMENT '更新時(shí)間',
  PRIMARY KEY (field_id)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8 COMMENT ='數(shù)據(jù)權(quán)限相關(guān)字段表';

INSERT INTO exa_dr_fields(field_id,field_name,prop_name,invalid_value,has_sub,is_user_prop,is_id) 
VALUES(1,'org_id','orgId','-1',1,1,1);

-- ----------------------------
-- Table structure for exa_user_drs
-- 用戶數(shù)據(jù)權(quán)限表
-- 用戶對(duì)各個(gè)權(quán)限相關(guān)字段,應(yīng)都有一條記錄,如無記錄,表示無權(quán)限
-- ----------------------------
DROP TABLE IF EXISTS exa_user_drs;
CREATE TABLE exa_user_drs
(
  user_id			BIGINT(20)		NOT NULL DEFAULT 0  COMMENT '用戶ID',
  field_id			INT(11)			NOT NULL DEFAULT 0  COMMENT '字段ID',
  field_name		VARCHAR(80)		NOT NULL DEFAULT '' COMMENT '字段名',
  -- 如果字段為用戶屬性字段,則允許使用默認(rèn)規(guī)則,否則不允許
  dr_type			TINYINT(4)		NOT NULL DEFAULT 1  COMMENT '數(shù)據(jù)權(quán)限類型,1-默認(rèn)規(guī)則、2-自定義、3-全部',
  -- 如果字段不是ID類型,可以使用表達(dá)式,目前暫時(shí)不用
  expr				VARCHAR(255)	NOT NULL DEFAULT '' COMMENT '表達(dá)式',
  func_id			INT(11)			NOT NULL DEFAULT 0  COMMENT '功能ID,0-所有功能',

  -- 記錄操作信息
  operator_name		VARCHAR(80)		NOT NULL DEFAULT '' COMMENT '操作人賬號(hào)',
  delete_flag		TINYINT(4)		NOT NULL DEFAULT 0  COMMENT '記錄標(biāo)記,保留',
  create_time		DATETIME		NOT NULL DEFAULT NOW() COMMENT '創(chuàng)建時(shí)間',
  update_time		DATETIME		DEFAULT NULL ON UPDATE NOW() COMMENT '更新時(shí)間',
  PRIMARY KEY (user_id,field_id)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8 COMMENT ='數(shù)據(jù)權(quán)限規(guī)則表';

-- ----------------------------
-- Table structure for exa_user_custom_drs
-- 用戶自定義數(shù)據(jù)權(quán)限表
-- 僅針對(duì)數(shù)據(jù)權(quán)限類型為自定義的用戶數(shù)據(jù)權(quán)限記錄
-- 由于不確定有多少個(gè)自定義權(quán)限字段,因此使用了記錄ID作為主鍵,方便增加字段
-- ----------------------------
DROP TABLE IF EXISTS exa_user_custom_drs;
CREATE TABLE exa_user_custom_drs
(
  user_id			BIGINT(20)		NOT NULL DEFAULT 0  COMMENT '用戶ID',
  field_id			INT(11)			NOT NULL DEFAULT 0  COMMENT '字段ID',
  field_value		INT(11)			NOT NULL DEFAULT 0  COMMENT '字段值',

  -- 記錄操作信息
  operator_name		VARCHAR(80)		NOT NULL DEFAULT '' COMMENT '操作人賬號(hào)',
  delete_flag		TINYINT(4)		NOT NULL DEFAULT 0  COMMENT '記錄標(biāo)記,保留',
  create_time		DATETIME		NOT NULL DEFAULT NOW() COMMENT '創(chuàng)建時(shí)間',
  update_time		DATETIME		DEFAULT NULL ON UPDATE NOW() COMMENT '更新時(shí)間',
  PRIMARY KEY (user_id,field_id,field_value)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8 COMMENT ='用戶數(shù)據(jù)權(quán)限關(guān)系表';
?	使用了三個(gè)表來管理數(shù)據(jù)權(quán)限,如果需要列維度的數(shù)據(jù)權(quán)限,則還需要增加數(shù)據(jù)權(quán)限字段過濾表。
?	數(shù)據(jù)權(quán)限相關(guān)字段表exa_dr_fields,用于定義數(shù)據(jù)權(quán)限相關(guān)的字段,包括數(shù)據(jù)庫字段名稱,對(duì)象屬性名。為方便數(shù)據(jù)權(quán)限管理,這個(gè)名稱和含義是整個(gè)系統(tǒng)一致的,如org_id,表示組織ID,則所有表中如包含org_id字段的,其含義必須是組織ID。
?	invalid_value為字段的某個(gè)無效值,如ID字段一般大于0,但有時(shí)0表示全部,所以一般取-1表示ID的無效值。當(dāng)對(duì)該字段無權(quán)限時(shí),使用無效值,如orgIdList為[-1],查詢條件為"org_id in (-1)",查詢到的結(jié)果集為空集,表示無權(quán)限。
?	has_sub,表示是否有下級(jí)對(duì)象,即ID字段代表的對(duì)象是否支持樹型結(jié)構(gòu),如組織對(duì)象,支持下級(jí)對(duì)象;而班級(jí)對(duì)象,則不支持下級(jí)對(duì)象。為了方便權(quán)限設(shè)置,如果包含所有下級(jí)對(duì)象的權(quán)限,只需設(shè)置父級(jí)對(duì)象的權(quán)限,而不必一一設(shè)置。
?	is_user_prop,是否為用戶屬性字段,如果為用戶屬性字段(用戶表或用戶擴(kuò)展表,用戶的某種屬性值),則可以使用默認(rèn)權(quán)限。如用戶只能屬于某一個(gè)組織,則org_id為用戶屬性字段;如果用戶可以屬于某幾個(gè)組織,則用戶表的組織ID屬性失去意義,就不能使用默認(rèn)數(shù)據(jù)權(quán)限。
?	is_id,是否為ID字段,即起源表的主鍵,即為某種對(duì)象的ID。目前所有權(quán)限字段都是ID字段,該字段是為了保留擴(kuò)展的可能性(如需要增加數(shù)據(jù)權(quán)限字段過濾表,則過濾字段一般就不是ID字段)。

?	用戶數(shù)據(jù)權(quán)限表exa_user_drs,用于定義對(duì)不同數(shù)據(jù)權(quán)限字段和功能ID的數(shù)據(jù)權(quán)限類型。
?	dr_type,數(shù)據(jù)權(quán)限類型,1-默認(rèn)規(guī)則、2-自定義、3-全部。如果字段為用戶屬性字段,則可以使用“默認(rèn)規(guī)則”。如用戶只能屬于某一個(gè)組織,則org_id為用戶屬性字段,默認(rèn)規(guī)則就是用戶可以訪問本組織及下屬組織的所有數(shù)據(jù)?!白远x”,就是權(quán)限范圍通過用戶自定義數(shù)據(jù)權(quán)限表exa_user_custom_drs來配置,如未配置,則無數(shù)據(jù)權(quán)限(樹型對(duì)象默認(rèn)包含全部下級(jí)對(duì)象,下級(jí)對(duì)象可不配置)?!叭俊保褪菍?duì)此字段不進(jìn)行過濾。數(shù)據(jù)權(quán)限類型支持默認(rèn)規(guī)則和全部,可以方便數(shù)據(jù)配置,減少維護(hù)工作量。如支持默認(rèn)規(guī)則,則本組織下級(jí)增加一個(gè)子組織,該用戶自動(dòng)擁有對(duì)新增子組織的訪問權(quán)限,而無需在用戶自定義數(shù)據(jù)權(quán)限表中配置。
?	func_id,功能ID,用于功能維度,0表示全部。每個(gè)用戶,在每個(gè)權(quán)限字段上,都需要配置一條數(shù)據(jù)權(quán)限記錄,功能ID為0,用于不特別指定功能ID的情況下的數(shù)據(jù)權(quán)限配置。如某些功能需要特別數(shù)據(jù)權(quán)限,則再加上特定功能ID的數(shù)據(jù)權(quán)限記錄。
?	expr,用于sql條件表達(dá)式,為擴(kuò)展保留,未使用。

?	用戶自定義數(shù)據(jù)權(quán)限表exa_user_custom_drs,用于數(shù)據(jù)權(quán)限類型為自定義時(shí),ID字段的取值范圍。
?	field_value,字段值,不同ID字段的數(shù)據(jù)類型,此處使用整數(shù)型,如有Long型,則需要修改字段數(shù)據(jù)類型。

?	假設(shè)系統(tǒng)需要進(jìn)行數(shù)據(jù)權(quán)限控制的字段集為A={d1,d2,...,dn},某個(gè)表T如需要進(jìn)行數(shù)據(jù)權(quán)限控制,則其需要包含A的某個(gè)非空子集的字段。如果表T包括多個(gè)數(shù)據(jù)權(quán)限字段,則數(shù)據(jù)權(quán)限為交集,相當(dāng)于"d1 in (...) and d2 in (...)"。為了方便查詢過濾,表結(jié)構(gòu)設(shè)計(jì)時(shí),應(yīng)該增加相關(guān)數(shù)據(jù)權(quán)限字段的冗余設(shè)計(jì)。這樣查詢T時(shí),可以使用如:"di in (...)"形式的查詢條件,而不必進(jìn)行表的聯(lián)結(jié),并且冗余設(shè)計(jì)后,由于實(shí)體類對(duì)象包含了相關(guān)數(shù)據(jù)權(quán)限字段,也便于代碼實(shí)現(xiàn)。

4、Entity實(shí)體類 ?

4.1、實(shí)體類代碼示例

?	Entity實(shí)體類的代碼示例如下:
package com.abc.example.entity;

import java.time.LocalDate;
import java.time.LocalDateTime;
import javax.persistence.Column;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;

/**
 * @className	: User
 * @description	: 用戶對(duì)象實(shí)體類
 * @summary		: 
 * @history		:
 * ------------------------------------------------------------------------------
 * date			version		modifier		remarks
 * ------------------------------------------------------------------------------
 * yyyy/mm/dd	1.0.0		author		    初版
 *
 */
@Data
public class User {
	// 用戶ID
	@Column(name = "user_id")
	@JsonFormat(shape= JsonFormat.Shape.STRING)
	private Long userId = 0L;
	
	// 用戶名
	@Column(name = "user_name")
	private String userName = "";
	
	// 用戶密碼
	@Column(name = "password")
	private String password = "";
	
	// 加鹽md5算法中的鹽
	@Column(name = "salt")
	private String salt = "";
	
	// 用戶類型,1-系統(tǒng)管理員、2-公司內(nèi)部用戶、3-外部用戶
	@Column(name = "user_type")
	private Byte userType = 3;
	
	// 組織機(jī)構(gòu)ID
	@Column(name = "org_id")
	private Integer orgId = 0;
	
	// 組織名稱
	private String orgName = "";	
	
	// 真實(shí)姓名
	@Column(name = "real_name")
	private String realName = "";
	
	// Email
	@Column(name = "email")
	private String email = "";
	
	// 手機(jī)號(hào)碼
	@Column(name = "phone_number")
	private String phoneNumber = "";
	
	// 性別,1-無值、2-男、3-女、4-其它
	@Column(name = "sex")
	private Byte sex = 1;
	
	// 生日
	@Column(name = "birth")
	@JsonFormat(shape= JsonFormat.Shape.STRING, pattern="yyyy-MM-dd")
	private LocalDate birth;
	
	// 身份證號(hào)碼
	@Column(name = "id_no")
	private String idNo = "";
	
	// 微信小程序的openid
	@Column(name = "open_id")
	private String openId = "";
	
	// 微信公眾號(hào)openid
	@Column(name = "woa_openid")
	private String woaOpenid = "";
	
	// 備注
	@Column(name = "remark")
	private String remark = "";
	
	// 操作人賬號(hào)
	@Column(name = "operator_name")
	private String operatorName = "";
	
	// 記錄刪除標(biāo)記,0-正常、1-禁用
	@Column(name = "delete_flag")
	private Byte deleteFlag = 0;
	
	// 創(chuàng)建時(shí)間
	@Column(name = "create_time")
	@JsonFormat(shape= JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")
	private LocalDateTime createTime;
	
	// 更新時(shí)間
	@Column(name = "update_time")
	@JsonFormat(shape= JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")
	private LocalDateTime updateTime;	

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		User other = (User) obj;
		if (userName == null) {
			if (other.userName != null)
				return false;
		} else if (!userName.equals(other.userName))
			return false;
		return true;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((userName == null) ? 0 : userName.hashCode());
		return result;
	}	
}    

4.2、實(shí)體類開發(fā)規(guī)范

?	1)一般使用lombok的@Data注解,以替代getter/setter方法的冗長代碼。
?	2)屬性字段名使用駝峰規(guī)則,要有對(duì)應(yīng)的數(shù)據(jù)表字段名,以及屬性的描述。數(shù)據(jù)表字段名可使用JPA的@Column來表述,其它添加屬性字段則不需要@Column注解。
?	3)默認(rèn)值,這個(gè)要與表結(jié)構(gòu)一致,否則實(shí)現(xiàn)Mybatis腳本insert語句會(huì)比較復(fù)雜。
?	4)不同數(shù)據(jù)類型的前端支持問題,如LocalDateTime的格式化問題,前端Long型數(shù)據(jù)損失精度問題等,這些需要用@JsonFormat進(jìn)行注解。
?	5)與數(shù)據(jù)庫字段對(duì)應(yīng)的屬性字段,其數(shù)據(jù)類型使用類的形式,如Integer,Long,而不是int,long,這樣可以賦值為null??紤]到信息安全及數(shù)據(jù)權(quán)限,某些屬性不希望展示給前端,此時(shí)可以設(shè)置為null。需要注意的是,數(shù)據(jù)類型使用類的形式,類對(duì)象之間比較,==和!=操作符會(huì)失效,要使用equals方法來比較值。
?	6)是否需要支持對(duì)象克隆,如需支持,需要實(shí)現(xiàn)Cloneable的clone接口,支持克隆可大大簡化對(duì)象復(fù)制的處理代碼。
?	7)是否需要支持對(duì)象比較,如果實(shí)體類對(duì)象要作為Map的key,則需要實(shí)現(xiàn)equals和hashCode接口,這個(gè)可以使用IDE工具自動(dòng)生成代碼。
?	8)是否需要支持格式化輸出,如作為TreeNode的節(jié)點(diǎn)數(shù)據(jù),則需要實(shí)現(xiàn)toString接口。
?	9)是否需要增加其它表的引用字段,如orgId,需要引用組織表的orgName字段,否則前端不好展示。
?	10)是否有一些內(nèi)部字段,不希望傳到前端,可考慮使用@JsonIgnore進(jìn)行注解。
?	11)考慮線程安全,日期時(shí)間類型不再使用Date類型,而是使用LocalDateTime,LocalDate,LocalTime。另外,關(guān)于時(shí)間,涉及到時(shí)區(qū)問題,關(guān)于Mysql驅(qū)動(dòng)的配置項(xiàng)應(yīng)考慮GMT+8,即:
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/demodb?verifyServerCertificate=false&useSSL=false&characterEncoding=UTF-8&serverTimezone=GMT%2B8
?	12)是否需要支持Excel導(dǎo)入,如需支持,應(yīng)增加一個(gè)equals和hashCode方法,作為在導(dǎo)入數(shù)據(jù)時(shí)的異常數(shù)據(jù)行的定位,這個(gè)在后面Excel導(dǎo)入功能時(shí)將詳細(xì)討論。

(未完待續(xù)...)

文章來源地址http://www.zghlxwxcb.cn/news/detail-478860.html

到了這里,關(guān)于Spring Boot實(shí)現(xiàn)高質(zhì)量的CRUD-1的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • AI Code Translator —— 能夠?qū)崿F(xiàn)高質(zhì)量的自動(dòng)編程語言轉(zhuǎn)換工具

    AI Code Translator —— 能夠?qū)崿F(xiàn)高質(zhì)量的自動(dòng)編程語言轉(zhuǎn)換工具

    https://github.com/mckaywrigley/ai-code-translator AI Code Translator —— 是一款基于大型語言模型的代碼翻譯工具,同時(shí)也是一款顛覆性的編程語言翻譯工具,它基于先進(jìn)的機(jī)器學(xué)習(xí)技術(shù)和大規(guī)模語料庫訓(xùn)練而成,能夠?qū)崿F(xiàn)高質(zhì)量的自動(dòng)編程語言轉(zhuǎn)換。 這款工具最大的突破在于翻譯速度快且

    2024年02月04日
    瀏覽(64)
  • 如何編寫高質(zhì)量代碼

    如何編寫高質(zhì)量代碼

    現(xiàn)代軟件開發(fā)中,代碼是構(gòu)建高質(zhì)量軟件的核心。高質(zhì)量代碼能夠提高軟件系統(tǒng)的可靠性、可維護(hù)性和可擴(kuò)展性,減少bug的數(shù)量和修復(fù)時(shí)間,提升開發(fā)效率和代碼可讀性,同時(shí)有助于團(tuán)隊(duì)協(xié)作和知識(shí)傳承共享。 然而,夢(mèng)想是豐滿的,現(xiàn)實(shí)是骨感的!軟件開發(fā)面臨諸多挑戰(zhàn)。

    2024年02月02日
    瀏覽(675)
  • 高質(zhì)量橢圓檢測(cè)庫

    高質(zhì)量橢圓檢測(cè)庫

    目錄 前言 效果展示 檢測(cè)庫 簡介 安裝庫 用法 測(cè)試 論文算法步驟簡讀 1. lsd 檢測(cè) 2. lsd group 3. 生成初始 ellipse 4. 聚類 橢圓檢測(cè)是工業(yè)中比較常用的一種檢測(cè)需求。目前常用的基于傳統(tǒng)圖像處理的橢圓檢測(cè)方法是霍夫變換,但是霍變換的檢測(cè)率比較低,很難滿足工業(yè)場(chǎng)景。而基

    2024年02月07日
    瀏覽(876)
  • 如何寫出高質(zhì)量代碼?

    作為一名資深開發(fā)人員,寫出高質(zhì)量的代碼是我們必須要追求的目標(biāo)。然而,在實(shí)際開發(fā)中,我們常常會(huì)遇到各種問題。比如,代碼的可讀性、可維護(hù)性、健壯性和靈活性等,這些都會(huì)影響代碼的質(zhì)量。那么,究竟如何才能寫出高質(zhì)量的代碼呢? 代碼結(jié)構(gòu)清晰易懂,能夠使代

    2024年02月02日
    瀏覽(104)
  • 如何寫出高質(zhì)量代碼

    一、 前言 編寫高質(zhì)量代碼是每一位程序員的追求。高質(zhì)量的代碼可以提高代碼可讀性、可維護(hù)性、可擴(kuò)展性以及軟件運(yùn)行的性能和穩(wěn)定性。在這篇文章中,我將分享一些編寫高質(zhì)量代碼的特征、編程實(shí)踐技巧和軟件工程方法論。 可讀性:好的代碼應(yīng)該能夠被維護(hù)者輕易地理

    2024年02月02日
    瀏覽(111)
  • 如何寫出高質(zhì)量的代碼

    你是否曾經(jīng)為自己寫的代碼而感到懊惱?你是否想過如何才能寫出高質(zhì)量代碼?那就不要錯(cuò)過這個(gè)話題!在這里,我們可以討論什么是高質(zhì)量代碼,如何寫出高質(zhì)量代碼等問題。無論你是初學(xué)者還是資深開發(fā)人員,都可以在這個(gè)話題下進(jìn)行分享,汲取靈感和知識(shí),共同提高自

    2023年04月25日
    瀏覽(100)
  • 網(wǎng)絡(luò)安全高質(zhì)量文庫

    網(wǎng)絡(luò)安全高質(zhì)量文庫

    PeiQI文庫 http://api.orchidstudio.cn/ PeiQi文庫是一個(gè)面對(duì)網(wǎng)絡(luò)安全從業(yè)者的知識(shí)庫,涉及漏洞研究,代碼審計(jì),CTF奪旗,紅藍(lán)對(duì)抗等多個(gè)安全方向,用于解決安全信息不聚合,安全資料不易找的難題。幫助網(wǎng)絡(luò)安全從業(yè)者共同構(gòu)建安全的互聯(lián)網(wǎng),快速驗(yàn)證并及時(shí)修復(fù)相關(guān)漏洞,為甲

    2024年02月12日
    瀏覽(96)
  • 有哪些高質(zhì)量的自學(xué)網(wǎng)站?

    有哪些高質(zhì)量的自學(xué)網(wǎng)站?

    分享32個(gè)鮮為人知并且完全免費(fèi)的高質(zhì)量自學(xué)網(wǎng)站,每個(gè)都是堪稱神器,讓你相見恨晚。 是一個(gè)完全免費(fèi)的綜合視頻教程網(wǎng)站,非常良心實(shí)用。 它提供的視頻教程非常豐富并且質(zhì)量很高,包括:PS 教程、手機(jī)攝影教程、Ai 做圖教程、Excel 教程、Word 教程、PPT 教程、Pr 視頻剪輯

    2024年02月02日
    瀏覽(96)
  • 如何編寫高質(zhì)量的測(cè)試計(jì)劃

    如何編寫高質(zhì)量的測(cè)試計(jì)劃

    1.1目的 簡述本計(jì)劃的目的,旨在說明各種測(cè)試階段任務(wù)、人員分配和時(shí)間安排、工作規(guī)范等。 測(cè)試計(jì)劃在策略和方法的高度說明如何計(jì)劃、組織和管理測(cè)試項(xiàng)目。測(cè)試計(jì)劃包含足夠的信息使測(cè)試人員明白項(xiàng)目需要做什么是如何運(yùn)作的。另外,清晰的文檔結(jié)構(gòu)能使任何一個(gè)讀

    2024年02月16日
    瀏覽(93)
  • Visio 轉(zhuǎn)為高質(zhì)量PDF

    Visio 轉(zhuǎn)為高質(zhì)量PDF

    Visio另存為pdf不夠清晰怎么辦 - - 可以選擇先另存為高分辨率的圖片( 存的時(shí)候分辨率選擇打印機(jī)或者自定義即可 ),然后轉(zhuǎn)為pdf. 或者用 打印 1 保存為高質(zhì)量 2 的pdf (本文介紹) 版本:Microsoft Visio 2010 Adobe Acrobat 2018 關(guān)鍵就是設(shè)置分辨率,不按照以上流程亦可 一般情況下安裝完

    2024年02月04日
    瀏覽(209)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包