《阿里巴巴 Java 開發(fā)手冊》讀書筆記

偶然看到阿里巴巴居然出書了踏烙?踢涌??趁著滿減活動(節(jié)約節(jié)約....)我趕緊買來準(zhǔn)備看看攘残,剛拿到的時候掂量了好多下拙友,總覺得商家給我少發(fā)了一本書,結(jié)果打開才知道..原來這本書這么小....

編碼規(guī)范的重要性

別人都說我們是搬磚的碼農(nóng)歼郭,但我們知道自己是追求個性的藝術(shù)家献宫。也許我們不會過多在意自己的外表和穿著,但在我們不羈的外表下实撒,骨子里追求著代碼的美姊途、系統(tǒng)的美涉瘾、設(shè)計(jì)的美,代碼規(guī)范其實(shí)就是一個對程序美的定義捷兰×⑴眩—— 引自 序

如果有一天在我們的項(xiàng)目中看到了這樣的代碼:

或者是這樣的代碼:

這樣美不美呢?或許看著是還挺美的贡茅,但是如果需要修改秘蛇,是不是人傻啦?

那這樣的代碼呢顶考?

作為一個對自己有一定要求的程序猿赁还,是不是第一反應(yīng)就是:

  • 重寫!
  • 原作者是誰驹沿?錘他艘策!

規(guī)范不一,就會像下圖中的小鴨和小雞對話一樣渊季,語言不通朋蔫,一臉囧相。雞同鴨講也恰恰形容了人與人之間溝通的痛點(diǎn)却汉,自說自話驯妄,無法達(dá)成一致意見。再舉一個生活中的例子合砂,交通規(guī)則靠左行駛還是靠右行駛青扔,兩者孰好孰壞并不重要,重要的是必須要在統(tǒng)一的方向上通行翩伪,表面上限制了自由微猖,但實(shí)際上是保障了公眾的人身安全。試想幻工,如果沒有規(guī)定靠右行駛励两,那樣的路況肯定擁堵不堪,險象環(huán)生囊颅。同樣当悔,過分自由隨意、天馬行空的代碼會嚴(yán)重的傷害系統(tǒng)的健康踢代,影響到可擴(kuò)展性以及可維護(hù)性盲憎。

  • 總結(jié):代碼規(guī)范很重要!

關(guān)于編碼規(guī)范的三大圣戰(zhàn)

眾所周知胳挎,互聯(lián)網(wǎng)公司的優(yōu)勢在于效率饼疙,它是企業(yè)核心競爭力。體現(xiàn)在產(chǎn)品開發(fā)領(lǐng)域慕爬,就是夠溝通效率和研發(fā)效率窑眯。對于溝通效率的重要性屏积,可以從程序猿三大 “編碼理念之爭” 說起:

  • 縮進(jìn)采用空格鍵,還是 Tab 鍵
  • if 單行語句需要大括號還是不需要大括號
  • 左大括號不換行磅甩,還是單獨(dú)另起一行

在美劇《硅谷》中炊林,有這樣的一個經(jīng)典鏡頭:

  • 程序媛:Kid? 我們似乎很久沒有一起睡了。
  • 程序猿:現(xiàn)在卷要?不可能渣聚!我永遠(yuǎn)不會和使用空格來縮進(jìn)的人睡在一起!
  • 程序媛:(瘋狂敲 space 氣走了程序猿)
  • 程序猿:(甩了一句)一個 Tab 可以代替 8個 空格僧叉!
    之后程序猿就因?yàn)橐晥D一步跨下八個階梯而摔了....

Tab 鍵和空格鍵的爭議確實(shí)存在奕枝,并且在知乎上討論得火熱:寫代碼時,縮進(jìn)使用 tab 還是空格瓶堕?

  • 總結(jié):使用 4 個空格好隘道,在《阿里巴巴 Java 開發(fā)手冊》中也明確支持了這樣的做法。下面也引用一張圖來調(diào)侃一下捞烟。

