Spring Data MongoDB实现@DBRef级联存储

这篇具有很好参考价值的文章主要介绍了Spring Data MongoDB实现@DBRef级联存储。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

	使用@DBRef时默认只会保存当前对象中的@DBRef对象,而不会保存嵌套对象中被@DBRef注解的类,例如:
//用户
@Document(collection = "Persons")
@Data
public class Person {
    @DBRef(lazy = true)
    private Book book;
}
//图书
@Document(collection = "Books")
@Data
public class Book {
    @DBRef(lazy = true)
    private Chapter chapter;
}
//章节
@Document(collection = "Chapters")
@Data
public class Chapter {...}

当使用上面的示例保存Person时,会报以下错误,原因是:被引用的对象的id属性为null

org.springframework.data.mapping.MappingException: Cannot create a reference to an object with a NULL id.

出现MappingException异常的原因:

  1. 被引用的对象在保存到数据库之前没有生成id。确保在保存被引用对象之前为其生成一个唯一的id。
  2. 被引用的对象在数据库中的id属性为null。在使用@DBRef进行查询时,被引用对象的id属性不能为空,否则无法创建引用。
  3. 引用关系配置错误。请确保在实体类之间的引用关系配置正确,包括正确使用@DBRef注解,以及引用对象的id属性和关联字段的映射关系正确。

AbstractMongoEventListener是什么?

AbstractMongoEventListener是Spring Data MongoDB框架提供的一个抽象类,用于监听MongoDB的事件并执行相应的操作。它提供了一组钩子方法,可以在MongoDB的不同事件发生时进行回调。

AbstractMongoEventListener的主要作用是允许开发人员在MongoDB的不同操作(如插入、更新、删除等)发生时执行自定义的逻辑。通过继承AbstractMongoEventListener并覆盖相应的方法,我们可以在特定操作之前、之后或在特定的操作上执行自定义操作。具体来说,AbstractMongoEventListener提供了以下一些方法:

  1. onBeforeConvert: 当将领域对象转换为持久化文档之前,调用此方法。
  2. onBeforeSave: 当将领域对象保存到数据库之前,调用此方法。
  3. onAfterSave: 在将领域对象保存到数据库之后,调用此方法。
  4. onAfterLoad: 在从数据库加载领域对象后,调用此方法。
  5. onBeforeDelete: 在删除领域对象之前,调用此方法。
  6. onAfterDelete: 在删除领域对象之后,调用此方法。

通过覆盖这些方法,可以实现一些额外的业务逻辑,如在保存对象之前进行数据验证、在对象保存之后执行一些后处理操作等。此外,AbstractMongoEventListener还可以扩展为自定义事件监听器,监听其他MongoDB事件(如索引创建、索引删除等)。

需要注意的是,为了使用AbstractMongoEventListener,我们需要将其注册为Spring的Bean,并将其与MongoTemplate或MongoRepository关联起来,以便框架在适当的时机调用监听器的方法。

自定义监听onBeforeConvert,实现级联存储

import com.sun.istack.internal.NotNull;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener;
import org.springframework.data.mongodb.core.mapping.event.BeforeConvertEvent;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.List;

/**
 * mongoDB实现级联存储,支持List列表级联存储
 */
@Component
public class CascadingMongoEventListener extends AbstractMongoEventListener {

    @Resource
    private MongoOperations mongoOperations;

    @Override
    public void onBeforeConvert(BeforeConvertEvent event) {
        Object document = event.getSource();
        ReflectionUtils.doWithFields(document.getClass(), new CascadeCallback(document, mongoOperations));
    }
    private static class CascadeCallback implements ReflectionUtils.FieldCallback {
        private final Object source;
        private final MongoOperations mongoOperations;
        public CascadeCallback(Object source, MongoOperations mongoOperations) {
            this.source = source;
            this.mongoOperations = mongoOperations;
        }
        @Override
        public void doWith(@NotNull Field field) throws IllegalArgumentException, IllegalAccessException {
            ReflectionUtils.makeAccessible(field);
            if (!field.isAnnotationPresent(DBRef.class)) {
                return;
            }
            Object fieldValue = field.get(source);
            if(fieldValue == null) {
                return;
            }
            if(fieldValue instanceof List) {
                List<?> list = (List<?>) fieldValue;
                list.forEach(mongoOperations::save);
            } else {
                mongoOperations.save(fieldValue);
            }
        }
    }
}

使用

创建 PersonBookChapter

@Document(collection = "Persons")
@Data
public class Person {
    @JsonSerialize(using = ObjectIdSerializer.class)
    @JsonDeserialize(using = ObjectIdDeserializer.class)
    @Id
    private ObjectId id;
    private String name;
    @DBRef(lazy = true)
    private Book book;//支持List<Book>
}

@Document(collection = "Books")
@Data
public class Book {

    @JsonSerialize(using = ObjectIdSerializer.class)
    @JsonDeserialize(using = ObjectIdDeserializer.class)
    @Id
    private ObjectId id;
    private String name;
    private Double price;
    @DBRef(lazy = true)
    private Chapter chapter;//支持List<Chapter>
}

