月度记录-2024-8月

80 阅读11分钟

1. mysql我有一张表主键是bigint类型的,我用select * from table where id = '123456G',为何可以把id=123456的数据查出来?

在MySQL中,进行比较时,如果数据类型不匹配,MySQL会尝试进行隐式的类型转换。id字段是BIGINT类型,而你在查询条件中使用了字符串'123456G'MySQL会将'123456G'转换为数值类型,并且字符串转换为数字时,只会保留字符串开头的数字部分,忽略后面的非数字字符。

2. sudo是什么意思?

sudo 是 “superuser do” 的缩写,是一个用于在 Unix 和 Linux 系统中以超级用户(root)权限执行命令的工具。它允许普通用户以更高权限运行特定的命令,从而进行系统级别的操作或修改。

3. Swagger/knife4j文档空白

本次遇到的问题是有人的@ApiImplicitParam()是空的,@ApiImplicitParam()是用于描述方法参数的注解,不可为空。

4. mybatisplus BaseMapper>启动报错

mybatisplus会对实体类进行反射,获取信息,J8写个Map一反射一个不吱声

5. websocket

全双工通信协议,旨在通过一个单一的持久连接实现客户端和服务器之间的实时通信。它建立在 TCP 连接之上,与传统的 HTTP 请求-响应模型不同,WebSocket 允许服务器和客户端能够主动发送和接收消息。

实时双向通信、减少网络开销、低延迟。

6. 重复提交问题(前端点击多次提交按钮)

我更倾向于服务端生成唯一id这种方式解决重复提交问题。原因:

实现思路:

第一步,写个接口用于对进行请求id生成,生成一个随机id,放入Redis,设置过期时间。前端执行某些操作前,获取此id

第二步,前端请求后端,携带此id,后端接口可以注解+aop实现拦截,类似于Redis作为分布式锁。判断请求中是否携带请求id,请求id是否过期。通过校验,继续执行接口。通不过,则丢弃请求,或者抛出异常提示用户请求过期,需要重新发起请求。

第三步,对通过了的id从Redis进行删除

纯粹是我瞎想,可能根本没卵用。

7. jscson中@Jsonformat注解有什么作用?

在 Jackson 中,@JsonFormat 注解用于指定如何格式化序列化和反序列化 JSON 数据中的字段。它通常用于日期、时间、数字等类型,以便在 JSON 转换过程中应用特定的格式。

也就是说进去和出来都管用,以前一直以为只有进去管用,格局小了。

8. MyBatis-Plus IdentifierGenerator自定义ID

主键是Long或者是String,mp是如何选择使用nextId还是nextUUID的?

首先,要选择IDType,Long类型要选择ASSIGN_ID,String要选择ASSIGN_UUID,其实也可以不选,默认就是String类型的。还有就是,mp判断id是Long还是String,用的是getId方法,返回值是Long就是Long是String就是String,千万要注意,万不可自己转型再返回,例如:

private Long id;
public String getId {
    // 会被坑死!!!!!!!!!!!!
    return String.valueOf(id)
}
  • IdType.ASSIGN_ID:

  • 如果你在实体类中使用了@TableId(type = IdType.ASSIGN_ID),MyBatis-Plus 会根据主键字段的类型来决定调用 nextId 还是 nextUUID。

  • IdType.ASSIGN_UUID:

  • 如果你显式指定了 IdType.ASSIGN_UUID,即使主键字段类型为 Long 或 Integer,MyBatis-Plus 仍会调用 nextUUID 方法。

9. mybatis插入mysql数据,是完全插入了才返回吗?

是的,使用Lock Tables xxx write锁住表,执行插入方法,会发现插入方法一直在阻塞,使用UNLOCK TABLES解锁,就插入成功了,所以是等到插入成功才返回。起码不是提交到mysql就返回。

10. 关于@Transactional

加了这个注解就是为整个方法加上了事务,那么是执行完数据库操作就提交事务吗?

并不是,必须等到方法内最后一行代码执行完毕,即使剩余代码不操作数据库。应该是考虑到后续操作发生异常,也要回滚数据。

11. shorten command line

12. ES使用@Field注解设置分词器

// 使用ik_max_word分词器进行分词
@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
private String content;

13. mybatis-plus设置null值