if 單語句是否需要換行薄声,也是爭論不休的話題当船。相對來說题画,寫過格式縮進(jìn)類編程語言的開發(fā)者, 更加習(xí)慣于不加大括號德频。《手冊》中明確 if/for 單行語句必須加大括號苍息,因?yàn)閱涡姓Z句的寫法,容易在添加邏輯時引起視覺上的錯誤判斷壹置。此外竞思,if 不加大括號還會有局部變量作用域的問題。

左大括號是否單獨(dú)另起一行钞护?因?yàn)?Go 語言的強(qiáng)制不換行盖喷,在這點(diǎn)上,“編程理念之爭” 的硝煙味似乎沒有那么濃难咕。如果一定要給一個理由课梳,那么換行的代碼可以增加一行,對于按代碼行數(shù)考核工作量的公司員工余佃,肯定傾向于左大括號前換行暮刃。《手冊》明確左大括號不換行!

  • 總結(jié): 其實(shí)爆土,很多編程方式客觀上沒有對錯之分椭懊,一致性很重要,可讀性很重要步势,團(tuán)隊(duì)溝通效率很重要氧猬。

第1章:編程規(guī)約

這一章是對傳統(tǒng)意義上的代碼規(guī)范背犯,包括變量命名、代碼風(fēng)格盅抚、控制語句媳板、代碼注釋等基本的變成習(xí)慣,以及從高并發(fā)場景中提煉出來的集合處理技巧與并發(fā)多線程的注意事項(xiàng)泉哈。

1.1 命名風(fēng)格

第一條:【強(qiáng)制】代碼中的命名均不能以下劃線或美元符號開始蛉幸,也不能以下劃線或美元符號結(jié)束。

  • 反例:_name / $name / name_ / name$

盡管 $ 可以作為標(biāo)識符使用丛晦,然而我們應(yīng)該盡量避免對其使用奕纫。

  • 原因: $ 通常在編譯器生成的標(biāo)識符名稱中使用,如果我們也使用這個符號烫沙,可能會有一些意想不到的錯誤發(fā)生....
  • 意想不到的錯誤示例:
package test;

public class User$VIP {
    public static void main(String[] args) {
        User user = new User();
        User.VIP vip = user.new VIP();
        vip.print();
    }
}

class User{
    class VIP{
        void print(){
            System.out.println("成員類");
        }
    }
}

仔細(xì)閱讀以下匹层,似乎并沒有什么問題,代碼也比較簡單锌蓄,但正在我們編譯的時候升筏,IDEA提示我們:

定義了重復(fù)的代碼?歸根到底瘸爽,都是 $ 惹的禍您访!因?yàn)?$ 被編譯器所使用,在源文件(.java 文件)編譯成字節(jié)碼(.class 文件)后剪决,會稱為頂層類型與嵌套類型之間的連接符灵汪。例如,如果存在一個頂層類 A柑潦,在其內(nèi)聲明了一個成員類 B享言,那么編譯之后就會產(chǎn)生兩個 class 文件,分別為 A.classA$B.class渗鬼。

就本程序來說览露,會生成 3 個 class 文件(如果可以編譯的話),分別是 User$VIP.class(頂層類)譬胎、User.classUser$VIP.class(User 類的成員類差牛,也就是類 VIP)。由于試圖存在兩個 User$VIP.class 所以才會報(bào)錯银择!

第三至第六條:【強(qiáng)制】

  • 類名使用 UpperCamelCase 風(fēng)格多糠,方法名、參數(shù)名浩考、成員變量夹孔、局部變量都同意使用 lowerCamelCase 風(fēng)格,必須遵從駝峰形式。
  • 變量命名全部大寫搭伤,單詞兼用下劃線隔開只怎,力求予以表達(dá)完整清楚,不要嫌名字太長怜俐。

正例:MAX_STOCK_COUNT / PRIZE_NUMBER_EVERYDAY
反例:MAX_COUNT / PRIZE_NUMBER

  • 抽象類命名使用 Abstract 或 Base 開頭身堡;異常類命名使用 Exception 結(jié)尾;測試類命名以它要測試的類名開始拍鲤,以 Test 結(jié)尾贴谎。

第八條:【強(qiáng)制】 POJO 類中布爾類型的變量都不要加 is 前綴,否則部分框架解析會引起序列化錯誤季稳。

