Java项目开发规范

文档名称: Java项目开发规范
文档编号:V1.1
审定日期:2021年10月
一、前言
本开发规范总结了目前可找到的各种编码规范的可取之处,制定出了系统开发时应遵守的规范。从各种编码规范所要规范的内容来看,主要包括命名规范(包括类、变量、方法等)、注释规范、编码规范、数据库设计规范、代码提交规范和一些编程的惯例。其中规范命名和文档注释比较重要,它们对于改善软件的可读性很有帮助,尤其是JDK中含有提取文档注释成为单独文件的JavaDOC工具,合乎规范的文档注释可直接提取成文档供后续修改维护人员参考,其内容也比更新不够及时的设计文档更准确详细。
二、目的
1)养成良好的编程习惯。
2)写出清楚、易懂、易维护的程序代码。
3)提高软件质量与生产率。
4)减少软件编码中的不必要的错误。
5)提供完整的软件产品编码和文档。
三、目录
目录
一、 前言 1
二、 目的 1
三、 目录 1
四、 命名规范 3
1. 概述 3
2. 骆驼法则 3
3. 英文 vs 拼音 3
4. 包名 4
5. 类名 4
6. 方法名 6
7. 静态常量 7
8. 枚举 8
9. 局部变量名 8
五、 文档注释规范 9
1. 概述 9
2. 实现注释 9
3. 文档注释 10
4. 注释条件(必加) 10
5. 注释举例 11
六、 编码规范 12
1. 代码格式 12
2. 编程惯例 15
3. 技术栈规约 19
4. API接口规范 20
七、 数据库设计规范 22
1. 命名规范 22
2. 表设计规范 23
3. 索引规范 24
4. SQL规范 25
5. 其他 27
八、 代码提交规范 28

