JSONobject
readTree ObjectMapper //不建议用, 因为我 JSONNode.get数据时,有的结果带双引号,有的不带,一摸一样的数据就比如说get() 后有的得到的是“test”,有的得到是test,不知道是工具原因还是啥原因
JSON.parseObject //建议hutool的这个
定时运行某个方法
一般用于数据库更新,然后让后端数据重新读取
Timer timer =new Timer();
timer.shedule(new TImerTask(){ run(需要重复运行的方法)},(delay)5000,(period)5000)
JSON 变成键值对类型
set<Map.Entry<String,Object>> entry=jsonData.entrySet()
获取JSON中的所有key或者value
jsonData.keySet() jsonData.values
用逗号隔开列表中的数据
第一种
StringUtils.join(Set{1,2,2},“,”);
引入依赖
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
第二种
list 去重
List collect = list.stream().distinct().collect(Collectors.toList());
user.setTags(Joiner.on(“,”).join(collect));
引入依赖
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>27.0.1-jre</version>
</dependency>
把json对象转化为指定对象
OrderInfo orderInfo = JSON.parseObject(string, OrderInfo.class);
给某个对象的特定值赋值,而不用set
BeanUtils.setProperty(rowData,metaData.getColumnName(i),rs.getObject(i));
rowData : T rowData = clazz.newInstance();
meteData.getColumnName()要赋值的属性值
rs.getObject(i) 表示要赋值的值
让对象中的某个数值不序列化
加上@JSONIgnore
得到linux文件的行数
:set nu
jps看进程详情
jps -ml
flink向clinkhouse插入时间数据
entity里写String类型直接插
生成随机id
https://www.hutool.cn/docs/#/core/%E5%B7%A5%E5%85%B7%E7%B1%BB/%E5%94%AF%E4%B8%80ID%E5%B7%A5%E5%85%B7-IdUtil
hutool工具中有随机生成id
association 是mybaties 当两个表join时
驼峰命名转下划线
hutool
生成永不相同的主键
hutool
当实体对象属性特别多时,把object转换成hashmap
package com.hnradio.utils;
import cn.hutool.core.util.StrUtil;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
/**
* @author zhz
* @date 2021/10/9
*/
public class ObjectToMap {
public static HashMap<String, Object> convertToMap(Object obj) throws Exception {
HashMap<String, Object> map = new HashMap<String, Object>();
HashMap<String, Object> b = new HashMap<String, Object>();
Field[] fields = obj.getClass().getDeclaredFields();
for (int i = 0, len = fields.length; i < len; i++) {
String varName = fields[i].getName();
boolean accessFlag = fields[i].isAccessible();
//必须加isAccessible 否则的话,当object中有属性是private时,运行报错
fields[i].setAccessible(true);
Object o = fields[i].get(obj);
if (o != null) {
map.put(varName, o.toString());
fields[i].setAccessible(accessFlag);
}
}
map.forEach((k,v) -> b.put(StrUtil.toUnderlineCase(k), v));
return b;
}
}
Mybatis 时间bug
不能写 =“” 否则报错
接受数据库的类时间也要用date(java.util) 别用localdatetime,否则解析错误
配置多数据源错误(一定要记住)
1配置不同数据库,如果,账户密码一样,只用写一个datasource
例如这个抖音快手B站 三个不同的数据库,但是账号密码一样,jdbc-url随便写一个就行,在mapper.xml写数据库也行
2如果是不同的账号密码 不仅要配置两个datasource,还要写两个@mapper ,我因为我两个数据库都是mysql,我把他写进一个mapper中,但读取第二个数据库时,总是用第一个账户密码,然后我浪费了3个小时解决这个问题
mybatis动态传入表名错误
delete from 表明,并不能使用#{} 要使用${} #{}传进来的是预编译的 ${}传进来就直接是个字符串
mybatis 传输数值为o问题
and T.status=#{work_status,jdbcType=INTEGER}
当work_status为0时,Mybatis会将0解析为了空字符串‘’,这样if判断就为false,如果想正确添加and后的查询条件,应该改成
and T.status=#{work_status,jdbcType=INTEGER}
参数校验
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<scope>provided</scope>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<scope>provided</scope>
<version>6.0.16.Final</version>
</dependency>
@Null 被注解的元素必须为null
@NotNull 被注解的元素必须不为null
@AssertTrue 被注解的元素必须为true
@AssertFalse 被注解的元素必须为false
@Min(value) 被注解的元素必须为数字,其值必须大于等于最小值
@Max(value) 被注解的元素必须为数字,其值必须小于等于最小值
@Size(max,min) 被注解的元素的大小必须在指定范围内
@Past 被注解的元素必须为过去的一个时间
@Future 被注解的元素必须为未来的一个时间
@Pattern 被注解的元素必须符合指定的正则表达式
在方法入参中添加
@NotNull(message = “公共入参不能为空”) CommonParam commonParam调用方法时即可验证
或者利用
@Valid
private CarrierInfoDTO carrierInfoDTO;
@Length(
max = 200,
message = “年龄不能超过200”
)
@Range(
min = 2L,
max = 4L,
message = “改址类型不合要求”
)
@NotNull(
message = “号码为空”
)
@Within(
values = {0L, 2L, 3L, 4L, 7L, 9L, 10L, 11L, 12L},
message = “类型(signType)不合法”
)
//@Validated 这个注解就是如果传入的参数不符合条件就会报message中的错误
@PostMapping("/save")
public Object testUser(@Validated @RequestBody User user) {
return user.toString();
}
mysql合适建造分表
单表行数超过 500 万行或者单表容量超过 2GB
这个具体还要根据内存吧,内存要有存储所有表的所有索引
flink或者spark 存入数据到redis等 可以用hahir
官网 http://bahir.apache.org/
时间转换LocalDateTime、LocalDate、Long、Date、String 相互转换
LocalDateTime、LocalDate、Long、Date、String 相互转换
DateTimeFormatter dateTimeFormatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
DateTimeFormatter dateTimeFormatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDateTime localDateTime = LocalDateTime.parse("2019-07-31 00:00:00",dateTimeFormatter1);
LocalDate localDate = LocalDate.parse("2019-07-31",dateTimeFormatter2);
Date date = Date.from(LocalDateTime.parse("2019-07-31 00:00:00",dateTimeFormatter1).atZone(ZoneId.systemDefault()).toInstant());
String strDateTime = "2019-07-31 00:00:00";
String strDate = "2019-07-31";
Long timestamp=1564502400000l;
/** LocalDateTime 转 LocalDate */
System.out.println("LocalDateTime 转 LocalDate: "+localDateTime.toLocalDate());
/** LocalDateTime 转 Long */
System.out.println("LocalDateTime 转 Long: "+localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
/** LocalDateTime 转 Date */
System.out.println("LocalDateTime 转 Date: "+Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()));
/** LocalDateTime 转 String */
System.out.println("LocalDateTime 转 String: "+localDateTime.format(dateTimeFormatter1));
System.out.println("-------------------------------");
/** LocalDate 转 LocalDateTime */
System.out.println("LocalDate 转 LocalDateTime: "+LocalDateTime.of(localDate,LocalTime.parse("00:00:00")));
/** LocalDate 转 Long */
System.out.println("LocalDate 转 Long: "+localDate.atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli());
/** LocalDate 转 Date */
System.out.println("LocalDate 转 Date: "+Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()));
/** LocalDate 转 String */
System.out.println("LocalDateTime 转 String: "+localDateTime.format(dateTimeFormatter2));
System.out.println("-------------------------------");
/** Date 转 LocalDateTime */
System.out.println("Date 转 LocalDateTime: "+LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()));
/** Date 转 Long */
System.out.println("Date 转 Long: "+date.getTime());
/** Date 转 LocalDate */
System.out.println("Date 转 LocalDateTime: "+LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()).toLocalDate());
/** Date 转 String */
SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS" );
System.out.println("Date 转 String: "+sdf.format(date));
System.out.println("-------------------------------");
/** String 转 LocalDateTime */
System.out.println("String 转 LocalDateTime: "+LocalDateTime.parse(strDateTime,dateTimeFormatter1));
/** String 转 LocalDate */
System.out.println("String 转 LocalDate: "+LocalDateTime.parse(strDateTime,dateTimeFormatter1).toLocalDate());
System.out.println("String 转 LocalDate: "+LocalDate.parse(strDate,dateTimeFormatter2));
/** String 转 Date */
System.out.println("String 转 Date: "+Date.from(LocalDateTime.parse(strDateTime,dateTimeFormatter1).atZone(ZoneId.systemDefault()).toInstant()));
System.out.println("-------------------------------");
/** Long 转 LocalDateTime */
System.out.println("Long 转 LocalDateTime:"+LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault()));
/** Long 转 LocalDate */
System.out.println("Long 转 LocalDate:"+LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault()).toLocalDate());
日期比较
LocalDateTime now = LocalDateTime.now();//2020-09-11T09:41:01.547
LocalDateTime DiscountStartTime = now.minusDays(3);//减法 2020-09-08T09:41:01.547
LocalDateTime DiscountEndTime = now.plusDays(3);//加法 2020-09-14T09:41:01.547
// now>DiscountStartTime && DiscountEndTime>now
// DiscountEndTime>now>DiscountStartTime
if(now.isAfter(DiscountStartTime) && DiscountEndTime.isAfter(now)){
true;//输出true
}
向数据库插入date 或者dateTime 时,如果用mybatis的话,String 都能插
但是如果要用jdbc 的话 date 对应的就是date dateTime对应的就是Timestamp
第三种是错误的,不能强转
mysql数据库插入时存在就更新,不存在就插入on DUPLICATE key
insert into test_duplication(ID,name,idcard) VALUES (1,‘1’,‘1’) on DUPLICATE key update id=2,NAME=‘2’,idcard=‘2’;
clickhouse分布式表 分表索引只能用Replicated?
我用clickhouse同步mysql的数据,因为大概800多万条数据,且更改比较多,我用了以下两种方法。
1 使用mysql表引擎 失败,查不到数据,因为我想要join redis中的数据,所以也没仔细研究
2 binlog通过kafka存入clickhouse使用CollapsingMergeTree 引擎,但是带我那个哥说 分布式表只能用Replicated 引擎,但是官网上并没有说,所以我头铁就用,果然可以,但是当我cout()的时候,每次结果都不同,查了问题 https://cloud.tencent.com/developer/article/1748216 就是说如果副本数大于2,count()的数量有可能计算多个副本的数量,所以建议用Replicated。那么我用ReplicatedCollapsingMergeTree ,但是不同机器上的分区能合并吗
Phoenix配置多数据源
phoenix:
article:
driverClassName: org.apache.phoenix.jdbc.PhoenixDriver
jdbc-url: jdbc:phoenix:10.1.100.39:2181
username: li
password: li
导入依赖是最恶心的,又是依赖冲突又是啥的,多亏我有一个超级好的学长。
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>29.0-jre</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>3.2.1</version>
<exclusions>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.phoenix</groupId>
<artifactId>phoenix-core</artifactId>
<version>5.0.0-HBase-2.0</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
<exclusion>
<artifactId>javax.el</artifactId>
<groupId>org.glassfish</groupId>
</exclusion>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>2.5.0</version>
</dependency>
这个报冲突的错是因为没有引入 hadoop common
mybaties property报红
像这个一般是没get set方法,但是我明明用@Data注解了啊,为啥还是错呢
我仔细看了下源码,get set并没有注入进去,然后我把@Accessors删除了,把Data放在仅靠类的上面,就可以了。这两个注释有矛盾吧,反正我只要同时用两个就报错,无语了。
关于mysql插入数据报错
emoji 错误,插入的String中有表情。
create table third_platforms_video
(
id int auto_increment
primary key,
platform varchar(32) null comment '属于哪个平台',
open_id varchar(255) null comment '授权用户唯一标识',
nickname varchar(255) null comment '账户名字',
createTime date null comment '视频创建时间',
item_id varchar(255) null comment '视频ID',
title varchar(255) null comment '视频名称',
digg_count bigint null comment '点赞量',
comment_count bigint null comment '评论量',
share_count bigint null comment '分享量',
forward_count bigint null comment '转发量',
play_count bigint null comment '视频播放量',
coin_count bigint null comment '投币量',
collect_count bigint null comment '收藏量',
update_at datetime null comment '新媒体矩阵平台中的更新时间',
create_at datetime null comment '新媒体矩阵平台中的创建时间'
)
engine = InnoDB
charset = utf8mb4;
修改编码格式就可以了。utf8mb4
用group by 分组,没有分组的字段随便取一条记录
例如:
id trueName userName score
1 张三 zs 80
2 张三 zs1 100
3 张三 zs2 90
想要获得张三的总分(userName 随便去一个值即可):
张三 zs 270 或 张三 zs1 270 或 张三 zs1 270
我在整理埋点数据的时候遇到了这个问题,可以用max 或者min
select name,max(第二列),sum(分数) group by name
dataGrip时差问题
我的dataGrip时差问题没配好,差8小时,然后我在查询的时候发现了一个奇怪的问题,既然时差没配好,差8个小时,那么只查年月的话月份结果是没差的。
yml注入问题
@postStruct() 这个注解就是构造方法完成后,执行这个命令。
mybaties批量插入问题
等于说如果list大于6000条的话,那就2000条一拆分,2000条插入一次
SqlServer 对语句的条数和参数的数量都有限制,分别是 1000 和 2100。
Mysql 对语句的长度有限制,默认是 4M。
Mybatis 对动态语句没有数量上的限制。
//拆分list代码
package com.hnradio.bdthirdplatform.utils;
import java.util.ArrayList;
import java.util.List;
/**
* @author zhz
* @date 2021/11/29
*/
public class SplitList {
/**允许使用的最大记录数量*/
private static final int SELECT_MAX_COUNT = 1000;
/**
* 按照count拆分成多个list
* @param lists 需要拆分的数据
* @param num 以num为拆分数据
* @return
*/
public static <T> List<List<T>> splitList(List<T> lists, Integer num) {
int maxCount;
if (num == null || num == 0) {
maxCount = SELECT_MAX_COUNT;
} else {
maxCount = num.intValue();
}
List<List<T>> result = new ArrayList<>();
if (lists != null) {
//记录数量
int length = lists.size();
int time = length / num;
//计算拆分几条
time = length % num > 0 ? time + 1 : time;
int end;
List<T> tmpList;
for (int i = 1, start = 0; i <= time; i++) {
if (i == time) {
end = length;
} else {
end = i * maxCount;
}
tmpList = lists.subList(start, end);
start = end;
result.add(tmpList);
}
}
return result;
}
/**
* 按照count拆分成多个list
* 默认拆分记录条数 1000
* @param lists 需要拆分的数据
* @return 返回拆分后 数据集合用于使用
*/
public static <T> List<List<T>> splitList(List<T> lists){
return splitList(lists,SELECT_MAX_COUNT);
}
}
直接用下面这个一步到位
List<List> partition = Lists.partition(res, 1000);
创建一个List,但里边只有一个值
浮点数比较大小
建立索引的经验
如果表格中大量增删改,最好别用索引(为啥因为B+树)
复合索引(where后 and 左右两边两个关联比较大的时候.如果建的是两个单一索引,则只会用一个,因为用的是一个B+tree呀!)
单一索引(where后 or )
日期取代SimpleDateFormat
String 拼接节省空间
SQL函数
date_add(date,interval 1 day)
month(date)
date_sub(date,interval 1 day)
TIMESTAMPDIFF(second, start_time, end_time)计算出时间差。
round(,1)保存几位小数。即保存一位小数
Row_Number() 用法,以deptid为分区,根据ORDER BY进行分区,SELECT *, Row_Number() OVER (partition by deptid ORDER BY salary desc) rank FROM employee
rank() over(partition by id order by dt) rankover和row_number的区别是rankover排序后相同的排名相等,row_number就是按照序列排。
当要面对group by 内,条件是每个数值的最大值时,但又不求这个最大值,可以使用拼接的方法,然后Max(String)。可以这样求这种思想。
windows下删除vue的node_modules
安装rimraf
npm install -g rimraf
node_modules的父级目录,执行
rimraf node_modules
Java中List 数组 Set相互转换
new ArrayList(set) 注意list或者set必须是封装类(比如就不能是int 而必须用inteager,如果用int的话,那set会把整个int当成一个set[0]的位置)
new HashSet(list)
list.toArray
set.toArray
Arrays.asList()
数组转换set必须先转list,再转换为set
hive的group by报错
hive本身有bug
在 select from (select 1 from a join b) 别名 group by
注意必须要有别名,否则hive报错
join时候注意点问题
A表中join的字段类型是double
B表中join的字段类型String
当进行on的时候隐式转换会把stirng类型有可能转为null.