反例:定義為基本數(shù)據(jù)類型 Boolen isDeleted; 的屬性擅这,它的方法名稱也是 isDeleted() ,RPC 框架在反向解析的時候景鼠,“誤以為” 對應(yīng)的屬性名稱是 deleted 仲翎,導(dǎo)致屬性獲取不到拋出異常。

第十二條:【推薦】 如果模塊铛漓、類溯香、方法使用了設(shè)計(jì)模式,應(yīng)在命名時體現(xiàn)出具體模式

  • 說明: 將設(shè)計(jì)模式體現(xiàn)在名字中浓恶,有利于閱讀者快速理解架構(gòu)設(shè)計(jì)理念玫坛。

正例:
public class OrderFactory;
public class LoginProxy;
public class ResourceObserver;

第十三條:【推薦】 接口類中的方法和屬性不要加任何修飾符號(public 也不要加),保持代碼的間接性问顷,并加上有效的 Javadoc 注釋昂秃。盡量不要在接口里定義變量禀梳,如果一定要定義變量杜窄,必須是與接口方法相關(guān)的,并且是整個應(yīng)用的基礎(chǔ)變量算途。

正例:
接口方法簽名: void commit();
接口基礎(chǔ)變量: String COMPANY = "alibaba";
反例:
接口定義方法: public abstract void commit();

  • 說明: 如果 JDK8 中接口允許有默認(rèn)實(shí)現(xiàn)塞耕,那么這個 default 方法,是對所有實(shí)現(xiàn)類都有價值的默認(rèn)實(shí)現(xiàn)嘴瓤。

第十四條:接口和實(shí)現(xiàn)類的命名規(guī)則

  • 1):【強(qiáng)制】 對于 Service 和 DAO 類扫外,基于 SOA 的理念,暴露出來的服務(wù)一定是接口廓脆,內(nèi)部的實(shí)現(xiàn)類用 Impl 后綴與接口區(qū)別筛谚。

正例: CacheServiceImpl 實(shí)現(xiàn) CacheServcie 接口

  • 2):【推薦】 如果是形容能力的接口名稱,取對應(yīng)的形容詞為接口名(通常是 -able 的形式)停忿。

正例: AbstractTranslator 實(shí)現(xiàn) Translatable驾讲。

1.2 常量定義

第二條:【強(qiáng)制】 long 或者 Long 初始賦值時,使用大寫的 L,不能是小寫的 l吮铭。小寫的 l 容易跟數(shù)字 1 混淆时迫,造成誤解。

  • 說明: Long a = 2l; 寫得是數(shù)字的 21 還是 Long 型的 2谓晌?

第三條:【推薦】 不要使用一個常量類維護(hù)所有變量掠拳,要按常量功能進(jìn)行歸類,分開維護(hù)纸肉。

  • 說明: 大而全的變量類溺欧,非得使用查找功能才能定位到修改的常量,不利于理解和維護(hù)柏肪。

正例:緩存相關(guān)常量放在類 CacheConsts 下胧奔;系統(tǒng)配置相關(guān)常量放在 ConfigConsts 下。

1.3 代碼格式

public static void main(String[] args){
    // 注釋的雙斜線與注釋內(nèi)容之間有且僅有一個空格
    // 縮進(jìn) 4 個空格
    String say = "hello";
    // 運(yùn)算符的左右必須有 1 個空格
    int flag = 0;
    // 關(guān)鍵字 if 與括號之間必須有 1 個空格预吆,括號內(nèi)的 f與左括號龙填、
    // 0 與右括號之間不需要空格
    if (flag == 0) {
        System.out.println(say);
    }
    // 左大括號前加空格且不換行;左大括號后換行
    if (flag == 1) {
        System.out.println("world");
    // 右大括號前換行拐叉,右大括號后有 else岩遗,不用換行
    } else {
        System.out.println("ok");
    // 在右大括號后直接結(jié)束,則必須換行
    }
}

第八條:【強(qiáng)制】 方法參數(shù)在定義和傳入時凤瘦,多個參數(shù)逗號后邊必須加空格宿礁。

正例:下例中實(shí)參的“one”,后邊必須要有一個空格蔬芥。
method("one", "two", "three");

1.4 OOP 規(guī)約