mybatis-plus中,updateById方法,他默认会忽略null值。可是有些时候我们就是想设置null值。按照下面这么搞就ok了,update可以传wrapper进去,甚好!

LambdaUpdateWrapper<Entity> updateWrapper = Wrappers.lambdaUpdate();
updateWrapper.set(Entity::getStatus, null);
updateWrapper.eq(Entity::getId, id);
update(entity, updateWrapper);

14. spring中@Transactional,不指定rollbackfor会怎么样

  • RuntimeException 和 Error:默认情况下,Spring 事务管理器会对所有未捕获的 RuntimeException(包括其子类)和 Error(如 OutOfMemoryError)进行回滚。也就是说,如果方法内抛出了一个 RuntimeException 或 Error,事务会自动回滚。

  • Checked Exception:对于 Checked Exception(例如 IOException、SQLException 等),Spring 不会自动回滚事务。除非你手动捕获并重新抛出一个RuntimeException,否则事务仍然会被提交。

如果在 @Transactional 注解中设置 rollbackFor = Exception.class,那么 Spring 事务管理器会在遇到任何类型的异常时回滚事务,包括 Checked Exception 和 Unchecked Exception(即 RuntimeException)。

15. mysql的事务,隔离级别设置为读已提交。如果开启事务,插入一条数据,然后再此事务中查询插入的数据,可以查出来吗?

可以!!!事务内部的操作是相互可见的,读已提交的隔离级别是指一个事务只能看到其他已经提交的事务所做的更改,但这不影响同一事务内操作的可见性。

16. redis incr

INCR 是 Redis 中的一个命令,用于对存储在 Redis 数据库中的某个键的整数值进行递增操作。这个命令的基本用途是对一个键的整数值进行加一操作,并返回加操作后的新值。

  • 如果键不存在,INCR 命令会将其初始化为 0,然后递增。也就是说,第一次对一个不存在的键使用 INCR 时,它会将该键的值设为 1。

  • INCR 命令要求键的值必须是整数类型。如果键的值不是一个有效的整数,Redis 会返回一个错误。

  • INCR 是一个原子操作,即 Redis 在执行这个命令时会确保不会被其他操作打断。这使得 INCR 可以在高并发环境下安全地使用,确保每次递增操作都能正确地反映到数据库中。

  • 因为 INCR 是一个原子操作,Redis 内部使用了高效的机制来实现递增,通常可以处理非常高的操作频率。

17. mybatisplus-QueryWrapper 如何添加 limit 1

wrapper.last(“limit 1”);

18. QueryBuilders.matchQuery("description", "quick brown fox");

MatchQuery 是 Elasticsearch 中最常用的查询之一,特别适合进行全文搜索。它通过对输入的查询内容进行分词和分析,来匹配索引中的文档。这使得 MatchQuery 在处理自然语言查询时非常有效。

MatchQuery 的工作原理

  1. 分词与分析:

  2. 匹配过程:

MatchQuery 的类型

  1. Standard Match (默认)。默认情况下,MatchQuery 使用 "OR" 布尔逻辑。这意味着如果一个文档包含查询中的任何一个词条,它将被认为是匹配的。

QueryBuilders.matchQuery("content", "quick brown fox");这将返回包含 "quick"、"brown" 或 "fox" 的任何文档。

  1. Boolean Match。可以通过设置 operator 参数为 AND,要求文档必须包含查询字符串中的所有词条。

QueryBuilders.matchQuery("content", "quick brown fox").operator(Operator.AND);这将仅返回同时包含 "quick"、"brown" 和 "fox" 的文档。

MatchQuery 的选项

jaQueryBuilders.matchQuery("content", "quick brown fox").minimumShouldMatch("75%");这意味着在查询的三个词条中,至少要匹配两个(75%)。

QueryBuilders.matchQuery("content", "quikc brwn fx").fuzziness(Fuzziness.AUTO);支持模糊匹配,用于处理拼写错误或相似的词条。fuzziness 参数允许一定的编辑距离(即允许的字符替换、插入、删除次数)。这将会尝试匹配拼写错误的词条,如 "quick" 和 "brown"。

MatchQuery 的使用场景

  1. 全文搜索:MatchQuery 是处理自然语言文本的理想选择,比如在电子商务网站上搜索产品描述,或在社交媒体应用中搜索用户发布的内容。
  2. 多字段查询:结合 MultiMatchQuery 可以在多个字段上同时执行 MatchQuery,这对于搜索引擎的实现非常有用。