四、命名规范
1.概述
代码中的命名力求做到统一、达意和简洁;
代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束;
代码和注释中都要避免使用任何语言的种族歧视性词语。
2.骆驼法则
Java中,除了包名,静态常量等特殊情况,大部分情况下标识符使用骆驼法则,即单词之间不使用特殊符号分割,而是通过首字母大写来分割。比如: supplierName, addNewContract,而不是 supplier_name, add_new_contract。
3.英文 vs 拼音
尽量使用通俗易懂的英文单词,如果不会可以使用翻译软件,实在不行则使用汉语拼音,避免拼音与英文混用。比如表示归档,用archive比较好, 用pigeonhole则不好,用guiDang尚可接受;
杜绝完全不规范的缩写,避免望文不知义。
反例:AbstractClass“缩写”成 AbsClass;condition“缩写”成 condi;
Function 缩写”成 Fu,此类随意缩写严重降低了代码的可阅读性。
4.包名
全部使用小写字母,单词间不要用字符隔开
正例:com.axj.batchfile
反例:com.axj.batch_file
5.类名
(1)首字母大写
类名使用驼峰命名,每个自然语义的单词首字母大写,其他字母小写
正例:SendThread
反例:sendThread,Sendthread
(2)后缀
类名往往用不同的后缀表达额外的意思,如下表:
后缀名 意义 举例
Service 表明这个类是个服务类,里面包含了给其他类提同业务服务的方法 PaymentOrderService
Impl 这个类是一个实现类,而不是接口 PaymentOrderServiceImpl
Inter 这个类是一个接口 LifeCycleInter
Dao 这个类封装了数据访问方法 PaymentOrderDao
Controllter 直接处理页面请求,管理页面逻辑的类 SysConfigController
Listener 监听某种事件的类 PaymentSuccessListener
Event 这个类代表了某种事件 PaymentSuccessEvent
Servlet 一个Servlet,作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层 PaymentCallbackServlet
Factory 生成某种对象工厂的类 PaymentOrderFactory
Adapter 用来连接某种以前不被支持的对象的类 DatabaseLogAdapter
Job 某种按时间运行的任务 PaymentOrderCancelJob
Wrapper 这是一个包装类,为了给某个类提供没有的能力 SelectableOrderListWrapper
Exception 这个类是异常类 RuntimeException
Thread 表示是线程类 SendThread
Bean 遵从特定命名约定的POJO MenuStateBean
PO 持久对象,简单说PO就是数据库中的记录,一个PO的数据结构对应着库中表的结构 ShopOrderPO
DO 数据对象,等同于上面的PO xxxDO,xxx 即为数据表名
DTO 数据传输对象,泛指用于展示层与服务层之间的数据传输对象 xxxDTO,xxx 为业务领域相关的名称
VO 展示对象,VO主要的存在形式就是js里面的对象(也可以简单理解成json) xxxVO,xxx 一般为网页名称。
BO 业务对象,BO就是PO的组合
简单的例子比如说PO是一条交易记录,BO是一个人全部的交易记录集合对象 TransactionOrderBO
(3)其他
抽象类命名使用 Abstract 或 Base 开头;
测试类命名以它要测试的类的名称开始,以 Test 结尾;
POJO 是 DO/DTO/BO/VO 的统称,禁止命名成 xxxPOJO;
6.方法名
首字母小写,后面自然语义的单词首字母都大写
正例:closeSession
反例:CloseSession,closesession
方法命名格式(方法名要准确表达业务的含义):
动词前缀往往表达特定的含义,如下表:
前缀名 意义 举例
create 创建 createOrder()
delete 删除 deleteOrder()
add 创建,暗示新创建的对象属于某个集合 addPaidOrder()
remove 移除 removeOrder()
init或则initialize 初始化,暗示会做些诸如获取资源等特殊动作 initializeObjectPool
destroy 销毁,暗示会做些诸如释放资源的特殊动作 destroyObjectPool
open 打开 openConnection()
close 关闭 closeConnection()
read 读取 readUserName()
write 写入 writeUserName()
get 获得 getName()
set 设置 setName()
prepare 准备 prepareOrderList()
copy 复制 copyCustomerList()
modity 修改 modifyActualTotalAmount()
calculate 数值计算 calculateCommission()
do 执行某个过程或流程 doOrderCancelJob()
dispatch 判断程序流程转向 dispatchUserRequest()
start 开始 startOrderProcessing()
stop 结束 stopOrderProcessing()
send 发送某个消息或事件 sendOrderPaidMessage()
receive 接受消息或时间 receiveOrderPaidMessgae()
response 响应用户动作 responseOrderListItemClicked()
find 查找对象 findNewSupplier()
update 更新对象 updateCommission()
find方法在业务层尽量表达业务含义,比如 findUnsettledOrders(),查询未结算订单,而不要findOrdersByStatus()。 数据访问层,find,update等方法可以表达要执行的sql,比如findByStatusAndSupplierIdOrderByName(Status.PAID, 345)
7.静态常量
全大写用下划线分割,如
public static find String ORDER_PAID_EVENT = “ORDER_PAID_EVENT”;
(1)常量定义

  1. 不允许任何魔法值 ( 即未经预先定义的常量 ) 直接出现在代码中。
    反例:
    // 本例中,开发者 A 定义了缓存的 key,然后开发者 B 使用缓存时少了下划线,即 key 是"Id#taobao"+tradeId,导致出现故障
    String key = “Id#taobao_” + tradeId;
    cache.put(key, value);
  2. 在 long 或者 Long 赋值时,数值后使用大写字母 L,不能是小写字母 l,小写容易跟数字混淆,造成误解。
    说明:Long a = 2l; 写的是数字的 21,还是 Long 型的 2?
  3. 不要使用一个常量类维护所有常量,要按常量功能进行归类,分开维护。
    说明:大而全的常量类,杂乱无章,使用查找功能才能定位到修改的常量,不利于理解,也不利于维护。
    正例:缓存相关常量放在类 CacheConsts 下;系统配置相关常量放在类 SystemConfigConsts 下。
    8.枚举
    全大写,用下划线分割,如
    public enum Events {
    ORDER_PAID,
    ORDER_CREATED
    }
    9.局部变量名
    参数和局部变量名首字母小写,骆驼法则。尽量不要和域冲突,尽量表达这个变量在方法中的意义。
    避免在子父类的成员变量之间、或者不同代码块的局部变量之间采用完全相同的命名,
    使可理解性降低。

