赞
踩
业务场景中经常有需要生成单号,单号是连续递增的,不能中断
例如:生成一个单号,单号规则是,四位流水号,初始值:0001
从数据库中查询最大的值
基于mybatis-plus的QueryWrapper查询
在这个最大值基础上加一
使用hutool的工具StrUtil类中的padPre方法,补充字符串以满足指定长度
<!-- hutool依赖 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.19</version>
</dependency>
<!-- mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.toolkit.support.SFunction; import com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda; import org.apache.ibatis.reflection.property.PropertyNamer; import org.springframework.stereotype.Component; import java.lang.reflect.Field; /** * @date 2024/2/21 */ @Component public class NumberGenerateUtil { /** * 单号生成(纯数字,不走redis) * * @param func * @param length * @param baseMapper * @param <T> * @return */ public <T> String genAutoNumber(SFunction<T, ?> func, int length, BaseMapper<T> baseMapper) { String maxValue = getMaxValue(func, baseMapper); if (maxValue != null) { return numberAdd(maxValue); } else { return StrUtil.padPre("1", length, "0"); } } /** * 获取数据库中字段的最大值 * * @param func * @param baseMapper * @param <T> * @return */ private <T> String getMaxValue(SFunction<T, ?> func, BaseMapper<T> baseMapper) { String property = PropertyNamer.methodToProperty(SerializedLambda.resolve(func).getImplMethodName()); String column = StrUtil.toUnderlineCase(property); QueryWrapper<T> queryWrapper = new QueryWrapper<>(); queryWrapper.select("max(" + column + ") as " + property); queryWrapper.last("for update"); T entity = baseMapper.selectOne(queryWrapper); if (entity == null) { return null; } Object propertyValue = getValueByPropName(entity, property); if (propertyValue == null) { return null; } else { return propertyValue.toString(); } } /** * 编号加1 * * @param number * @return */ private static String numberAdd(String number) { int addend = Integer.parseInt(number); addend = addend + 1; String s = String.valueOf(addend); if (s.length() > number.length()) { throw new RuntimeException("编号长度超出限制"); } return StrUtil.padPre(s, number.length(), "0"); } /** * 通过属性名获取对象的属性值 * * @param object * @param propName * @return */ public String getValueByPropName(Object object, String propName) { String value = null; try { // 通过属性获取对象的属性 // getDeclaredFields() 获得某个类的所有声明的字段,即包括public、private和proteced但不包括父类申明字段 // getClass() 是⼀个对象实例的⽅法,只有对象实例才有这个⽅法,具体的类是没有的 Field field = object.getClass().getDeclaredField(propName); // 对象的属性的访问权限设置为可访问 // 允许获取实体类private的参数信息 field.setAccessible(true); // 获取属性的对应的值 value = field.get(object).toString(); } catch (Exception e) { return null; } return value; } }
为商品的number设置单号
import com.mamba.mybatisplus.entity.Product; import com.mamba.mybatisplus.mapper.ProductMapper; import com.mamba.mybatisplus.service.ProductService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.mamba.mybatisplus.utils.NumberGenerateUtil; import lombok.SneakyThrows; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.RequestBody; import javax.annotation.Resource; import java.util.concurrent.atomic.AtomicInteger; /** * <p> * 商品表 服务实现类 * </p> * @since 2024-02-21 */ @Service public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService { @Resource private NumberGenerateUtil numberGenerateUtil; @Resource private ProductMapper productMapper; @Override @Transactional(rollbackFor = Exception.class) public Product add(Product product) { String number = numberGenerateUtil.genAutoNumber(Product::getNumber, 4, productMapper); product.setNumber(number); save(product); return product; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。