惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

J
Java Code Geeks
小众软件
小众软件
博客园 - 叶小钗
宝玉的分享
宝玉的分享
博客园_首页
Hugging Face - Blog
Hugging Face - Blog
人人都是产品经理
人人都是产品经理
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
S
SegmentFault 最新的问题
B
Blog RSS Feed
Engineering at Meta
Engineering at Meta
N
Netflix TechBlog - Medium
Google DeepMind News
Google DeepMind News
U
Unit 42
F
Fortinet All Blogs
IT之家
IT之家
Y
Y Combinator Blog
Martin Fowler
Martin Fowler
T
The Blog of Author Tim Ferriss
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
The GitHub Blog
The GitHub Blog
Stack Overflow Blog
Stack Overflow Blog
Blog — PlanetScale
Blog — PlanetScale
酷 壳 – CoolShell
酷 壳 – CoolShell

Chenxu's Blog

写出一份好的代码 linux 的基本操作 启动我的服务 更舒适地写代码(含学生白嫖指南) RAG检索优化:从 68% 到 82.2% 学习深度学习 北邮计算机研究生选课指北 学习机器学习 上海篇 提出一个好问题 写代码的环境 选购一台合适的设备 计算机的第零课 序言 内蒙古篇 山东篇 一篇对transformers的疑惑 浅析GPUStack 浅谈后端项目分层 浙江篇 河南篇 一些三端协同的开发工具记录 浅谈编程语言中的 GC 在 Windows 上安装 Rust 美化博客 消息队列 MyBatis 现代交换原理2024年题目 回忆版 北邮计科本科课程指北 ClkLog埋点用户分析系统研究报告 大数据梧桐实验分享
使用 MongoTemplate 时开启事务
Chenxu · 2023-11-24 · via Chenxu's Blog

最近有一个需求, 用户信息表内有一个唯一索引用户 id, 希望在插入时如果不存在该用户的信息则插入, 否则更新, 看了网上的方法, 似乎 MongoTemplate 并没有提供这项功能 (有类似的功能但只对主键 id 有效), 所以我选择了先删除, 再插入, 由此引发了我对事务的需求

修改 MongoDB 配置

MongoDB 的事务只能在开启副本集的时候才能使用,Windows 上的 MongoDB 安装后默认是单副本,所以我们首先需要将其转换为多副本.

找到 MongoDB 的安装目录, 在 bin 目录下有一个 mongod.cfg 配置文件, 在文件中增加配置:

replication:
    replSetName: rs0

然后重启 MongoDB, 以管理员身份运行终端:

net stop mongodb

net start mongodb

此时可以连上 MongoDB, 但是无法读取其中的数据, 所以需要初始化将其配置为副本集的成员, 在 MongoDB 的命令行界面执行以下命令 (这里使用 IDEA 提供的命令行):

# 初始化
rs.initiate()

# 查看状态
rs.status()

在 SpringBoot 中开启事务

先在配置文件中增加一项自定义配置, 这是为了兼容性

spring:
    data:
        mongodb:
            #      uri: mongodb://localhost/tcm
            host: localhost
            port: 27017
            database: test
            auto-index-creation: true
            transactionEnabled: true # 自定义配置, 打开事务

写配置类, 配置事务

@Configuration
public class MongoTransactionConfiguration {

    @Bean
    @ConditionalOnProperty(name = "spring.data.mongodb.transactionEnabled", havingValue = "true")
    MongoTransactionManager mongoTransactionManager(MongoDatabaseFactory factory) {
        return new MongoTransactionManager(factory);
    }
}

然后在需要的方法上面加上 @Transactional 注解就可以开启事务啦

测试结果

@Override
@Transactional(rollbackFor = Exception.class)
public UserInfo saveUserInfo(UserInfo userInfo) {
    userInfo.setUpdateTime(DateUtil.getNowTime());

    Query q = Query.query(Criteria.where("userId").is(userInfo.getUserId()));
    UserInfo info = mongoTemplate.findOne(q, UserInfo.class);
    if (info != null) {
        userInfo.setId(info.getId());
        mongoTemplate.remove(q, UserInfo.class);
        int i = 1 / 0; // 报错测试事务效果

    }
    return mongoTemplate.save(userInfo);
}

可以看到报错以后执行事务回滚, 并没有删除原来的 userId 为 1 的数据