千家信息网

spring-data-elasticsearch和Jackson配合使用有什么bug

发表于:2025-02-05 作者:千家信息网编辑
千家信息网最后更新 2025年02月05日,本篇内容介绍了"spring-data-elasticsearch和Jackson配合使用有什么bug"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何
千家信息网最后更新 2025年02月05日spring-data-elasticsearch和Jackson配合使用有什么bug

本篇内容介绍了"spring-data-elasticsearch和Jackson配合使用有什么bug"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

下面先简单描述项目。

项目依赖:

dependencies {  implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-elasticsearch', version: '2.1.0.RELEASE'  testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: '2.1.0.RELEASE'  testCompile group: 'junit', name: 'junit', version: '4.12'}

ES索引结构:

{        "test_log": {                "mappings": {                        "_doc": {                                "properties": {                                        "id": {                                                "type": "keyword"                                        },                                        "log_type": {                                                "type": "keyword"                                        }                                }                        }                }        }}

注意如果不加 @JsonProperty 注解,保存时会向 ES 添加新的 'logType' 字段(视 mapping 的 dynamic 配置而定,默认是true)。POJO如下:

@Document(indexName="test_log", type="_doc")public class TestLog {  @Id  private long id;  @JsonProperty("log_type")  private String logType; // setters & getters}

TestLogRepository:

import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;import org.springframework.stereotype.Repository;@Repositorypublic interface TestLogRepository extends ElasticsearchRepository {}

测试用例很简单:

@Testpublic void testSave() {  testLogRepository.save(new TestLog(System.currentTimeMillis(), "test name 1"));}

测试结果是虽然向ES添加了一条新的记录,但 log_type 字段为空。

郁闷了一会后开始跟踪源码。先将整个过程分为初始化、序列化、写入三个阶段。写入肯定没有问题,因为是 ES client 直接向ES写生成好的JSON,那么问题就出在前边。

先来看初始化过程,其关键调用链描述如下:

1. spring 扫描自定义的 Repository;

2. 使用 ElasticsearchRepositoryFactoryBean 来初始化 TestLogReposity 的实例;

3. 在 AbstractMappingContext 的 addPersistentEntity 方法中将类型信息(TestLog)添加到 MappingContext( AbstractMappingContext )的 persistentEntities 的私有属性中(HashMap结构,里边的变量是 SimpleElasticsearchPersistentEntity 实例)。

4. 第3步中会在写 persistentEntities 时遍历 TestLog 所有 properties,将字段名保存到 PersitentEntity 的 propertyCache(ArrayList)中。我们需要关注的结构就是 context-> persistentEntities -> propertyCache, 这个 propertyCache 先简单表示为 ['id', 'logType']

JSON序列化过程中关键调用链如下:

1. 调用 DefaultEntityMapper 的 mapToString;

2. 调用 ObjectMapper 的 writeValueAsString;

3. 调用 DefaultSerializerProvider 的 serializeValue;

4. 序列化 TestLog 时, Jackson发现从各种缓存中都找不到序列化器,只好构造一个,即调用 BeanSerializerFactory 的 createSerializer;

5. createSerializer 时会扫描 TestLog 中各式注解,如 @JsonProperty、@JsonSetter、@JsonGetter 以及 @JsonNaming,使用注解的值来构造要序列化的属性列表。如果没有注解,就直接使用字段名。本例中的 props 列表形为 ['id', 'log_type']

6. 到第5步还一切OK,但是最后 Jackson 会回调 SpringDataSerializerModifier 对 props 进行修改,SpringDataSerializerModifier 直接从上面我们初始化好的 context-> persistentEntities -> propertyCache 一路查下来,发现 log_type 匹配不到 propertyCache 列表中的任何值,直接删掉。。。返回待序列化的字段列表只包含 [ 'id' ] 一个值!关键代码就在 BeanSerializerFactory 的 constructBeanSerializer,和 SpringDataSerializerModifier 的 changeProperties 方法中。源码就不贴了,有兴趣的同学自己去查。

到这里已经真相大白了,笔者特意去查了 spring-data-elasticsearch 的 issue 列表。发现还真有此类问题:DATAES-550、DATAES-562。

要补充的是试过 springboot 2.1.0.RELEASE、2.1.5.RELEASE、2.1.9.RELEASE都不行,官方的解决方案是使用 spring-data-elasticsearch 3.2.x以上版本。但一来此版本要求的ES是6.8以上,二来是和项目中其它地方有奇怪的冲突,尝试了一段时间遂放弃。最后还是使用了自定义的 ObjectMapper 和 ElasticsearchTemplate 来手动写入:

public void save(TestLog log) {  IndexQuery indexQuery = new IndexQueryBuilder().withIndexName("test_log").withType("_doc").withId(log.getId()).withSource(objectMapper.writeValueAsString(log)).build();  elasticsearchTemplate.index(indexQuery);}

"spring-data-elasticsearch和Jackson配合使用有什么bug"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

序列 字段 注解 过程 结构 问题 项目 关键 内容 实例 属性 方法 更多 源码 版本 知识 测试 不行 郁闷 真相大白 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 方舟创建自己的服务器是永久的吗 华为将发布云数据库新产品 微信提示手机正在连接服务器 csgo设置服务器延时 安装金蝶服务器要选择客户端吗 古风网络安全手抄报五年级 服务器打开8082端口 服务器数据的安全管理软件 php 数据库 循环多条 现在软件开发主流编译器 新罗区浩芸电网络技术 河南六度空间软件开发公司 吉林卫星同步子母钟服务器云主机 电脑网络技术工作总结 计算机网络技术信息高速之 网络安全教育专业学校 人力资源技能数据库 网络安全法规班会 网络安全为人民手抄报二年级 数据库多少行受影响 周口软件开发操作 世界各国网络安全指数 分布式数据库同步软件 现在还用得着监控服务器吗 流式传输媒体服务器 ssm数据库怎么插入 计算机网络安全事件包括 nac网络安全准入控制研发公司 网络安全检测不到位 涞源高速服务器有什么吃的
0