第二條:【強(qiáng)制】 所有的復(fù)寫方法梆靖,必須加 @Override 注解。

  • 說明: getObject() 與 get0bject() 的問題笔诵。一個是字母 O,一個是數(shù)字 0返吻,
    加 @Override 注解可以準(zhǔn)確判斷是否覆蓋成功。另外乎婿,如果在抽象類中對方法簽名進(jìn)行修改测僵,其實(shí)現(xiàn)類會馬上編譯報(bào)錯。
打臉

第七條:【強(qiáng)制】 所有相同類型的包裝類對象之間值得比較谢翎,全部使用 equals 方法

  • 說明: 對于 Intergre var = ? 在 -128~127 范圍內(nèi)的賦值捍靠, Integer 對象是在 IntegerCache.cache 中產(chǎn)生的,會復(fù)用已有的對象森逮,這個區(qū)間內(nèi)的 Integer 值可以直接使用 == 進(jìn)行判斷榨婆,但是這個區(qū)間之外的所有數(shù)據(jù),都會在堆上產(chǎn)生褒侧,并不會復(fù)用已有對象良风。這是一個大坑颜武,推薦使用 equals 方法進(jìn)行判斷。

第十二條:【強(qiáng)制】 POJO 類必須寫 toString 方法拖吼。在使用 IDE 中的工具 source>generate toString 時鳞上,如果繼承了另一個 POJO 類,注意在前面加一下 super.toString吊档。

  • 說明: 在方法執(zhí)行拋出異常時篙议,可以直接調(diào)用 POJO 的 toString() 方法打印其屬性值,便于排查問題怠硼。

1.5 集合處理

第七條:【強(qiáng)制】 不要在 foreach 循環(huán)里進(jìn)行元素的 remove / add 操作鬼贱。remove 元素請使用 Iterator 方式,如果并發(fā)操作香璃,需要對 Iterator 對象加鎖这难。

// 正例
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    String item = iterator.next();
    if (刪除元素的條件) {
        iterator.remove();
    }
}
// 反例
List<String> list = new ArrayList<>();
list.add("1");
list.add("2");
for (String item : list) {
    // 如果把 1 改為 2 再試一下看看是否相同
    if ("1".equals(item)) {
        list.remove(item);
    }
}
打臉

第十一條:【推薦】 高度注意 Map 類集合 K/V 能不能存儲 null 值得情況

1.6 并發(fā)處理

第三條:【強(qiáng)制】 線程資源必須通過線程池提供,不允許在應(yīng)用中自行顯式創(chuàng)建線程葡秒。

  • 說明: 使用線程池的好處是減少在創(chuàng)建和銷毀線程上所消耗的時間以及系統(tǒng)資源姻乓,解決資源不足的問題。如果不適用線程池眯牧,有可能造成系統(tǒng)創(chuàng)建大量同類線程而導(dǎo)致消耗完內(nèi)存或者 “過渡切換” 的問題蹋岩。
打臉

1.7 控制語句

第二條:【強(qiáng)制】 在 if / else / for / while / do 語句中,必須使用大括號学少。即使只有一行代碼剪个,也應(yīng)該避免采用單行的編碼方式:if (condition) statements;

第三條:【強(qiáng)制】 在高并發(fā)場景中,避免使用 “等于” 判斷作為終端或退出的條件

  • 說明: 如果并發(fā)控制沒有處理好版确,容易產(chǎn)生等值判斷被 “擊穿” 的情況扣囊,應(yīng)使用大于或小于的區(qū)間判斷條件來代替。

反例:判斷剩余獎品數(shù)量等于 0 時绒疗,終止發(fā)放獎品侵歇,但因?yàn)椴l(fā)處理錯誤導(dǎo)致獎品數(shù)量瞬間變成了負(fù)數(shù),這樣的話忌堂,活動無法終止盒至。

第四條:【推薦】 在表達(dá)異常的分支時,盡量少用 if-else 方式

  • 說明: 如果不得不使用 if()...else if()...else... 方式表達(dá)邏輯士修,【強(qiáng)制】 避免后續(xù)代碼維護(hù)困難,請勿超過 3 層樱衷。
