当前位置:   article > 正文

【基于SpringBoot和Mybatis-Plus的关联表关联关系保存和修改】_mybatisplus级联保存数据

mybatisplus级联保存数据

本项目是个微服务项目,采用前后端分离方式进行协作开发。需求描述:表A和和表B通过equity_id进行关联,其中A->B是一对多且双向绑定关系。对此关联关系保证可编辑和新增。整体思路:新增时候直接双向绑定,修改时候先根据id全部删除,再新增关联关系。特此设计整理如下:

一、表结构和实体类

1.equity_limit_buy_set

CREATE TABLE `equity_limit_buy_set` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键id',
  `del_flag` bit(1) NOT NULL DEFAULT b'0' COMMENT '删除状态:0否,1是',
  `equity_id` bigint(20) NOT NULL COMMENT '权益id',
  `effective_days` tinyint(1) NOT NULL DEFAULT '0' COMMENT '自购买后有效天数:默认值0:无限制',
  `limit_buy_num_type` tinyint(1) NOT NULL DEFAULT '0' COMMENT '购买次数类型限制:0不限购,1终身限购,2按周期限购,默认值0',    
  `limit_buy_num_cycle` tinyint(1) NOT NULL DEFAULT '0' COMMENT '购买次数周期限制:0终生,1每天,2每周,3每月',
  `limit_buy_num` int(11) NOT NULL DEFAULT '-1' COMMENT '限购数量:默认值:-1不限购',
  `limit_buy_user` bit(1) NOT NULL DEFAULT b'0' COMMENT '人群标签ID,0不限制购买人群,1:限制',
  `mutex_equity` bit(1) NOT NULL DEFAULT b'0' COMMENT '互斥权益ID列表,默认值:0没有互斥权益,1:有互斥权益',
  `stock_num` int(11) NOT NULL DEFAULT '-1' COMMENT '库存数量',
  `buy_button_text` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '立即购买' COMMENT '权益详情页:按钮文本',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  KEY `idx_equity_id` (`equity_id`)
) COMMENT='权益限购设置';
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

在这里插入图片描述

2.equity_limit_buy_mutex_equity

CREATE TABLE `equity_limit_buy_mutex_equity` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键id',
  `del_flag` bit(1) NOT NULL DEFAULT b'0' COMMENT '删除状态:0否,1是',
  `equity_id` bigint(20) NOT NULL COMMENT '权益id',
  `mutex_equity_id` bigint(20) NOT NULL COMMENT '互斥权益id',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  KEY `idx_equity_id` (`equity_id`),
  KEY `idx_mutex_equity_id` (`mutex_equity_id`)
) COMMENT='互斥权益关联设置';
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

在这里插入图片描述
其中equity_limit_buy_set中如果没有mutex_equity互斥权益,则mutex_equity为0;如果有则为1。然后在equity_limit_buy_mutex_equity中维护equity_id和mutex_equity_id的双向绑定关联关系。

3.EquityLimitBuySetConstant常量枚举类

public class EquityLimitBuySetConstant {

    /**
     * 购买次数限制:0不限购,1终身限购,2按周期限购,默认值0
     */
    @Getter
    @AllArgsConstructor
    public enum limitBuyNumTypeEnum{
        no_purchase_restrictions(0,"不限购"),
        lifetime_limit(1,"终身限购"),
        restricted_by_cycle(2,"按周期限购");

        private int code;
        private String message;
    }

    /**
     *购买次数限制:0终生,1每天,2每周,3每月
     */
    @Getter
    @AllArgsConstructor
    public enum limitBuyNumCycleEnum{
        lifetime(0,"终生") {
            @Override
            public Date[] getIntervalTime() {
                return null;
            }
        },
        daily(1,"每天") {
            @Override
            public Date[] getIntervalTime() {
                return new Date[]{DateUtils.getStartOfDay(new Date()),DateUtils.getEndOfDay(new Date())};
            }
        },
        weekly(2,"每周") {
            @Override
            public Date[] getIntervalTime() {
                return DateUtils.getWeekStartAndEnd(0);
            }
        },
        monthly(3,"每月") {
            @Override
            public Date[] getIntervalTime() {
                return DateUtils.getMonthStartAndEnd();
            }
        };
        private int code;
        private String message;