MatchQuery 的局限性

  • 精确性: 如果你需要精确匹配某个特定词语,MatchQuery 可能并不合适。这时 TermQuery 或 PhraseQuery 可能是更好的选择。
  • 性能: 尽管 MatchQuery 在文本搜索中非常强大,但如果查询的复杂性增加(例如高频使用 fuzziness 或复杂的布尔逻辑),查询性能可能会受到影响

19. Term Query

用例: 用于精确匹配单个词的字段值,也就是Keyword类型的数据。

优势: Term Query 是最能发挥倒排索引优势的查询之一,因为它能够直接定位到词条的文档。

示例:QueryBuilders.termQuery("status", "active");

20. wildcardQuery(通配符查询)

wildcardQuery 在 Elasticsearch 中用于执行通配符查询,它允许你查找符合特定模式的文档。这种查询方式特别适合以下几种情况:

// 这会匹配 username 字段以 "john" 开头的所有文档,如 "john", "johnny", "john_doe"。
QueryBuilders.wildcardQuery("username", "john*");// 这会匹配 filename 字段以 ".log" 结尾的所有文档,如 "error.log", "access.log"。
QueryBuilders.wildcardQuery("filename", "*.log");// 这会匹配 description 字段中包含 "error" 的所有文档,如 "critical error", "error occurred"。
QueryBuilders.wildcardQuery("description", "*error*");

wildcardQuery 的局限性

  • 性能影响:

  • wildcardQuery 可能导致全字段扫描,尤其是当查询字符串以通配符 * 开头时。这会显著降低查询性能,特别是在大数据集上。

  • 因为倒排索引是基于词条来组织的,而 wildcardQuery 需要对字段的所有词条进行匹配操作,复杂的通配符模式可能导致大量候选词条的匹配和扫描。

替代方案

21. mysql前缀索引

varchar建立索引,完整索引和前缀索引。

最好建立前缀索引,根据前缀先缩小范围,然后再全文匹配。可以把索引的开销降低,同时又可以用到索引,保证一个比较快的查询速度(xxx%)。

22. 使用ApplicationListener监听ContextRefreshedEvent实现创建ES多字段类型(multi-fields)

有时候需要ES中的字段同时具有keyword和text两种类型,可以通过监听器实现。通过反射获取到要创建的类,再通过反射获取到类中的字段,然后创建or更新索引。

fields 属性在 Elasticsearch 的映射(mapping)配置中用于定义多字段(multi-fields)。它允许你将一个字段索引为多种不同的数据类型,以便在不同的使用场景中对这个字段进行不同的处理。具体来说,fields 属性可以让一个字段在索引时不仅作为一种类型(例如 text),还可以同时作为另一种类型(例如 keyword)。这样你就可以在查询时根据需要选择使用哪种类型的索引数据。

ApplicationListener 是 Spring 框架中的一个接口,用于监听 Spring 应用上下文中发布的事件。它允许你在 Spring 应用中监听特定类型的事件,并在事件发生时执行相应的操作。

ContextRefreshedEvent 是 Spring 框架中的一个事件,它在应用上下文被初始化或刷新时触发。ContextRefreshedEvent 会在所有 Bean 被完全初始化后触发,因此你可以安全地在这个事件的监听器中访问所有 Bean。

23. ignore_above :256

ignore_above: 256 的意思是:如果字段的值超过 256 个字符,整个字段值将会被忽略,而不会被索引。然而,这个字段值仍然会完整地存储在文档中,只是不会被索引。具体来说:

  • 索引层面:超过 256 个字符的字段值将不会被索引,因此你不能基于这个字段值进行搜索、排序或聚合。wildcard query 或 term query查这个字段都查不出来!实测
  • 存储层面:字段的值仍然会被存储在 Elasticsearch 中,所以你依然可以在获取文档时看到完整的字段值。

24. springdata操作es,怎么可以在save的时候不创建没有的字段?

1. 使用 @Transient 注解,加了这个注解的字段就不会自动创建了。

2. 手动创建索引并禁用动态映射。dynamic: false (忽略,只是不索引,但还是会存进es)或 dynamic: strict(抛出错误,建议使用!!)。

3. 直接新建一个es专用实体。(可能是最正确的做法)