使用了Mybatis 增强工具包 mybatis-plus: mybatis 增强工具包,简化 CRUD 操作。 文档 http://baomidou.com低代码组件库 http://aizuda.com
java 泛型详解-绝对是对泛型方法讲解最详细的,没有之一-CSDN博客 泛型相关
本来这里有一大段溢美之词,但是写完感觉也没什么高大上的,但是作为小白下面的代码极其思想是我需要多学习的,之前一直加班,现在有点时间开始欣赏cto的代码;大概介绍一下:简单的三层,采用springboot,redis,baomidou,一切从简原来的mq也去掉了,当然即使mq在,这四个也不是本文的重点;
实体相关:
//这里的id和key是后面的业务需要
public interface ObjectWithId {
Long getId();
void setId(Long id);
}
public interface ObjectWithIdAndKey extends ObjectWithId {
String getKey();
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class RegionStockBO implements ObjectWithIdAndKey {
private Long id;
//……
@Override
public String getKey() {
return "some function to generate key ";
}
}
//这块我们借助mapstruct进行转换,对于泛型需要了解一下,结合下面RfidBoDoConvertor一起看
public interface BoDoConvertor<BO extends ObjectWithId, DO extends ObjectWithId> extends AllEnumConvertor {
BO doToBo(DO o);
List<BO> doListToBoList(List<DO> doList);
DO boToDo(BO o);
List<DO> boListToDoList(List<BO> boList);
}
import org.mapstruct.Mapper;
import org.mapstruct.ReportingPolicy;
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface RfidBoDoConvertor extends
BoDoConvertor<RfidBO, RfidDO>,
ContainerIdConvertor {
//ContainerIdConvertor对id为null的处理,省略
}
如果没有BoDoConvertor,我们的转换最简洁的也要类似这样的,而不是只定义接口
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface BizRuleConverter {
BizRule toBizRule(BizRuleBO bizRuleBO);
BizRuleBO toBizRuleBO(BizRuleBO bizRuleBO);
List<BizRuleBO> toBizRuleBOList(List<BizRule> bizRuleList);
}
当然这样的封装处理的只是针对大部分的情况,如果有其他五花八门需求则需要单写:(当然这是mapstruct的)
@Mapping(target = "salt", ignore = true)
@Mapping(target = "userId", source = "userID")
@Mapping(target = "outboundOrderDO.source", constant = "20")
@Mapping(target = "updateAt", expression = "java(java.time.LocalDateTime.now())")
@Mapping(target = "outboundDetailNum", expression = "java(com.megvii.lbg.fr.wes.utils.IDCreatorUtil.getNextInboundLongId())")
OutboundOrderDetailDO mapOutboundOrderDetailDO(IF009ReceiveInfo if009ReceiveInfo);
@Mapping(target = "outboundOrderDO.orderCreateAt", expression = "java(java.time.LocalDateTime.ofEpochSecond(entry.getValue().get(0).getCreateDt(), 0, java.time.ZoneOffset.ofHours(8)))")
@Mapping(target = "outboundOrderDetailDOList", source = "entry.value")
OutboundOrderBo mapOutboundOrderByMapEntry(Map.Entry<String, List<IF009ReceiveInfo>> entry);
service例子:先写增删改查的逻辑吧
//二八定律,八成多的代码是简单的,另外的二成可以使其不那么复杂
public interface ContainerService extends ObjectsWithCacheService<ContainerBO, ContainerDO> {
ContainerBO getVirtualContainerBO();
}
//ObjectWithIdAndKey与ObjectWithId见后面
public interface ObjectsWithCacheService<BO extends ObjectWithIdAndKey, DO extends ObjectWithId>
extends IService<DO> {
BO getObjectById(Long id);
BO getObjectByKey(String key);
List<BO> getAllObjects();
void updateCache(BO value);
void removeFromCache(Long id);
void init();
DO boToDo(BO bo);
List<DO> boListToDoList(List<BO> boList);
BO doToBo(DO o);
}
//这块真的省了很多代码,当然也有缺点,先看思想:其实也没啥,武林秘籍就两字:泛型!
/**
* ObjectsWithCacheServiceImpl
* ServiceImpl是baomidou的
* @param <Mapper> baomidou的,继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能
* @param <DO> 自己的
* @param <Convertor> 自己的
* @param <BO> 自己
*/
@Slf4j
@Transactional
public abstract class ObjectsWithCacheServiceImpl<
Mapper extends BaseMapper<DO>,
DO extends ObjectWithId,
Convertor extends BoDoConvertor<BO, DO>,
BO extends ObjectWithIdAndKey>
extends ServiceImpl<Mapper, DO>
implements ObjectsWithCacheService<BO, DO> {
@Autowired
protected Convertor convertor;
protected Map<Long, BO> idMap = new HashMap<>();
protected Map<Object, BO> valueMap = new HashMap<>();
@Override
public BO getObjectById(Long id) {
return this.idMap.get(id);//id是ObjectWithId
}
@Override
public BO getObjectByKey(String key) {
return this.valueMap.get(key);//这个key是ObjectWithIdAndKey里面的
}
@Override
public List<BO> getAllObjects() {
return List.copyOf(this.idMap.values());
}
@Override
public void updateCache(BO bo) {
this.idMap.put(bo.getId(), bo);
this.valueMap.put(bo.getKey(), bo);
}
@Override
public void removeFromCache(Long id) {
this.valueMap.remove(this.idMap.remove(id).getKey());
}
@Override
public void init() {
var doList = this.getBaseMapper().selectList(new QueryWrapper<>());
this.idMap.clear();
this.valueMap.clear();
doList.forEach(o -> {
var bo = this.convertor.doToBo(o);
this.idMap.put(bo.getId(), bo);
this.valueMap.put(bo.getKey(), bo);
});
}
@Override
public DO boToDo(BO bo) {
return this.convertor.boToDo(bo);
}
@Override
public List<DO> boListToDoList(List<BO> boList) {
return this.convertor.boListToDoList(boList);
}
@Override
public BO doToBo(DO o) {
return this.convertor.doToBo(o);
}
}
这样主体代码就写差不多了,但是怎么用哪?给点提示性的提问:idMap,valueMap的数据怎么put又如何get?这时候抬头望望天是想不出来的,上面的代码会给你第二条思路,你看init方法,当然还可以加工这个抽象类让它更巴适:
public interface InventoryLockService extends ObjectsWithCacheService<InventoryLockBO, InventoryLockDO> {}
@Slf4j
@Service
public class InventoryLockServiceImpl
extends ObjectsWithCacheServiceImpl
<InventoryLockMapper, InventoryLockDO, InventoryLockBoDoConvertor, InventoryLockBO>
implements InventoryLockService {
@Autowired
private RfidService rfidService;
@Autowired
private ContainerService containerService;
@Autowired
private RegionStockService regionStockService;
@Override
public void init() {
super.init();//父类,组织数据,下面就是自己的业务处理了
var reservedRfidBOList = new ArrayList<RfidBO>();
var reservedContainerList = new ArrayList<ContainerBO>();
this.idMap.values().forEach(inventoryLockBO -> {
if (inventoryLockBO.getLockType() == LockTypeEnum.RFID) {
var rfidBO = this.rfidService.getObjectByKey(inventoryLockBO.getTarget());
rfidBO.lock(inventoryLockBO, false);
if (inventoryLockBO.isForReserved()) {
reservedRfidBOList.add(rfidBO);
}
} else if (inventoryLockBO.getLockType() == LockTypeEnum.CONTAINER) {
var containerBO = this.containerService.getObjectByKey(inventoryLockBO.getTarget());
containerBO.lock(inventoryLockBO, false);
if (inventoryLockBO.isForReserved()) {
reservedContainerList.add(containerBO);
}
} else {
throw ErrorCodes.SYSTEM_EXCEPTION.exception("invalid lock type {}", inventoryLockBO.getLockType());
}
});
var stock = RfidBO.calculateStock(reservedRfidBOList);
for (var containerBO : reservedContainerList) {
stock.increase(containerBO.getStock());
}
this.regionStockService.lockReserve(stock);
}
}
看完很容易,其中思想入驻大脑,还需要努力