// 正例:超過 3 層的 if-else 邏輯判斷代碼可以使用衛(wèi)語句棋嘲、策略模式
// 狀態(tài)模式等來實(shí)現(xiàn),其中衛(wèi)語句實(shí)例如下:
public void today() {
    if (isBusy()) {
        System.out.println("change time,");
        return;
    }

    if (isFree()) {
        System.out.println("go to travel.");
        return;
    }
    System.out.println("stay at home to learn Java");
    return;
}

1.8 注釋規(guī)約

第一條:【強(qiáng)制】 類矩桂、類屬性沸移、類方法的注釋必須使用 Javadoc 規(guī)范,使用 /**內(nèi)容*/ 格式,不得使用 //xxx 方式

第二條:【強(qiáng)制】 所有的抽象方法(包括接口中的方法)必須要用 Javadoc 注釋雹锣,除了返回值网沾、參數(shù)、異常說明外蕊爵,還必須指出該方法做什么事情辉哥,實(shí)現(xiàn)什么功能。

  • 說明: 對子類的實(shí)現(xiàn)要求攒射,或者調(diào)用注意事項(xiàng)醋旦,請一并說明。

第三條:【強(qiáng)制】 所有的類都必須添加創(chuàng)建者和創(chuàng)建日期别渔。

打臉

1.9 其他

第三條:【強(qiáng)制】 后臺輸送給網(wǎng)頁的變量必須加$!{var}——中間是感嘆號

  • 說明: 如果 var=null 或者不存在悬襟,那么 ${var} 會直接顯示在頁面上愈捅。

第四條:【強(qiáng)制】 注意 Math.random() 這個方法返回的是 double 類型,取值的范圍 0≤x<1(能夠取到零值捂人,注意除零異常),如果向獲取整數(shù)類型的隨機(jī)數(shù)矢沿,不要將 x 放大 10 的若干倍然后取整先慷,直接使用 Random 對象的 nextInt 或者 nextLong 方法。

第六條:【推薦】 不要在視圖模板中加入任何復(fù)雜的邏輯咨察。

  • 說明: 根據(jù) MVC 理論论熙,視圖的職責(zé)是展示,不要搶模型和控制器的工作摄狱。

第4章:安全規(guī)約

“安全生產(chǎn)脓诡,責(zé)任重于泰山∶揭郏” 這句話同樣適用于軟件生產(chǎn)祝谚,本章主要說明編程中需要注意的比較基礎(chǔ)的安全準(zhǔn)則。

第一條:【強(qiáng)制】 隸屬于用戶個人的頁面或者功能必須進(jìn)行權(quán)限控制校驗(yàn)

  • 說明: 放置皆有做水平權(quán)限校驗(yàn)就可以隨意訪問酣衷、修改交惯、刪除別人的數(shù)據(jù),比如查看他人的私信內(nèi)容穿仪、修改他人的訂單席爽。

第二條:【強(qiáng)制】 用戶敏感數(shù)據(jù)禁止直接展示,必須對展示數(shù)據(jù)進(jìn)行脫敏啊片。

  • 說明: 個人手機(jī)號碼會顯示為 158****9119只锻,隱藏中間 4 位,防止個人隱私泄露紫谷。

第三條:【強(qiáng)制】 用戶輸入的 SQL 參數(shù)嚴(yán)格使用參數(shù)綁定或者 METADATA 字段值限定齐饮,防止 SQL 注入捐寥,禁止字符串拼接 SQL 訪問數(shù)據(jù)庫。

打臉

第四條:【強(qiáng)制】 用戶請求傳入的任何參數(shù)必須做有效性驗(yàn)證

  • 說明: 忽略參數(shù)校驗(yàn)可能導(dǎo)致如下情況祖驱。
    1)page size 過大導(dǎo)致內(nèi)存溢出
    2)惡意 order by 導(dǎo)致數(shù)據(jù)庫慢查詢
    3)任意重定向
    4)SQL 注入
    5)反序列化注入
    6)正則輸入源串拒絕服務(wù) ReDoS
    Java 代碼用正則來驗(yàn)證客戶端的輸入握恳,有些正則寫法驗(yàn)證普通用戶輸入沒有問題,但是如果攻擊人員使用的是特殊構(gòu)造的字符串來驗(yàn)證捺僻,則有可能導(dǎo)致死循環(huán)乡洼。