        protected abstract Date[] getIntervalTime();

        public static Date[] getDateArray(int code){
            final limitBuyNumCycleEnum cycleEnum = Arrays.stream(values()).filter(v -> v.code == code).findFirst().orElse(null);
            if(Objects.isNull(cycleEnum)){
                return null;
            }
            return cycleEnum.getIntervalTime();
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59

4.请求和响应体EquityInfoEditReq

@Data
public class EquityInfoEditReq {

    @ApiModelProperty("权益基本信息")
    @NotNull(message = "权益基本信息不能为空")
    private EquityInfo baseInfo;

    @ApiModelProperty("权益附加信息")
    private EquityInfoExt extInfo;

    @ApiModelProperty("权益限购设置")
    private EquityLimitBuySetReq equityLimitBuySetReq;
}    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

EquityLimitBuySetReq

@Data
public class EquityLimitBuySetReq{

    @ApiModelProperty("权益id")
    private Long equityId;

    @ApiModelProperty("自购买后有效天数:默认值0:无限制,其他值为实际有效天数")
    private Integer effectiveDays;

    @ApiModelProperty("购买次数限制:0不限购,1终身限购,2按周期限购,默认值0")
    private Integer limitBuyNumType;

    @ApiModelProperty("购买周期限制:0终生,1每天,2每周,3每月,默认值0")
    private Integer limitBuyNumCycle;

    @ApiModelProperty("限购数量:默认值:-1不限购,其他值为实际限购数量")
    private Integer limitBuyNum;

    @ApiModelProperty("限购人群设置:默认0不限制购买人群,1:限制;实际限购人群配置在limitBuyUserGroup")
    private Byte limitBuyUser;

    @ApiModelProperty("互斥权益设置:默认值0没有互斥权益,1:有互斥权益;实际互斥权益配置在mutexEquityIds")
    private Byte mutexEquity;

    @ApiModelProperty("库存数量:默认-1不限制,其他值为实际库存数量")
    private Integer stockNum;

    @ApiModelProperty("限购人群组列表")
    private List<Long> limitBuyUserGroup;

    @ApiModelProperty("互斥权益列表")
    private List<Long> mutexEquityIds;

    @ApiModelProperty(value = "权益详情页:购买按钮文本")
    private String buyButtonText;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

二、业务逻辑层,主要涉及缓存的处理

1.EquityLimitBuySetService

public interface EquityLimitBuySetService extends IService<EquityLimitBuySet> {

    /**
     * 获取权益限购设置
     * @param limitBuySetByEquityId
     * @return EquityLimitBuySet
     */
    EquityLimitBuySet getLimitBuySetByEquityId(Long limitBuySetByEquityId);

    /**
     * 移除权益限购设置
     * @param equityId
     * @return boolean
    */
    boolean removeByEquityId(Long equityId);

    /**
     * 获取权益购买限制配置
     * @param id
     * @return
     * @throws Exception
     */
    EquityLimitBuySetReq getLimitBuySet(Long id) throws Exception;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

2.EquityLimitBuySetServiceImpl

@Service
public class EquityLimitBuySetServiceImpl extends ServiceImpl<EquityLimitBuySetMapper, EquityLimitBuySet>
    implements EquityLimitBuySetService{

    @Autowired
    private EquityLimitBuyUserService equityLimitBuyUserService;

    @Autowired
    private EquityLimitBuyMutexEquityService equityLimitBuyMutexEquityService;

    private static final String BUY_SET = "buySet";

     /**
     * 获取权益限购设置
     * @param equityId
     * @return EquityLimitBuySet
     */
    @Override
    @Cacheable(value = BUY_SET,key = "#p0")
    public EquityLimitBuySet getLimitBuySetByEquityId(Long equityId) {
        QueryWrapper queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("equity_id",equityId);
        return baseMapper.selectOne(queryWrapper);
    }

    /**
     * 移除权益限购设置
     * @param equityId
     * @return boolean
     */
    @CacheEvict(value=BUY_SET,key="#p0")
    @Override
    public boolean removeByEquityId(Long equityId) {
         return lambdaUpdate()
                .eq(EquityLimitBuySet::getEquityId, equityId)
                .remove();
    }
    
    /**
     * 获取权益购买限制配置
     * @param id
     * @return
     * @throws Exception
     */
    @Override
    public EquityLimitBuySetReq getLimitBuySet(Long id) throws Exception {
        EquityLimitBuySet equityLimitBuySet = this.getLimitBuySetByEquityId(id);
        if (equityLimitBuySet != null) {
            EquityLimitBuySetReq equityLimitBuySetReq = BeanCopyUtils.copyProperties(EquityLimitBuySetReq.class, equityLimitBuySet);
            if(equityLimitBuySet.getMutexEquity()){
                equityLimitBuySetReq.setMutexEquityIds(equityLimitBuyMutexEquityService.getMutexEquity(id));
            }
            if(equityLimitBuySet.getLimitBuyUser()){
                equityLimitBuySetReq.setLimitBuyUserGroup(equityLimitBuyUserService.getEquityLimitBuyUserByEquityId(id));
            }
            return equityLimitBuySetReq;
        }
        return null;
    }

    /**
     * 重写saveOrUpdate方法,清空缓存
     * */
    @CacheEvict(value=BUY_SET,key="#p0.equityId")
    @Override
    public boolean saveOrUpdate(EquityLimitBuySet entity) {
        return super.saveOrUpdate(entity);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69

3.EquityLimitBuyMutexEquityService

public interface EquityLimitBuyMutexEquityService extends IService<EquityLimitBuyMutexEquity> {
    /**
     * 查找互斥权益
     * @param limitBuyMutexByEquityId
     * @return
     */
    List<Long> getMutexEquity(Long limitBuyMutexByEquityId);

    /**
     * 保存权益和互斥权益关联关系
     * @param equityId
     * @param mutexEquityIds
     */
    void saveOrUpdateLimitBuyMutex(Long equityId, List<Long> mutexEquityIds);

    /**
     * 移除互斥权益关联设置关系
     * @param equityId
     * @return
     */
    boolean removeByEquityId(Long equityId);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

4.EquityLimitBuyMutexEquityServiceImpl

@Service
public class EquityLimitBuyMutexEquityServiceImpl extends ServiceImpl<EquityLimitBuyMutexEquityMapper, EquityLimitBuyMutexEquity>
    implements EquityLimitBuyMutexEquityService{

    private final static String BUY_MUTEX_EQUITY = "buyMutexEquity";

    /**
     * 查找互斥权益
     * @param limitBuyMutexByEquityId
     * @return
     */
    @Override
    @Cacheable(value = BUY_MUTEX_EQUITY,key = "#p0")
    public List<Long> getMutexEquity(Long limitBuyMutexByEquityId) {
        final List<EquityLimitBuyMutexEquity> equities = lambdaQuery().eq(EquityLimitBuyMutexEquity::getEquityId, limitBuyMutexByEquityId)
                .select(EquityLimitBuyMutexEquity::getMutexEquityId)
                .list();
        return equities.stream().map(EquityLimitBuyMutexEquity::getMutexEquityId).collect(Collectors.toList());
    }

    /**
     * 保存权益和互斥权益关联关系
     * @param equityId
     * @param mutexEquityIds
     */
    @CacheEvict(value = BUY_MUTEX_EQUITY,key="#p0")
    @Override
    public void saveOrUpdateLimitBuyMutex(Long equityId, List<Long> mutexEquityIds) {
        List<EquityLimitBuyMutexEquity> buyMutexEquity = new ArrayList<>();

        //删除双向绑定的互斥关系,采用nonIn是增量更新删除,提升效率
        lambdaUpdate()
                .notIn(EquityLimitBuyMutexEquity::getMutexEquityId,mutexEquityIds)
                .eq(EquityLimitBuyMutexEquity::getEquityId,equityId)
                .remove();
        lambdaUpdate()
                .notIn(EquityLimitBuyMutexEquity::getEquityId,mutexEquityIds)
                .eq(EquityLimitBuyMutexEquity::getMutexEquityId,equityId)
                .remove();

        //查找双向绑定的互斥关系
        List<EquityLimitBuyMutexEquity> mutexIdsList = lambdaQuery()
                .in(EquityLimitBuyMutexEquity::getMutexEquityId, mutexEquityIds)
                .eq(EquityLimitBuyMutexEquity::getEquityId,equityId)
                .list();
        List<EquityLimitBuyMutexEquity> equityIdsList = lambdaQuery()
                .eq(EquityLimitBuyMutexEquity::getMutexEquityId, equityId)
                .in(EquityLimitBuyMutexEquity::getEquityId,mutexEquityIds)
                .list();

        //获取双向绑定的互斥权益id和权益id
        Set<Long> mutexIds = mutexIdsList.stream().map(EquityLimitBuyMutexEquity::getMutexEquityId).collect(Collectors.toSet());
        Set<Long> equityIds = equityIdsList.stream().map(EquityLimitBuyMutexEquity::getEquityId).collect(Collectors.toSet());

        //保存双向绑定的关联关系
        mutexEquityIds.stream().forEach(
                i -> {
                    if(!mutexIds.contains(i)){
                        EquityLimitBuyMutexEquity mutexIdEquity = EquityLimitBuyMutexEquity.builder()
                                .equityId(equityId)
                                .mutexEquityId(i)
                                .build();
                        buyMutexEquity.add(mutexIdEquity);
                    }

                    if(!equityIds.contains(i)){
                        EquityLimitBuyMutexEquity equityIdEquity = EquityLimitBuyMutexEquity.builder()
                                .equityId(i)
                                .mutexEquityId(equityId)
                                .build();
                        buyMutexEquity.add(equityIdEquity);
                    }
                });
        this.saveBatch(buyMutexEquity);
    }

    /**
     * 移除互斥权益关联设置关系
     * @param equityId
     * @return
     */
    @CacheEvict(value = BUY_MUTEX_EQUITY,key="#p0")
    @Override
    public boolean removeByEquityId(Long equityId) {
        return lambdaUpdate()
                .eq(EquityLimitBuyMutexEquity::getEquityId,equityId)
                .remove();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89

5.saveOrUpdateEquityLimitBuySet

    /**
     * 保存或修改权益限购设置
     *
     * @param equityId
     * @param req
     * @return Long
     * @throws CommonException
     */
    public Boolean saveOrUpdateEquityLimitBuySet(Long equityId, EquityInfoEditReq req) throws Exception {
        EquityLimitBuySetReq buySetReq = req.getEquityLimitBuySetReq();
        if (buySetReq != null) {
            EquityLimitBuySet equityLimitBuySet = BeanCopyUtils.copyProperties(EquityLimitBuySet.class, buySetReq);
            equityLimitBuySet.setDelFlag(false);
            equityLimitBuySet.setEquityId(equityId);
            EquityLimitBuySet limitBuySetByEquityId = equityLimitBuySetService.getLimitBuySetByEquityId(equityId);
            if(limitBuySetByEquityId != null){
			    //后续用于保存或者新增判断标志
                equityLimitBuySet.setId(limitBuySetByEquityId.getId());
            }
            //互斥权益id列表
            List<Long> mutexEquityIds = buySetReq.getMutexEquityIds();

            //保存或修改互斥权益id列表
            if (CollectionUtils.isEmpty(buySetReq.getMutexEquityIds())) {
                equityLimitBuySet.setMutexEquity(false);
				//删除缓存
                equityLimitBuyMutexEquityService.removeByEquityId(equityId);
            } else {
                equityLimitBuySet.setMutexEquity(true);
                equityLimitBuyMutexEquityService.saveOrUpdateLimitBuyMutex(equityId, mutexEquityIds);
            }
            equityLimitBuySetService.saveOrUpdate(equityLimitBuySet);
        }else{
            //权益限购设置为空的时候移除缓存
            equityLimitBuySetService.removeByEquityId(equityId);
            equityLimitBuyMutexEquityService.removeByEquityId(equityId);
        }
        return true;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

三、测试结果

在这里插入图片描述
在这里插入图片描述

四、总结

新增和删除关联关系表数据时候,需要考虑各种情况,尤其是对缓存淘汰时机的把控。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/代码探险家/article/detail/830465
推荐阅读
相关标签
  

闽ICP备14008679号