五、文档注释规范
1.概述
Java程序有两类注释:实现注释(implementation comments)和文档注释(document comments)。实现注释是那些使用“//”和“//”界定的注释。文档注释(被称为“doc comments”)是Java独有的,并由“//”界定。团队成员都应该形成良好的写注释的习惯,方便以后阅读,以及为了后期生成可读性良好的Java Doc。
2.实现注释
实现注释使用/
/和//界定,使用//来进行块注释,使用//进行行注释,位于注释代码上一行。
方法内部单行注释,在被注释语句上方另起一行,使用//注释。方法内部多行注释使
用/
*/注释,注意与代码对齐。
3.文档注释
文档注释描述Java的类、接口、构造器,方法,以及字段(field)。每个文档注释都会被置于注释定界符/
…*/之中,一个注释对应一个类、接口或成员。该注释应位于声明之前,javadoc是j2sdk里面一个非常重要的工具,如果你按照规范在Java的源代码里面写好注释的话,那么它就可以生成相应的文档,便于开发者察看
javadoc参数定义:
@author 对类的说明 标明开发该类模块的作者
@date 日期 类创建日期
@version 对类的说明 标明该类模块的版本
@see 一般用于标记该类相关联的类,@see即可以用在类上,也可以用在方法上。
@param 对方法的说明 对方法中某参数的说明
@return 对方法的说明 对方法返回值的说明
@exception 对方法的说明 对方法可能抛出的异常进行说明
4.注释条件(必加)
1)类的注释
2)方法的注释
3)在代码复杂处注释
4)代码修改处注释上时间和修改原因
5)全局变量注释
6)在多重嵌套和循环逻辑上注释
7)接口注释
8)调用工具类中方法的注释
5.注释举例
(1)类注释
/**

  • 类功能概述×××××××
    *@author cloud
    @date 2020-1-1
    /
    public class LogicManager {

    }
    (2)方法注释
    /
  • 方法说明×××××××
  • @param1 参数说明
  • @param2 参数说明
  • @return 返回值说明
  • @throws Exception
    /
    public boolean executeLogic(int param1, int param2) throws Exception{

    return true;
    }
    (3)全局变量、字段、属性注释
    public class ReadManager {
    /
    * 全局的计数变量*/
    private final int count;
    /** 字段/属性*/
    private String name;
    }
    六、编码规范
    1.代码格式
    1)如果是大括号内为空,则简洁地写成{}即可,大括号中间无需换行和空格;如果是非
    空代码块则:
    左大括号前不换行。
    左大括号后换行。
    右大括号前换行。
    右大括号后还有 else 等代码则不换行;表示终止的右大括号后必须换行。
    2)左小括号和右边相邻字符之间不出现空格 ; 右小括号和左边相邻字符之间也不出现空
    格;而左大括号前需要加空格。详见第 5 条下方正例提示。
    反例:if (空格 a == b 空格)
    3)if/for/while/switch/do 等保留字与括号之间都必须加空格。
    4)任何二目、三目运算符的左右两边都需要加一个空格。
    说明:包括赋值运算符=、逻辑运算符&&、加减乘除符号等。
    5)采用 4 个空格缩进,禁止使用 Tab 字符。
    说明:如果使用 Tab 缩进,必须设置 1 个 Tab 为 4 个空格。IDEA 设置 Tab 为 4 个空格时,请勿勾选 Use
    tab character(IDEA:File>setting>Editor>Code Style>Java>Tab size);而在 Eclipse 中,必须勾选 insert spaces for tabs。
    正例: (涉及 1-5 点)

6)注释的双斜线与注释内容之间有且仅有一个空格。
正例:
// 这是示例注释,请注意在双斜线之后有一个空格
String commentString = new String();
7)在进行类型强制转换时,右括号与强制转换值之间不需要任何空格隔开。
正例:
double first = 3.2d;
int second = (int)first + 2;
8)单行字符数限制不超过 120 个,超出需要换行,换行时遵循如下原则:
1、第二行相对第一行缩进 4 个空格,从第三行开始,不再继续缩进,参考示例。
2、运算符与下文一起换行。
3、方法调用的点符号与下文一起换行。
4、方法调用中的多个参数需要换行时,在逗号后进行。
5、在括号前不要换行,见反例。