@Document(collection = "Chapters")
@Data
public class Chapter {
    @JsonSerialize(using = ObjectIdSerializer.class)
    @JsonDeserialize(using = ObjectIdDeserializer.class)
    @Id
    private ObjectId id;
    private String name;
    private String content;
}

验证

curl --location 'http://localhost:8080/person' \
--header 'Content-Type: application/json' \
--data '{
    "name":"小明",
    "book":{
            "name":"Go语言入门",
            "price":39.9,
            "chapter":{
                "name":"第一章",
                "content":"认识GO初级语法"
            }
    }
}'

总结

使用@DBRef进行级联存储的方式就是通过继承AbstractMongoEventListener并重写onBeforeConvert方法在保存文档之前先保存子对象,就可以实现级联存储,需要注意,使用当前配置会全局生效,如果想要自定义级联存储可以使用自定义注解实现,扫描指定注解后进行级联存储。文章来源地址https://www.toymoban.com/news/detail-527902.html

到了这里,关于Spring Data MongoDB实现@DBRef级联存储的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Spring连载】使用Spring Data访问 MongoDB(二)----Template API

    MongoTemplate及其反应式(reactive)对应类位于org.springframework.data.mongodb.core包中,是Spring MongoDB支持的中心类,为与数据库交互提供了丰富的功能集。该template提供了创建、更新、删除和查询MongoDB文档的方便操作,并提供了域对象和MongoDB documents之间的映射。 配置后,MongoTemplate是线

    2024年02月21日
    浏览(38)
  • 13、MongoDB--通过 SpringBoot 整合 Spring Data MongoDB(【连接多个 MongoDB 服务器】、【高级定制 MongoDB 客户端】的简单介绍)

    放弃 Spring Boot 为 MongeDB 提供的自动配置,接下来同样要干如下事情: 手动配置多组 ReactiveMongoDatabaseFactory 和 ReactiveMongoTemplate,要连几个 MongoDB 服务器就配置几组。 同步 API 则使用 MongoDatabaseFactory 和 MongoTemplate。 针对不同 MongoDB 服务器,分别开发相应的 DAO 组件类,建议将它

    2024年03月19日
    浏览(66)
  • Spring Cloud微服务架构:实现分布式系统的无缝协作

    🎉欢迎来到架构设计专栏~Spring Cloud微服务架构:实现分布式系统的无缝协作 ☆* o(≧▽≦)o *☆嗨~我是IT·陈寒🍹 ✨博客主页:IT·陈寒的博客 🎈该系列文章专栏:架构设计 📜其他专栏:Java学习路线 Java面试技巧 Java实战项目 AIGC人工智能 数据结构学习 🍹文章作者技术和水

    2024年02月08日
    浏览(61)
  • Spring Boot - 利用Resilience4j-Circuitbreaker实现断路器模式_防止级联故障

    Spring Boot - 利用Resilience4j-RateLimiter进行流量控制和服务降级 Resilience4J 是一个针对 Java 8 应用程序的轻量级容错和弹性库。它设计用于在分布式系统中的服务之间提供弹性和容错性。Resilience4J 的名字来源于它提供的核心功能,即让系统(服务)能够“弹性”(resilient)地应对各

    2024年01月19日
    浏览(100)
  • 【数据架构】Data Fabric 架构是实现数据管理和集成现代化的关键

    DA 领导者应该了解数据编织架构的关键支柱,以实现机器支持的数据集成。 在日益多样化、分布式和复杂的环境中,数据管理敏捷性已成为组织的任务关键优先事项。为了减少人为错误和总体成本,数据和分析 (DA) 领导者需要超越传统的数据管理实践,转向现代解决方案,例

    2024年02月16日
    浏览(43)
  • uniapp 使用 uni-data-picker级联选择器,自定义展示,uni小程序

    先看效果是不是你要的效果 页面组件 接口数据 接口数据以及处理方式 选中后的数据处理,拿到选中的值

    2024年02月05日
    浏览(59)
  • Spring boot MongoDB实现自增序列

    在某些特定的业务场景下,会需要使用自增的序列来维护数据,目前项目中因为使用MongoDB,顾记录一下如何使用MongoDB实现自增序列。 MongoDB自增序列原理 MongoDB本身不具有自增序列的功能,但是MongoDB的 $inc 操作是具有原子性的,因为操作的原子性,那么就可以通过 $inc 序列

    2024年02月12日
    浏览(46)
  • Spring boot MongoDB 实现自定义审计字段

    AuditorAware 是什么? AuditorAware 是Spring Data提供的一个接口,用于提供当前执行数据库操作的\\\"审计员\\\"的信息。\\\"审计员\\\"可以是当前操作的用户、系统的默认用户或其他相关信息,用于记录和跟踪数据的变更历史。 具体来说, AuditorAware 的作用是为实体类中标记了 @CreatedBy 和 @L

    2024年02月12日
    浏览(39)
  • 系统存储架构升级分享

    系统业务功能 :系统内部进行数据处理及整合, 对外部系统提供结果数据的初始化(写)及查询数据结果服务。 系统网络架构 :       部署架构对切量上线的影响 - 内部管理系统上线对其他系统的读业务无影响 分布式缓存可进行单独扩容, 与存储及查询功能升级无关 通过缓存层

    2024年02月03日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包