Prechádzať zdrojové kódy

【功能优化】全局:增加 selectFirstOne 方法,解决容易出现并发场景下的查询

YunaiV 5 mesiacov pred
rodič
commit
2dc8071faa

+ 28 - 2
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java

@@ -92,10 +92,36 @@ public interface BaseMapperX<T> extends MPJBaseMapper<T> {
 
     default T selectOne(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2,
                         SFunction<T, ?> field3, Object value3) {
-        return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2)
-                .eq(field3, value3));
+        return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2).eq(field3, value3));
     }
 
+    /**
+     * 获取满足条件的第 1 条记录
+     *
+     * 目的:解决并发场景下,插入多条记录后,使用 selectOne 会报错的问题
+     *
+     * @param field 字段名
+     * @param value 字段值
+     * @return 实体
+     */
+    default T selectFirstOne(SFunction<T, ?> field, Object value) {
+        // 如果明确使用 MySQL 等场景,可以考虑使用 LIMIT 1 进行优化
+        List<T> list = selectList(new LambdaQueryWrapper<T>().eq(field, value));
+        return CollUtil.getFirst(list);
+    }
+
+    default T selectFirstOne(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2) {
+        List<T> list = selectList(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2));
+        return CollUtil.getFirst(list);
+    }
+
+    default T selectFirstOne(SFunction<T,?> field1, Object value1, SFunction<T,?> field2, Object value2,
+                             SFunction<T,?> field3, Object value3) {
+        List<T> list = selectList(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2).eq(field3, value3));
+        return CollUtil.getFirst(list);
+    }
+
+
     default Long selectCount() {
         return selectCount(new QueryWrapper<>());
     }

+ 2 - 3
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/history/ProductBrowseHistoryMapper.java

@@ -21,9 +21,8 @@ import java.util.Collection;
 public interface ProductBrowseHistoryMapper extends BaseMapperX<ProductBrowseHistoryDO> {
 
     default ProductBrowseHistoryDO selectByUserIdAndSpuId(Long userId, Long spuId) {
-        return selectOne(new LambdaQueryWrapperX<ProductBrowseHistoryDO>()
-                .eq(ProductBrowseHistoryDO::getUserId, userId)
-                .eq(ProductBrowseHistoryDO::getSpuId, spuId));
+        return selectFirstOne(ProductBrowseHistoryDO::getUserId, userId,
+                ProductBrowseHistoryDO::getSpuId, spuId);
     }
 
     default PageResult<ProductBrowseHistoryDO> selectPage(ProductBrowseHistoryPageReqVO reqVO) {

+ 5 - 8
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/social/SocialUserMapper.java

@@ -5,23 +5,20 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.module.system.controller.admin.socail.vo.user.SocialUserPageReqVO;
 import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import org.apache.ibatis.annotations.Mapper;
 
 @Mapper
 public interface SocialUserMapper extends BaseMapperX<SocialUserDO> {
 
     default SocialUserDO selectByTypeAndCodeAnState(Integer type, String code, String state) {
-        return selectOne(new LambdaQueryWrapper<SocialUserDO>()
-                .eq(SocialUserDO::getType, type)
-                .eq(SocialUserDO::getCode, code)
-                .eq(SocialUserDO::getState, state));
+        return selectOne(SocialUserDO::getType, type,
+                SocialUserDO::getCode, code,
+                SocialUserDO::getState, state);
     }
 
     default SocialUserDO selectByTypeAndOpenid(Integer type, String openid) {
-        return selectOne(new LambdaQueryWrapper<SocialUserDO>()
-                .eq(SocialUserDO::getType, type)
-                .eq(SocialUserDO::getOpenid, openid));
+        return selectFirstOne(SocialUserDO::getType, type,
+                SocialUserDO::getOpenid, openid);
     }
 
     default PageResult<SocialUserDO> selectPage(SocialUserPageReqVO reqVO) {