方法参数在定义和传入时,多个参数逗号后面必须加空格。
正例:下例中实参的 args1,后边必须要有一个空格。
method(args1, args2, args3);
9)单个方法的总行数不超过 80 行。
说明:除注释之外的方法签名、左右大括号、方法内代码、空行、回车及任何不可见字符的总行数不超过80 行。
正例:代码逻辑分清红花和绿叶,个性和共性,绿叶逻辑单独出来成为额外方法,使主干代码更加清晰;共性逻辑抽取成为共性方法,便于复用和维护。
10)没有必要增加若干空格来使变量的赋值等号与上一行对应位置的等号对齐。
正例:
int one = 1;
long two = 2L;
float three = 3F;
StringBuilder sb = new StringBuilder();
说明:增加 sb 这个变量,如果需要对齐,则给 one、two、three 都要增加几个空格,在变量比较多的情况下,是非常累赘的事情。
11)不同逻辑、不同语义、不同业务的代码之间插入一个空行分隔开来以提升可读性。
说明:任何情形,没有必要插入多个空行进行隔开。
2.编程惯例
1)在java开发最常见的异常就是空指针(java.lang.NullPointerException)异常,需有效的规避异常,进行null判断,可能出现null模块:取集合元素,数据截取,方法返回,socket传输的数据,数据库取值等等…
2)判断所有集合内部的元素是否为空,使用 isEmpty()方法,而不是 size()==0 的方式。
说明:在某些集合中,前者的时间复杂度为 O(1),而且可读性更好。
正例:
Map<String, Object> map = new HashMap<>(16);
if(map.isEmpty()) {
System.out.println(“no element in this map.”);
}
3)Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。
正例:“test”.equals(object);
反例:object.equals(“test”);
4)BigDecimal 的等值比较应使用 compareTo()方法,而不是 equals()方法。
说明:equals()方法会比较值和精度(1.0 与 1.00 返回结果为 false),而 compareTo()则会忽略精度。
5) 禁止使用构造方法 BigDecimal(double)的方式把 double 值转化为 BigDecimal 对象。 说明:BigDecimal(double)存在精度损失风险,在精确计算或值比较的场景中可能会导致业务逻辑异常。 如:BigDecimal g = new BigDecimal(0.1F); 实际的存储值为:0.10000000149
正例:优先推荐入参为 String 的构造方法,或使用 BigDecimal 的 valueOf 方法,此方法内部其实执行了 Double 的 toString,而 Double 的 toString 按 double 的实际能表达的精度对尾数进行了截断。
BigDecimal recommend1 = new BigDecimal(“0.1”);
BigDecimal recommend2 = BigDecimal.valueOf(0.1);
6)拼接字符串尽量使用StringBuffer或者StringBuilder,使用”+”号每次会new一个对象,对空间和性能还是有一定影响的。
7)生产环境避免使用System.out.println()打印日志,改用日志框架(Log4j、Logback)打印日志。
说明:如平时调试代码或输出日志习惯使用System.out.println(),system.out都写入到一个文件里去了,对一个文件的读写就会排队写,而且syso在当前线程,必须写完才继续下面的程序。 如果使用log框架,你的日志会发散在多个日志文件上。可以控制日志是否输出,而且log框架只是通知要写日志,而不必等日志写完。
8)迭代entrySet() 获取Map 的key 和value
说明:keySet 其实是遍历了 2 次,一次是转为 Iterator 对象,另一次是从 hashMap 中取出 key 所对应的 value。而 entrySet 只是遍历了一次就把 key 和 value 都放到了 entry 中,效率更高。如果是 JDK8,使用 Map.forEach 方法。
避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成 本,直接用类名来访问即可。
9)捕获异常是为了处理它,不要捕获了却什么都不处理而抛弃之,如果不想处理它,请 将该异常抛给它的调用者。最外层的业务使用者,必须处理异常,将其转化为用户可以理解的内容。
10)所有的覆写方法,必须加@Override 注解。
说明:getObject()与 get0bject()的问题。一个是字母的 O,一个是数字的 0,加@Override 可以准确判 断是否覆盖成功。另外,如果在抽象类中对方法签名进行修改,其实现类会马上编译报错。
11)定义数据对象 DO 类时,属性类型要与数据库字段类型相匹配。
正例:数据库字段的 bigint 必须与类属性的 Long 类型相对应。
反例:某个案例的数据库表 id 字段定义类型 bigint unsigned,实际类对象属性为 Integer,随着 id 越来 越大,超过 Integer 的表示范围而溢出成为负数。
12)定义 DO/DTO/VO 等 POJO 类时,不要设定任何属性默认值。
反例:POJO 类的 createTime 默认值为 new Date(),但是这个属性在数据提取时并没有置入具体值,在 更新其它字段时又附带更新了此字段,导致创建时间被修改成当前时间。
13)序列化类新增属性时,请不要修改 serialVersionUID 字段,避免反序列失败;如果 完全不兼容升级,避免反序列化混乱,那么请修改 serialVersionUID 值。
说明:注意 serialVersionUID 不一致会抛出序列化运行时异常。
14)获取当前毫秒数:System.currentTimeMillis(); 而不是 new Date().getTime()。
15)不允许在程序任何地方中使用:
java.sql.Date;
java.sql.Time;
java.sql.Timestamp。
说明:第 1 个不记录时间,getHours()抛出异常;
第 2 个不记录日期,getYear()抛出异常;
第 3 个在构造方法 super((time/1000)*1000),在 Timestamp 属性 fastTime 和 nanos 分别存储秒和纳秒信息。
反例: java.util.Date.after(Date)进行时间比较时,当入参是 java.sql.Timestamp 时,会触发 JDK BUG(JDK9 已修复),可能导致比较时的意外结果。
16)不要在程序中写死一年为 365 天,避免在公历闰年时出现日期转换错误或程序逻辑 错误。
17)不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator 方式,如果并发操作,需要对 Iterator 对象加锁。
正例:
List list = new ArrayList<>(); list.add(“1”);
list.add(“2”); Iterator iterator = list.iterator(); while (iterator.hasNext()) {
String item = iterator.next();
if (删除元素的条件) {
iterator.remove();
} }
反例:
for (String item : list) {
if (“1”.equals(item)) {
list.remove(item);
} }
3.技术栈规约
?JDK >= 1.8
?MySQL >= 5.7
?Maven >= 3.0
前端技术栈 :
ES6、vue、vuex、vue-router、vue-cli、axios、element-ui
后端技术栈 :
Spring Boot、Spring Security、Jwt、MyBatis、MyBatis-Plus、
Quartz、Apache POI、Junit、Netty、Redis、MySQL、Maven、GIT
微服务方向:
Spring Cloud Gateway、Spring Cloud & Alibaba、Nacos、Sentinel、Seata、RocketMQ、OpenFeign、MinIO、Elasticsearch
参考开源框架:
前后端分离版本RuoYi-Vue,基于SpringBoot、Spring Security、Jwt、Vue的前后端分离的权限管理系统;下载地址:https://gitee.com/y_project/RuoYi-Vue
微服务版本RuoYi-Cloud,基于Spring Boot、Spring Cloud & Alibaba的微服务的前后端分离的权限管理系统。下载地址:https://gitee.com/y_project/RuoYi-Cloud
4.API接口规范
(1)协议
API与客户端用户的通信协议,使用HTTPS协议,以确保交互数据的传输安全。
(2)域名
应该尽量将API部署在专用域名之下:
https://api.example.com
(3)接口返回定义
返回JSON数据包,命名规范:驼峰命名法。数据标准返回code,data, msg这3个字段,如果有额外的字段可以自行添加,如time代表系统时间,对时间校验有帮助
{
code: 200 #接口响应状态码
data: {} #接口返回数据
msg: “操作成功” #返回给用户的提示
}
(4)接口返回原则
返回data
1、前端需要哪些字段,API接口应该返回哪些字段,字段不多也不少。
2、避免返回null,可返回[]或{},减少前端判断错误
返回msg
1、不能出现页面一堆报错飘红的情况(即使某个组件出错,也需要catch住,但是需要能报出来,比如通过debug或者返回中增加额外错误信息展示字段)
2、报错类型尽量详细,每种返回简明致意,不要返回看到了也不知道什么原因的信息
返回状态码
status 含义
200 成功的状态
400 参数列表错误(缺少,格式不匹配)
401 未授权或未登陆状态,给提示,用户点击确定按钮,跳转登陆页面
403 权限问题,api没有权限或登录授权过期
404 资源,服务未找到,跳转默认的首页
500 系统内部错误,错误信息不展示,提示“服务内部发生错误,请稍后再试!”
502 服务器暂时不可用异常,提示“系统繁忙,请稍后再试!”

