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;
}
}