您的位置:首页 > 财经 > 金融 > 在线制作图片美图_怎么下载建筑工程网_营销型网站建站_seo中介平台

在线制作图片美图_怎么下载建筑工程网_营销型网站建站_seo中介平台

2025/7/16 3:43:02 来源:https://blog.csdn.net/m0_68389211/article/details/147566321  浏览:    关键词:在线制作图片美图_怎么下载建筑工程网_营销型网站建站_seo中介平台
在线制作图片美图_怎么下载建筑工程网_营销型网站建站_seo中介平台

大家吼鸭!今天学习新项目的时候,项目中运用了编程式项目,有点不理解什么叫编程式事务,于是我去查询了一些资料,大概了解了一下。现在做一个简单的介绍。

编程式事务和声明式事务的区别

现在想象一个场景,你妈让你去买酱油(事务操作),如果此时是

  • 编程式事务(手动档)

你妈对你说:“你先带钱出门(开始事务),买酱油(操作),如果超市关门了(失败),就把钱带回来(回滚),否则付钱(提交)“,你全程需要自己判断,如果超市没关门,买酱油,关门了,不买。灵活但累。

  • 声明式事务

你妈直接给你贴个纸条,“买酱油,买不到就回家”(@Transactional)。你无需自己动脑,但是纸条写死了规则,遇到特殊情况(比如超市排队太长)没法临时改主意。

编程式事务

定义
通过编写代码手动控制事务的开启、提交、回滚等操作,直接调用事务管理 API(如 TransactionTemplatePlatformTransactionManager)。

特点

  • 代码侵入性强:事务管理与业务逻辑耦合。
  • 灵活性高:可以精确控制事务的边界(例如在嵌套逻辑中动态决定事务行为)。
    • 事务边界指的是开始点和结束点
      • 开始点:开启事务(如 transactionTemplate.execute()@Transactional 方法入口)。
      • 结束点:提交事务或回滚事务的时候
  • 需要手动处理:需要显式调用 execute()commit()rollback() 等方法。

例如:

return transactionTemplate.execute(status -> {// 事务操作(更新数据库、删除缓存等)return success;
});

这里通过 TransactionTemplateexecute() 方法手动包裹事务逻辑。

下面是编程式事务的简单示例,以点赞项目为例:

      // 加锁,避免用户短时间多次取消点赞synchronized (loginUser.getId().toString().intern()) {// 编程式事务return transactionTemplate.execute(status -> {// 获取当前当前进行点赞的博客idLong blogId = doThumbRequest.getBlogId();// 判断当前用户是否已经点赞过该博客
//                Thumb thumb = this.lambdaQuery()
//                        .eq(Thumb::getBlogId, blogId)
//                        .eq(Thumb::getUserId, loginUser.getId())
//                        .one();Object thumbIdObj = redisTemplate.opsForHash().get(ThumbConstant.USER_THUMB_KEY_PREFIX + loginUser.getId().toString(), blogId.toString());// 如果没有点赞过,抛出异常ThrowUtils.throwIf(thumbIdObj == null, ErrorCode.OPERATION_ERROR, "未点赞过");Long thumbId = Long.valueOf(thumbIdObj.toString());// 更新博客点赞数 - 1boolean update = blogService.lambdaUpdate().eq(Blog::getId, blogId).setSql("thumbCount = thumbCount - 1").update();// 删除点赞记录boolean success = update && this.removeById(thumbId);if(success) {// 如果成功删除点赞记录,则将其从缓存中删除redisTemplate.opsForHash().delete(ThumbConstant.USER_THUMB_KEY_PREFIX + loginUser.getId().toString(), blogId.toString());}return success;});}

声明式事务

定义
通过注解(如 @Transactional)或 XML 配置声明事务规则,由框架自动管理事务的提交和回滚,无需编写事务管理代码。

特点

  • 代码侵入性低:通过 AOP 将事务逻辑与业务代码解耦。
  • 简洁性:只需一个注解即可完成事务控制。
  • 依赖代理机制:基于 Spring AOP 实现,通过动态代理在方法调用前后插入事务逻辑。

核心区别

特性编程式事务声明式事务
控制方式手动编写事务代码通过注解或配置声明
侵入性强(与业务代码耦合)弱(通过 AOP 分离)
灵活性高(可动态控制事务边界)较低(基于方法或类级别配置)
代码复杂度高(需处理提交、回滚)低(只需一个注解)
适用场景需要精细控制事务的复杂逻辑大多数常见业务场景

声明式事务举例

@Service
public class BlogService {@Autowiredprivate BlogMapper blogMapper;@Autowiredprivate ThumbService thumbService;// 声明式事务注解@Transactional(rollbackFor = Exception.class) // 指定所有异常都回滚public boolean cancelThumb(LoginUser loginUser, DoThumbRequest doThumbRequest) {// 业务逻辑(无需手动管理事务)Long blogId = doThumbRequest.getBlogId();Long userId = loginUser.getId();// 检查是否已点赞(直接操作数据库)Thumb thumb = thumbService.findByUserAndBlog(userId, blogId);if (thumb == null) {throw new BusinessException(ErrorCode.OPERATION_ERROR, "未点赞过");}// 更新博客点赞数boolean updateSuccess = blogMapper.decrementThumbCount(blogId) > 0;// 删除点赞记录boolean deleteSuccess = thumbService.removeById(thumb.getId());if (updateSuccess && deleteSuccess) {// 更新缓存(确保在事务提交后执行)redisTemplate.opsForHash().delete(ThumbConstant.USER_THUMB_KEY_PREFIX + userId, blogId.toString());}return updateSuccess && deleteSuccess;}
}
关键点说明:
  1. @Transactional 注解
    • 添加在方法或类上,声明该方法需要事务管理。
    • rollbackFor = Exception.class 表示所有异常(包括检查型异常)都会触发回滚(默认仅回滚运行时异常)。
  2. 事务边界
    • 方法开始时自动开启事务,方法正常结束时提交事务,抛出异常时回滚。
  3. 缓存与事务一致性
    • 缓存操作应放在事务提交之后(避免脏读)。如果使用声明式事务,缓存删除操作会在方法返回前(事务提交后)执行。
  4. 注意事项
    • 避免在同一个类中非事务方法调用 @Transactional 方法(代理失效问题)。
    • 确保数据库引擎支持事务(如 InnoDB)。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com