七、数据库设计规范
1.命名规范
1)不得使用数据库保留关键字,以及php/java等常用语言的保留关键字,或者可能成为关键字的单词作为完整命名。(对于一些疑似关键字的单词,可以在后面加一个下划线来避免,例如“key_”)。【附:MySQL保留关键字列表:https://dev.mysql.com/doc/refman/5.7/en/keywords.html】
2)名称必须用英文字母开头,采用有特征含义的单词或缩写,单词中间用“”分割,且只能由英文字母、数字和下划线组成,不能用双引号包含。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。说明:MySQL 在 Windows 下不区分大小写,但在 Linux 下默认是区分大小写。因此,数据库名、表名、字段名,都不允许出现任何大写字母,避免节外生枝。
正例:aliyun_admin,rdc_config,level3_name
反例:AliyunAdmin,rdcConfig,level_3_name
3)表达是与否概念的字段,必须使用 is_xxx 的方式命名,数据类型是 unsigned tinyint(1 表示是,0 表示否)。
说明:任何字段如果为非负数,必须是 unsigned。
注意:POJO 类中的任何布尔类型的变量,都不要加 is 前缀,所以,需要在设置从 is_xxx 到
Xxx 的映射关系。数据库表示是与否的值,使用 tinyint 类型,坚持 is_xxx 的命名方式是为了明确其取值含义与取值范围。
正例:表达逻辑删除的字段名 is_deleted,1 表示删除,0 表示未删除。
4)数据库名,表名,字段名控制在30个字符以内,可添加项目名称简写前缀或模块名称简写前缀,用下划线连接,如:sys_user。
5)对于多个表关联的外键字段和冗余字段,命名规则是“关联表名(可不加前缀)“+"
"+关联字段名”,如:user_id,user_name。
6)表名不使用复数名词。
说明:表名应该仅仅表示表里面的实体内容,不应该表示实体数量,对应于 DO 类名也是单数形式,符合表达习惯。
7)主键索引名为 pk_ 字段名;唯一索引名为 uk 字段名 ; 普通索引名则为 idx 字段名。
说明:pk
即 primary key;uk
即 unique key;idx_ 即 index 的简称。
2.表设计规范
1)创建表必须添加表注释与字段注释,如果修改字段含义或对字段表示的状态追加时,需要及时更新字段注释。
2)数据库和表的字符集统一使用UTF8,避免由于字符集转换产生的乱码。
3)表必备三字段:id, create_time, update_time。
说明:其中 id 必为主键,类型为 bigint unsigned、单表时自增、步长为 1。create_time, update_time的类型均为 datetime 类型,前者现在时表示主动式创建,后者过去分词表示被动式更新。
4)小数类型为 decimal,禁止使用 float 和 double。
说明:在存储的时候,float 和 double 都存在精度损失的问题,很可能在比较值的时候,得到不正确的结果。如果存储的数据范围超过 decimal 的范围,建议将数据拆成整数和小数并分开存储。
5)如果存储的字符串长度几乎相等,使用 char 定长字符串类型。
6)varchar 是可变长字符串,不预先分配存储空间,长度不要超过 5000,如果存储长度
大于此值,定义字段类型为 text ,独立出来一张表,用主键来对应,避免影响其它字段索引效率。
7)字段允许适当冗余,以提高查询性能,但必须考虑数据一致。
冗余字段应遵循:
a.不是频繁修改的字段。
b.不是唯一索引的字段。
c.不是 varchar 超长字段,更不能是 text 字段。
正例:各业务线经常冗余存储商品名称。
3.索引规范
1)限制每张表上的索引数量,单张表索引不超过5个。
说明:索引并不是越多越好的,索引可以提高效率同样可以降低效率
索引可以增加查询效率,但同样也会降低插入和更新的效率
2)order by、distinct、group by后的字段尽量建立索引。
3)update、delete的where尽量使用有索引的字段或主键。
4)频繁更新的列不要建索引。
5)不建议在低基数列上创建索引,例如“性别”列。
6)大文本类型字段(例如text)不能使用索引。
7)业务上具有唯一特性的字段,即使是组合字段,也必须建成唯一索引。
说明:不要以为唯一索引影响了 insert 速度,这个速度损耗可以忽略,但提高查找速度是明显的;另外,即使在应用层做了非常完善的校验控制,只要没有唯一索引,根据墨菲定律,必然有脏数据产生。
8)超过20字节的varchar字段建议用前缀索引,禁止对字符串长度超过50个字符的列创建索引。
建立前缀索引的语法为:
ALTER TABLE table_name ADD INDEX index_name(column_name(prefix_length));
例:alter table sys_user add index idx_email(email(6));
4.SQL规范
1)sql语句关键字应全部使用小写。
2)引用字符时应使用单引号。如:update testable set idcol=’abcd’。
3)连接符或运算符or、in、and、=、<=、>=, +,- 等前后宜加上一个空格。否则容易导致以下类似问题。例如在语句select a–b from table中,a,b均为变量,拼写该语句时,如果a = 6,b = -3,则语句变为select 6–3 from table。–被视为SQL的注释,结果语句报错。
4)不得使用“select * from …”语法,必须标明字段名。即select col1, col2,… from table where …
5)严禁使用“insert into table_name values (?,?,……)”语法,统一使用“insert into table_name (col1,col2,……) values (?,?,……)”。
6)SQL语句包含多表连接时,必须加上表的别名,对每个字段的使用都要带上表别名。即 select a.col1, a.col2, b.col3 from tablea a, tableb b where a.col4=b.col5
7)应避免显式或隐含的类型转换。例如在where子句中numeric型和int型的列的比较。
8)在子查询中前后必须加上括号。select col1, col2 from tablea where col3 in ( select col4 from tableb where col4>0)
9)执行SQL时一次应只执行一条,如果多条语句则应分开执行,但必须保持在一个事务中。不得一次执行通过分号等分开的多条语句,这样处理不清晰。
10)如果能采用or代替,则不宜使用in 语句。in语句中的元素不得超过500个,如果超过,则应拆分为多条SQL语句。严禁使用xx in(‘’,’’….) or xx in(‘’,’’,’’)。
11)不要使用 count(列名)或 count(常量)来替代 count(),count()是 SQL92 定义的标准统计行数的语法,跟数据库无关,跟 NULL 和非 NULL 无关。
说明:count(*)会统计值为 NULL 的行,而 count(列名)不会统计此列为 NULL 值的行。
12)查询时应尽量减少多余数据的读取,通过使用where子句来减少返回的记录数。
13) 如果在语句中有not in(in)操作,应尽量用not exists(exists)来代替。特别对大数据量的两者检索速度有很明显的区别。
14) 一条SQL语句中不宜使用3层以上的嵌套查询。如果超过,则应在Java等应用服务器程序中处理。
15) 对索引列的比较,应尽量避免使用not 或 !=,可拆分为几个条件。因为“not”和“!=”不会使用索引。如col1 是索引列,条件col1 !=0 可以拆分为col1 >0 or col2 <0。
16) 应尽量将数据库函数、计算表达式写在逻辑操作符右边。因为这些对列的操作会将导致表扫描,影响性能。
17)在where子句中,如果有多个过滤条件,应将索引列或过滤记录数最多的条件放在前面。
18)join 与on 必须严格匹配,严禁出现没有on的join。
19)join…on 后面不宜使用or,如果使用则需将or的范围用( )括起来。
20)count(distinct col) 计算该列除 NULL 之外的不重复行数,注意 count(distinct col1,col2) 如果其中一列全为 NULL,那么即使另一列有不同的值,也返回为 0。
21)当某一列的值全是 NULL 时,count(col)的返回结果为 0,但 sum(col)的返回结果为NULL,因此使用 sum()时需注意 NPE 问题。
正例:可以使用如下方式来避免 sum 的 NPE 问题:SELECT IFNULL(SUM(column), 0) FROM table;
5.其他
1)临时库、表名必须以”tmp_日期”为后缀,如当日创建多个,则在日期后增加数字后缀。
2)备份库、表必须以”bak_日期”为后缀,如当日创建多个,则在日期后增加数字后缀。
3)禁止在数据库中存储明文密码。
4)一般情况下,不要使用外键约束,通过程序维护关系。
说明:使用外键会使删除和更新操作十分的麻烦,不方便维护与扩展,会增加数据库压力,高并发大流量事务场景,使用外键还可能容易造成死锁。

八、代码提交规范
我们使用的无论是git,还是svn都需要遵守下面这些规范,建议使用git。
(1)工作目录要及时更新,不要和服务器有太大的差别
(2)提交代码时,如果出现冲突,必须仔细分析解决,不可以强行提交
(3)提交代码之前先在本地进行测试,确保项目能编译通过,且能够正常运行,不可盲目提交
(4)必须保证服务器上的版本是正确的,项目有错误时,不要进行提交
(5)提交之前先更新
(6)提交时注意不要提交本地自动生成的文件,比如java项目中的?.idea,target文件夹是不需要提交的。
(7)不要提交自己不明白的代码
(8)提前协调好项目组成员的工作计划,减少冲突
(9)对提交的信息采用明晰的标注(写注释)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值