java项目编码规范
随手与数据库字段对应的实体以Po命名,DTO作为传输对象,封装PO及其关联对象的相关数据,用于服务间的数据传输。以xxxDTO命名
跨应用间RPC调用优先考虑使用Result方式,封装状态码,错误信息
@Repository(dao层)、@Service和@Controller相同但要用在合适的地方
需要事务的方法上面加上Spring的注解@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
禁止在类名上面使用事务注解,防止事务滥用,如果需要,请使用PROPAGATION_MANDATORY,参考上文。
事务不要滥用,会影响数据库的QPS,并且可能导致死锁,影响其他功能;
使用了事务的地方需要考虑回滚方案:缓存回滚、消息补偿、统计修正等;
有try 块放到了事务代码中,catch异常后,如果需要回滚事务,一定要手动回滚事务,或者继续抛出异常触发回滚;
服务间事务统一使用最终一致性
用户请求传入的任何参数必须做校验,包括如下校验:
page size是否过大导致内存溢出
恶意order by导致数据库慢查询
SQL注入
反序列化注入
正则输入源拒绝服务ReDoS
目前集中式缓存使用Redis,按照功能不同划分成了数据库缓存,jms消息缓存和业务缓存
日志文件进行分类输出
如果在任务里面需要遍历处理一个集合的数据,请确保处理每一个元素的时候都需要捕获异常,避免某一个元素数据异常导致后续元素无法继续处理,如:
for(Order order : orderList){
try{
processor(order);
} catch (Exception) {
logger.error(...);
}
}
服务监控(短信提醒,开发后台监控,后台手动修复)
dao命名(save插入、get/list、remove、update、count)
记录个数使用count(\*)要是count(列名)的话要是值得null的不会被算在内
使用IF(ISNULL(SUM(col)), 0 , SUM(col))来避免NPE问题
当col列的值全是NULL时,count(col)返回的结果是0,但SUM(col)返回的结果是NULL
使用ISNULL()来判断是否为NULL
NULL与任何值直接比较都为NULL
不使用外键,在应用层实现外键功能(影响插入速度)
级联更新操作也不行(监听)
禁止在insert语句中判断是否级联是否存在(where后面不应当加查询),速度会主键变慢,会增加死锁风险
避免使用in操作,用的话,in里面的选择不超过1000个
返回给前端的关联查询不要超过三个大表
禁止使用*作为查询的字段列表,必须明确写出
Po既要与数据库字段名字一一对应,又需要定义配置映射关系
使用#{},不使用${}后者容易导致sql注入
MyBatis自带的queryForList(String statementName, int start, int size)不推荐使用
这种方式其实是根据statementName查找到所有的记录,再通过subList进行截取的,容易出现OOM。
每个表都需要有对应的update_time,并及时更新改时间
尽量不要更新没有改动的字段,易错,效率低,浪费性能
字母‘l’作为长整形标准时务必大写
Arrays.asList产生的list不可更改,添加或删除元素,否则就会报错,所以它和不能喝其他list发生关系,它是只读的
少手写排序,jdk已经提供了很多种排序了,拿来用就好,即1. 实现comparable 2. 实现comparator
个类要实现Comparator接口:它一定要实现compare(T o1, T o2) 函数,但可以不实现 equals(Object obj) 函数。
int compare(T o1, T o2) 是“比较o1和o2的大小”。返回“负数”,意味着“o1比o2小”;返回“零”,意味着“o1等于o2”;返回“正数”,意味着“o1大于o2”。
comparator的使用:
Collections.sort(list, (o1, o2) -> {
return (o2.getLifeTime()-o2.getAge())-(o1.getLifeTime()-o1.getAge());
});
Arrays.sort(arr,(o1,o2)->o2.getAge()-o1.getAge());
@see 类名
@see 完整类名
@see 完整类名#方法名
在列表中部插入删除元素建议使用linkList
类里面添加方法添加到类最后面