打臉

第五條:【強(qiáng)制】 禁止向 HTML 頁面輸出未經(jīng)安全過濾或未正確轉(zhuǎn)義的用戶數(shù)據(jù)。

第六條:【強(qiáng)制】 表單陵像、AJAX 提交必須執(zhí)行 CSRF 安全過濾

第七條:【強(qiáng)制】 在使用平臺資源就珠,譬如短信、郵件醒颖、電話妻怎、下單、支付泞歉,必須實(shí)現(xiàn)正確的防重放限制逼侦,如數(shù)量限制、疲勞度控制腰耙、驗(yàn)證碼校驗(yàn)榛丢,避免被濫刷、資損挺庞。

  • 說明:如注冊時發(fā)送驗(yàn)證碼到手機(jī)晰赞,如果沒有限制次數(shù)和頻率,那么可以利用此功能騷擾到其它用戶选侨,并造成短信平臺資源浪費(fèi)掖鱼。

第5章:MySQL 數(shù)據(jù)庫

5.1 建表規(guī)約

第二條:【強(qiáng)制】 表名、字段名必須使用小寫字母或數(shù)字 援制, 禁止出現(xiàn)數(shù)字開頭戏挡,禁止兩個下劃線中間只出現(xiàn)數(shù)字。數(shù)據(jù)庫字段名的修改代價很大晨仑,因?yàn)闊o法進(jìn)行預(yù)發(fā)布褐墅,所以字段名稱需要慎重考慮。

  • 說明: MySQL 在 Windows 下不區(qū)分大小寫洪己,但在 Linux 下默認(rèn)區(qū)分大小寫妥凳。因此,數(shù)據(jù)庫名码泛、表明猾封、字段名都不允許出現(xiàn)任何大寫字母,避免節(jié)外生枝噪珊。

正例: getter _ admin 晌缘, task _ config , level 3_ name
反例: GetterAdmin 痢站, taskConfig 磷箕, level 3 name

第四條:【強(qiáng)制】禁用保留字,如 desc 阵难、 range 岳枷、 match 、 delayed 等呜叫,請參考 MySQL 官方保留字空繁。

第五條: 【強(qiáng)制】主鍵索引名為 pk_ 字段名;唯一索引名為 uk _字段名 朱庆; 普通索引名則為 idx _字段名盛泡。

  • 說明: pk_ 即 primary key;uk _ 即 unique key娱颊;idx _ 即 index 的簡稱傲诵。

第六條:【強(qiáng)制】小數(shù)類型為 decimal ,禁止使用 float 和 double 箱硕。

  • 說明:float 和 double 在存儲的時候拴竹,存在精度損失的問題,很可能在值的比較時剧罩,得到不正確的結(jié)果栓拜。如果存儲的數(shù)據(jù)范圍超過 decimal 的范圍,建議將數(shù)據(jù)拆成整數(shù)和小數(shù)分開存儲惠昔。

第八條:【強(qiáng)制】 varchar 是可變長字符串幕与,不預(yù)先分配存儲空間,長度不要超過 5000舰罚,如果存儲長度大于此值纽门,定義字段類型為 text ,獨(dú)立出來一張表营罢,用主鍵來對應(yīng)赏陵,避免影響其它字段索引效率。

第九條:【強(qiáng)制】表必備三字段: id , gmt _ create , gmt _ modified

  • 說明:其中 id 必為主鍵饲漾,類型為 unsigned bigint 蝙搔、單表時自增、步長為 1考传。 gmt _ create ,gmt _ modified 的類型均為 date _ time 類型吃型。

第十條: 【推薦】表的命名最好是加上“業(yè)務(wù)名稱_表的作用”。

正例: tiger _ task / tiger _ reader / mpp _ config

第十五條:【參考】合適的字符存儲長度僚楞,不但節(jié)約數(shù)據(jù)庫表空間勤晚、節(jié)約索引存儲枉层,更重要的是提升檢索速度。

正例:如下表赐写,其中無符號值可以避免誤存負(fù)數(shù)鸟蜡,且擴(kuò)大了表示范圍。

