位图法不够用:业务标识码处理对象打标问题

1 业务标识码

订单具有多种复杂的业务属性,例如订单是否参与营销活动,是否当日达,是否次日达等等。对于这种业务要求,第一使用状态机不合适,因为状态机表达的是状态流转。

第二使用位图法是可以的,但是有局限性。局限一是长度有限制,例如无符号位BIGINT也只能表达64种业务标识位,如果超过则需要多个字段增加复杂度。局限二是每位只有0和1两种值,只能表示是和否,扩展性不强。

解决方案是使用字符串类型业务标识码,长度控制在100至500位。例如可以约定第一位表示营销属性,0表示无营销,1表示满减,2表示满折,3表示满减赠。第二位表示物流时效属性,0表示无时效要求,1表示当日达,2表示次日达。

假设一笔订单是满折次日达订单,服务标识码长度是100位,那么字段值是:

22000....0000(长度100位)

2 业务实例

2.1 建表语句

CREATE TABLE business_info (
    id INT AUTO_INCREMENT PRIMARY KEY,
    business_code VARCHAR(100) DEFAULT REPEAT('0', 100)
);

2.2 业务对象

public class BusinessInfo {
    private Integer id;
    private String businessCode;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getBusinessCode() {
        return businessCode;
    }

    public void setBusinessCode(String businessCode) {
        this.businessCode = businessCode;
    }
}

2.3 Mapper

@Mapper
public interface BusinessInfoMapper {
    BusinessInfo getBusinessInfoById(int id);

    void updateBusinessCode(@Param("id") int id, 
    @Param("businessCode") String businessCode);
}

2.4 BusinessCodeService

真实业务场景中需要使用分布式锁控制并发设值,并注意postion边界校验:

@Service
public class BusinessCodeService {

    @Autowired
    private BusinessInfoMapper businessInfoMapper;

    /**
     * 设置业务标识码某一位值
     * @param id 主键
     * @param position 业务标识码位置(从 0 开始)
     * @param value 业务标识码在该位置值(0-9)
     */
    public void setBusinessCode(int id, int position, int value) {
        BusinessInfo info = businessInfoMapper.getBusinessInfoById(id);
        if (info != null) {
            String currentCode = info.getBusinessCode();
            StringBuilder codeBuilder = new StringBuilder(currentCode);
            codeBuilder.setCharAt(position, (char) (value + '0'));
            String newCode = codeBuilder.toString();
            info.setBusinessCode(newCode);
            businessInfoMapper.updateBusinessCode(id, newCode);
        }
    }

    /**
     * 查询业务标识码某一位值
     * @param id 主键
     * @param position 业务标识码位置(从 0 开始)
     * @return 业务标识码在该位置值不存在则返回 -1
     */
    public int getBusinessCodeValue(int id, int position) {
        BusinessInfo info = businessInfoMapper.getBusinessInfoById(id);
        if (info != null) {
            String code = info.getBusinessCode();
            if (position < code.length()) {
                return code.charAt(position) - '0';
            }
        }
        return -1;
    }
}

3 延伸阅读

位图法在mongodb中的应用

一个字段如何表示多种业务含义

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值