Java程序猿搬砖笔记(七)
作为码农平时搜集一些小知识点个人认为是个不错的习惯,书上说
好记性不如烂笔头
我想即使是以前忽略或者新get的很简单的东西,自己动手记下来不管如何印象也会更深刻。
Java导入1W条数据耗时超过100秒
项目中导入一个含合并单元格的Excel,1W条数据耗时超过100秒。Excel模板如下:
数据库设计:
合并单元格部分(框红部分)存入主表,后面的部分存入详细表。
目前代码逻辑:
- 循环插入主表
- 然后把主表返回的主键封装到详细表的所需数据,批量插入详细表
问题原因:
导入1W条数据(如果全部未合并单元格)会循环插入主表数据库1W次,然后循环插入从表数据库1W次,效率及其低。
解决方法:
- 把数据库主键自增改为UUID,通过Java代码生成
UUID uuid = UUID.randomUUID(); - 封装主表数据批量插入、封装详细表数据批量插入
修改完成后1.1W条数据第一次12秒,之后大概6秒左右就可以插入完。
Java正则表达式的几种实现方式
- 方法一
1 | Pattern.matches(regex, str); |
- 方法二
1 | str.matches(regex); |
- 方法三
1 | Pattern p = Pattern.compile(regex); |
Matcher中的find()方法可以获取匹配的具体信息
1 | while(m.find()) { |
Linux查询进程杀进程命令
1 | # 查询进程 |
spring 注解@primary解析
@primary的作用是在多个类同时实现一个接口时,优先选择Bean注入。可以直接在类上使用:
1 |
|
可以在配置类的方法中使用,这种方法会被@Qualifier(value = “operaSinger”)注解覆盖:
1 |
|
@resource可以和@Qualifier有一样的作用
MySQL根据多字段查询出重复记录
1 | SELECT id FROM t_awards WHERE id IN ( |
MySQL取整的函数
1 | # 向上取整 |
MySQL 8.0忘记密码怎么办
MySQL 8.0官网解压版安装详细教程
exists和in的区别
- in引导的子查询只能返回一个字段,exists子查询可以有多个字段
- exists使用循环的方式,由outer表的记录数决定循环的次数,对于exists的影响最大,所以,外表的记录越小,子查询结果集较大时适用于exists
- in 先执行子查询,子查询的结果返回去重之后,再执行主查询,所以,子查询的返回结果越少,越适合使用in关键字。
MySQL用一个表更新另一个表
git回滚commit的近几次版本
- 方法一
回退最近几次提交
git reset --soft head~ - 方法二
git log、git reset --soft commitId
注意这里是回退commitId之后的操作,commitId不回退 - 方法三
git log
然后用IDEA操作
注意这里是回退commitId之后的操作,commitId不回退
MySQL根据年份和id排序后,取前后五条数据的SQL
思路:可以先通过连接工具观察,然后一步一步调试写出sql。例子中的2022和199作为参数传过来的前后五条sql如下所示:
前五条sql:
1 | SELECT id,project_code,project_name |
后五条sql:
1 | SELECT id,project_code,project_name |
MyBatis映射集合,参数传入多个
xml映射文件代码:
1 | <collection property="nextList" ofType="com.aspirecn.kjcgkmh.rms.vo.RecommendedReadingVo" |
其中,id、project_year、cgk_company_code是当前表的字段,id、projectYear、cgkCompanyCode作为SQL查询参数传入id为selectNextList的SQL。
1 | <!-- 后五条 --> |
Mapper.java代码:
1 | List<RecommendedReadingVo> selectNextList(Map<String,Object> map); |
注意,因为接收有多个参数,方法的参数应该为map类型(即使只有一个参数),否则会报错!
Springboot获取配置文件属性的几种方法
BeanMap不能进行put操作
1 | BeanMap map = BeanMap.create(req); |
SpringBoot配置集合(数组)
1 | // yml配置文件中 |
IDEA 搜索Jar包中的类和方法
Double Shift就行了
MySQL替换指定字段中的字符串
MySQL有replace函数
语法:
1 | replace (`field_name`,'from_str','to_str') |
示例:
1 | -- 把t_achievement表的company_name字段中的","的替换为"、" |
SpringBoot事务学习
1、确保在启动类中添加了@EnableTransactionManagement注解,在seivice中添加@Transactional 注解
Spring底层会设置数据库开启事务、不自动提交,所以加上上面两个注解就可以了。
2、事务回滚
Spring事务默认只在发生未被捕获的RuntimeExcetpion时才回滚。可以捕获到异常后抛出新的RuntimeExcetpion,推荐这种方法。
1 | // 插入失败后抛出自定义异常(继承RuntimeExcetpion),事务才能回滚 |
也可以捕获异常后添加
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();代码
手动回滚,这样上层就无需去处理异常,但是这样接口出错信息返回不到前端了。
service类中不加@Transactional注解,方法A调用方法B
1、注解加在方法A,方法B不加:
①方法A异常(抛出)
方法A中事务回滚,不走方法B
②方法B异常(抛出)
方法A,方法B事务都回滚
2、注解加在方法B,方法A不加:
①方法A异常(抛出)
方法A中事务不回滚,不走方法B
②方法B异常(抛出)
方法A事务不回滚,方法B回滚
service类中加@Transactional注解,相当于所有方法都加了注解
查看MySQL事务开启
Java替换最后一个字符
1 | /** |
例子:
1 | String str = "、1232、43424、、55、、"; |
Java替换第一个字符
用Java String自带的replaceFirst方法,第一个参数是正则表达式
例子:
1 | String str = "、1232、43424、、55、、"; |
MySQL查询Text字段会非常慢(IO慢),高并发下会特别明显。
列表查询尽量不要查这个字段。可以改为blob数据类型,得代码转换。
bootstrap.yml配置
- SpringBoot 项目中如果没有依赖spring-cloud-context的话不会读取到bootstrap.properties(yml)文件,bootstrap.yml配置是SpringCloud项目才会用到的。
1 | <!-- spring-cloud-context 加这个才能激活bootstrap.yml配置 注意springBoot的版本不能太高 否则项目起不来--> |
- bootstrap中的相同配置会被覆盖,bootstrap中的相同配置会被覆盖(亲自测试),所以application中不要配置bootstrap中已有的配置。
- applicaiton中的配置按优先级,以第一次读取的为准。即优先级从高到低,高优先级的配置覆盖低优先级的配置,所有配置会形成互补配置。
- 一般服务名和配置中心信息在bootstrp文件中指定。
BeanMap存在很多问题,最好用反射转换对象为Java原生Map
MySQL操作binlog相关命令
- 查询所有相关日志
SHOW MASTER logs; - 最新使用的日志
SHOW MASTER status; - 查询指定日志文件修改
SHOW BINLOG EVENTS IN ‘binlog.000014’; - 把指定时间开始的binlog导出为sql文件
mysqlbinlog --no-defaults --start-datetime=“2021-12-08 16:00:00” “D:\Program Files\mysql-8.0.27-winx64\Data\binlog.000014” > D:\export\test1.sql
IDEA有时候修改父项目pom.xml,子项目没有引用到父项目的jar包
解决方法:先看父项目中是否引用到,如果父项目有子项目没有,清理IDEA缓存重启一下(已经这样解决两次了)。
Linux查看端口占用情况
命令:lsof -i:端口号
例子:
查看服务器 8000 端口的占用情况:
1 | lsof -i:8000 |
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nodejs 26993 root 10u IPv4 37999514 0t0 TCP *:8000 (LISTEN)
可以看到 8000 端口已经被轻 nodejs 服务占用。
Java8中list转map如果Key重复的解决方法
若不处理会抛异常
java.lang.IllegalStateException: Duplicate key 11
解决方法:用第二个key覆盖第一个key。
示例代码如下:
1 | Map<String,String> roleKeyMap = allRoleList.stream() |
HttpClient的一些方法
1 | // 发送请求 |
MySQL模糊匹配表名拼接删表语句
1 | # drop不支持删表 |