對象 年齡區(qū)間 類型 表示范圍
150 歲之內(nèi) unsigned tinyint 無符號值:0 到 255
數(shù)百歲 unsigned smallint 無符號值:0 到 65535
恐龍化石 數(shù)千萬年 unsigned int 無符號值:0 到約 42.9 億
太陽 約 50 億年 unsigned bigint 無符號值:0 到約 10 的 19 次方

5.2 索引規(guī)約

第五條: 【推薦】如果有 order by 的場景挺邀,請注意利用索引的有序性揉忘。 order by 最后的字段是組合索引的一部分,并且放在索引組合順序的最后端铛,避免出現(xiàn) file _ sort 的情況泣矛,影響查詢性能。

正例: where a =? and b =? order by c; 索引: a _ b _ c
反例:索引中有范圍查找禾蚕,那么索引有序性無法利用您朽,如: WHERE a >10 ORDER BY b; 索引 a _ b 無法排序。

第九條: 【推薦】建組合索引的時候夕膀,區(qū)分度最高的在最左邊虚倒。

正例:如果 where a =? and b =? , a 列的幾乎接近于唯一值产舞,那么只需要單建 idx _ a 索引即可魂奥。

  • 說明: 存在非等號和等號混合判斷條件時,在建索引時易猫,請把等號條件的列前置耻煤。如: where a >? and b = ? 那么即使 a 的區(qū)分度更高,也必須把 b 放在索引的最前列准颓。

5.3 SQL 語句

第一條:【強(qiáng)制】不要使用 count( 列名 ) 或 count( 常量 ) 來替代 count( * ) 哈蝇, count( * ) 是 SQL 92 定義的標(biāo)準(zhǔn)統(tǒng)計(jì)行數(shù)的語法,跟數(shù)據(jù)庫無關(guān)攘已,跟 NULL 和非 NULL 無關(guān)炮赦。

  • 說明: count( * ) 會統(tǒng)計(jì)值為 NULL 的行,而 count( 列名 ) 不會統(tǒng)計(jì)此列為 NULL 值的行样勃。

第六條: 【強(qiáng)制】不得使用外鍵與級聯(lián)吠勘,一切外鍵概念必須在應(yīng)用層解決。

  • 說明: ( 概念解釋 ) 學(xué)生表中的 student _ id 是主鍵峡眶,那么成績表中的 student _ id 則為外鍵剧防。如果更新學(xué)生表中的 student _ id ,同時觸發(fā)成績表中的 student _ id 更新辫樱,則為級聯(lián)更新峭拘。外鍵與級聯(lián)更新適用于單機(jī)低并發(fā),不適合分布式、高并發(fā)集群 鸡挠; 級聯(lián)更新是強(qiáng)阻塞辉饱,存在數(shù)據(jù)庫更新風(fēng)暴的風(fēng)險 ; 外鍵影響數(shù)據(jù)庫的插入速度宵凌。
打臉

第八條: 【強(qiáng)制】數(shù)據(jù)訂正時鞋囊,刪除和修改記錄時止后,要先 select 瞎惫,避免出現(xiàn)誤刪除,確認(rèn)無誤才能執(zhí)行更新語句译株。

打臉

5.4 ORM 映射

整個規(guī)約對自己來說都挺有用的瓜喇,因?yàn)檎蒙婕暗竭@方面,幸好感覺臉不怎么疼歉糜。

第一條:【強(qiáng)制】在表查詢中乘寒,一律不要使用 * 作為查詢的字段列表,需要哪些字段必須明確寫明匪补。

  • 說明: 1 ) 增加查詢分析器解析成本伞辛。2 ) 增減字段容易與 resultMap 配置不一致。

第二條:【強(qiáng)制】 POJO 類的 布爾 屬性不能加 is 夯缺,而數(shù)據(jù)庫字段必須加 is _蚤氏,要求在 resultMap 中進(jìn)行字段與屬性之間的映射。

  • 說明: 參見定義 POJO 類以及數(shù)據(jù)庫字段定義規(guī)定踊兜,在 <resultMap>中 增加映射竿滨,是必須的。在 MyBatis Generator 生成的代碼中捏境,需要進(jìn)行對應(yīng)的修改于游。

