开发过程中常用的小技巧JAVA版(持续更新中)

1、数据量大时,分割查询列表,分批查询

List<List<String>> partition = Lists.partition(venderCodeList, 1_000);
for (List<String> perList : partition) {
    //查询操作...
}

2、 FIND_IN_SET函数:单个字段中存储列表数据,以逗号分隔,需要匹配其中某些元素时

//示例:province_codes存储S002,S008,S009,S011
select * from commodity_pool_apply_order where FIND_IN_SET('S002',province_codes);

3、Mybatis批量插入

 <insert id="batchInsert" parameterType="java.util.List">
    insert into t_user(user_name, age, sex, telno, email, address)
    values
    <foreach collection="userList" item="item" separator=",">
        (#{item.userName}, #{item.age}, #{item.sex}, #{item.telno}, #{item.email},
        #{item.address})
    </foreach>
  </insert>

4、Mybatis查询条件是where (a='xxx' and b='yyy') or (a='xxx1' and b='yyy1')

  <select id="selectByList" resultMap="BaseResultMap">
    select  <include refid="Base_Column_List" />
    from t_user
    where
    <foreach collection="list" item="item" separator="or">
       (product_code = #{item.productCode} and shop_code = #{item.shopCode})
    </foreach>
  </select>

5、Mybatis查询条件是 code in (...)

<if test="shipQueryVO.locationCodes != null and shipQueryVO.locationCodes.size>0">
    and shop_code in
	<foreach collection="shipQueryVO.locationCodes" separator="," open="(" close=")" item="item">
        #{item}
    </foreach>
</if>

6、Mybatis查询条件有特殊字符,把有特殊字符的语句放在 <![CDATA[ ]]>中,尽量缩小 <![CDATA[ ]]> 的范围

<if test="shipQueryVO.createdTimeStart != null">
    <![CDATA[
        and created_time >= #{shipQueryVO.createdTimeStart,jdbcType=TIMESTAMP}
    ]]>
</if>

7、Mybatis insert返回自增主键并设置到实体对象中

<insert id="insertSelective" parameterType="com.xxx.dao.entity.BaseBrandVO" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
    insert into base_brand values(.....)
</insert>

8、jsqlparser解析sql提取表名

<dependency>
    <groupId>com.github.jsqlparser</groupId>
    <artifactId>jsqlparser</artifactId>
    <version>4.2</version>
</dependency>
private static Set<String> getTableNames(String sql) {
    Statement statement = null;
    try {
        statement = CCJSqlParserUtil.parse(sql);
    } catch (JSQLParserException e) {
        throw new ProductCenterQueryException("解析sql语句错误!sql:" + sql);
    }
    TablesNamesFinder tablesNamesFinder = new TablesNamesFinder();
    List<String> tableList = tablesNamesFinder.getTableList(statement);
    Set<String> tableNames = new HashSet<>();
    for (String tableName : tableList) {
        //获取去掉“`”的表名
        if (tableName.startsWith("`") && tableName.endsWith("`")) {
            tableNames.add(tableName.substring(1, tableName.length() - 1));
        } else {
            tableNames.add(tableName);
        }
    }

    return tableNames;
}

9、MQ消息幂等处理(redis实现方式)

//MqMessageCacheDataUtil类中定义幂等判断逻辑
public static Boolean putMqMessage(String formInstanceId,String messageId){
    if(StringUtils.isBlank(formInstanceId) || StringUtils.isBlank(messageId)){
        return true;
    }
    String key = getKey(formInstanceId);
    if(redisUtils.hashKey(key,messageId)){
        return false;
    }
    redisUtils.hashPut(key,messageId,"");
    redisUtils.expire(key,EXPIRETIME, TimeUnit.SECONDS);
    return true;
}

//幂等校验
if(!MqMessageCacheDataUtil.putMqMessage(vo.getFormInstanceId(),vo.getUuId())){
    log.info("重复消息,消息已消费:"+vo.getFormInstanceId()+":"+JSON.toJSONString(vo));
    return;
}
//通过幂等校验,执行后续业务逻辑
.....

10、lombok使用

//开启链式编程
@Accessors(chain = true)

//创建一个无参构造函数
@NoArgsConstructor

//创建一个含有所有已声明字段属性参数的构造函数
@AllArgsConstructor

//生成toString()方法的实现,将callSuper设置为true,可以将toString的父类实现的输出包含到输出中
@ToString(callSuper = true)
//用于属性,结合类上标注@ToString使用
@ToString.Include(name =“some other name”)
@ToString.Exclude

//生成equals(Object other) 和 hashCode()方法
//默认不考虑父类,通过设置callSuper = true解决;
//默认使用类的所有非static、非transient字段,通过@EqualsAndHashCode.Exclude排除部分字段解决;
@EqualsAndHashCode(callSuper = true)
//用于属性,结合类上标注@EqualsAndHashCode使用
@EqualsAndHashCode.Exclude
@EqualsAndHashCode.Include

11、git使用进阶

# git无痕回退版本

# 1、未提交   已执行git add提交到暂存区,未执行git commit提交到本地仓库
git reset --hard    #清空暂存区

# 2、已提交未推送   已执行git commit提交到本地仓库,但未执行git push推送到远程仓库
#git reset 参数[不带参数时保存回退文件内容修改,--hard 不保留回退文件内容修改] [回退commit_id或HEAD^或HEAD~N或远程分支origin/master]
git reset HEAD^    #上一个版本回退(保存回退文件内容修改)
git reset HEAD~N    #N个版本回退(保存回退文件内容修改)
git reset <commit_id>    #指定版本回退(保存回退文件内容修改)
git reset origin/master    #回退到远程最新版本(保存回退文件内容修改)

# 3、已推送    已执行git commit提交到本地仓库,还执行了git push推送到远程仓库
git reset --hard HEAD~N    #先本地回退到具体版本
git push -f    #再执行强制推送到远程仓库
# git 配置相关
git config --list    #查看git配置(常用于查看用户名/邮箱)
git config --global --list      #查看git全局配置
git config --local --list      #查看git当前仓库配置
git config --global user.name "your_name"       #设置用户名(全局配置)
git config --global user.email "your_email"    #设置邮箱(全局配置)
git config --local user.name "your_name"       #设置用户名(当前仓库)
git config --local user.email "your_email"    #设置邮箱(当前仓库)
# git cherry-pick相关使用

# 使用引用日志记录找回因git reset --head <commit_id> ,git push origin master -f,git branch -D <branch_name>丢失的修改内容
git reflog    #查看引用日志记录

#根据reflog的列表找到对应的commit_id,再使用cherry-pick恢复对应的内容
git cherry-pick <commit_id>

# 场景:需要把某个分支的某次提交应用到其他分支上去,通过git log查到commitHash,再在需要应用的分支上执行cherry-pick
git cherry-pick <commitHash>

git cherry-pick commit1 commit2    #cherry-pick多次提交
git cherry-pick commit1^..commit2    #cherry-pick连续的几次提交

#cherry-pick遇到冲突时会中断,已cherry-pick的提交会应用到分支上,解决冲突后可继续cherry-pick
git cherry-pick --continue

#cherry-pick遇到冲突时,放弃cherry-pick
git cherry-pick --abort    #放弃cherry-pick,退回到cherry-pick前的状态
git cherry-pick --quit    #放弃cherry-pick,保留已经cherry-pick的改动
# 暂存当前分支改动的代码,防止切换分支时将当前分支的改动带到其他分支
git stash save "备注内容"   #暂存当前分支代码修改内容但不提交
git stash list    #查看暂存的列表
git stash pop    #提取上一次暂存的代码(stash list也会减少)
git stash drop stash@{n}    #删除指定暂存记录
git stash apply stash@{n}    #根据暂存编号提取暂存的代码(stash list不会减少)
git stash clear    #清除暂存列表
#git revert使用:回退部分历史提交,适用于需要被回退的提交后还有其他提交,此时不能用reset并push -f
#找到需要回退的提交的commitHash
git revert <commitHash>    #回退指定历史提交,保留了第一次提交和此次revert的log记录
# git tag相关使用
git tag    #查看本地tag列表
git tag V1.0.0    #基于当前代码打一个tag
git push origin V1.0.0    #将tag V1.0.0推送到远程仓库

#修复某tag上的bug并合并到master
git checkout -b bugfix-V1.0.0 V1.0.0    #修复V1.0.0tag上的bug,基于tag创建新分支进行修复
git tag V1.0.1    #修复完V1.0.0的bug后打新tag,一般是先基于修复bug的分支打tag,版本号升级;然后将本分支代码合并到master
git checkout master    #切换到master分支
git merge bugfix-V1.0.0    #合并tagbug修复分支到master

git ls-remote --tags origin    #列出远程tag列表
git tag -d <tag标签>    #删除本地tag
git pull    #拉取代码(包括远程tag)

git push origin --delete tag V1.0.0    #删除远程的tag

#查看代码库地址
git remote -v

#修改代码库地址
git remote set-url origin git@gitlab.tuhuyun.cn:shakaijian/pms-bi-server.git

#增加upstream远程库地址
git remote add upstream git@gitlab.tuhuyun.cn:TUHU.YEWU/PURCHASE/pms-bi-server.git

12、Mysql深分页问题

表结构

CREATE TABLE account (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '主键Id',
  name varchar(255) DEFAULT NULL COMMENT '账户名',
  balance int(11) DEFAULT NULL COMMENT '余额',
  create_time datetime NOT NULL COMMENT '创建时间',
  update_time datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (id),
  KEY idx_name (name),
  KEY idx_update_time (update_time)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 ROW_FORMAT=REDUNDANT COMMENT='账户表';

深分页现象: limit 100000,10时耗时明显增加

select id,name,balance from account where update_time> '2020-09-19' limit 0,10;    -- 0.003s
select id,name,balance from account where update_time> '2020-09-19' limit 100000,10;    -- 1.969s

分析:

通过普通二级索引树idx_update_time,过滤update_time条件,找到满足条件的记录ID。
通过ID,回到主键索引树,找到满足记录的行,然后取出展示的列(回表)
扫描满足条件的100010行,然后扔掉前100000行,返回。

优化方式一:通过子查询优化(通过二级索引拿到分页的起始id,回表10次)

select id,name,balance FROM account where id >= (select a.id from account a where a.update_time >= '2020-09-19' limit 100000, 1) LIMIT 10;  -- 0.038s

优化方式二:INNER JOIN 延迟关联

SELECT  acct1.id,acct1.name,acct1.balance FROM account acct1 INNER JOIN (SELECT a.id FROM account a WHERE a.update_time >= '2020-09-19' ORDER BY a.update_time LIMIT 100000, 10) AS  acct2 on acct1.id= acct2.id;    -- 0.034s

优化方式三:标签记录法(类似于方法一,只不过此处的id是有查询发起者传入)

select  id,name,balance FROM account where id > 100000 order by id limit 10;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值