第三條:【強(qiáng)制】不要用 resultClass 當(dāng)返回參數(shù),即使所有類屬性名與數(shù)據(jù)庫字段一一對應(yīng)垫言,也需要定義 贰剥; 反過來,每一個表也必然有一個與之對應(yīng)筷频。

  • 說明: 配置映射關(guān)系蚌成,使字段與 DO 類解耦,方便維護(hù)截驮。

第七條:【強(qiáng)制】更新數(shù)據(jù)表記錄時笑陈,必須同時更新記錄對應(yīng)的 gmt _ modified 字段值為當(dāng)前時間。

第九條:【參考】@ Transactional 事務(wù)不要濫用葵袭。事務(wù)會影響數(shù)據(jù)庫的 QPS 涵妥,另外使用事務(wù)的地方需要考慮各方面的回滾方案,包括緩存回滾坡锡、搜索引擎回滾蓬网、消息補(bǔ)償窒所、統(tǒng)計(jì)修正等。


總結(jié)

瀏覽了一遍帆锋,還是學(xué)習(xí)到了很多東西吧吵取,上面也僅僅只是總結(jié)了對我自己比較收益,現(xiàn)階段我能吸收能實(shí)際感受得到的規(guī)約锯厢,如果想要 PDF 版的可以在這里下載:戳這里

歡迎轉(zhuǎn)載皮官,轉(zhuǎn)載請注明出處!
簡書ID:@我沒有三顆心臟
github:wmyskxz
歡迎關(guān)注公眾微信號:wmyskxz_javaweb
分享自己的Java Web學(xué)習(xí)之路以及各種Java學(xué)習(xí)資料

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末实辑,一起剝皮案震驚了整個濱河市捺氢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌剪撬,老刑警劉巖摄乒,帶你破解...
    沈念sama閱讀 221,888評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異残黑,居然都是意外死亡馍佑,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評論 3 399
  • 文/潘曉璐 我一進(jìn)店門梨水,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拭荤,“玉大人,你說我怎么就攤上這事冰木∏钆” “怎么了?”我有些...
    開封第一講書人閱讀 168,386評論 0 360
  • 文/不壞的土叔 我叫張陵踊沸,是天一觀的道長歇终。 經(jīng)常有香客問我,道長逼龟,這世上最難降的妖魔是什么评凝? 我笑而不...
    開封第一講書人閱讀 59,726評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮腺律,結(jié)果婚禮上奕短,老公的妹妹穿的比我還像新娘。我一直安慰自己匀钧,他們只是感情好翎碑,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,729評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著之斯,像睡著了一般日杈。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,337評論 1 310
  • 那天莉擒,我揣著相機(jī)與錄音酿炸,去河邊找鬼。 笑死涨冀,一個胖子當(dāng)著我的面吹牛填硕,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播鹿鳖,決...
    沈念sama閱讀 40,902評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼扁眯,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了栓辜?” 一聲冷哼從身側(cè)響起恋拍,我...
    開封第一講書人閱讀 39,807評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎藕甩,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體周荐,經(jīng)...
    沈念sama閱讀 46,349評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡狭莱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,439評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了概作。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片腋妙。...
    茶點(diǎn)故事閱讀 40,567評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖讯榕,靈堂內(nèi)的尸體忽然破棺而出骤素,到底是詐尸還是另有隱情,我是刑警寧澤愚屁,帶...
    沈念sama閱讀 36,242評論 5 350
  • 正文 年R本政府宣布济竹,位于F島的核電站,受9級特大地震影響霎槐,放射性物質(zhì)發(fā)生泄漏送浊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,933評論 3 334
  • 文/蒙蒙 一丘跌、第九天 我趴在偏房一處隱蔽的房頂上張望袭景。 院中可真熱鬧,春花似錦闭树、人聲如沸耸棒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽与殃。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間奈籽,已是汗流浹背饥侵。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留衣屏,地道東北人躏升。 一個月前我還...
    沈念sama閱讀 48,995評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像狼忱,于是被迫代替她去往敵國和親膨疏。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,585評論 2 359

推薦閱讀更多精彩內(nèi)容