如何在Service中传参选择使用MyBatis或JPA执行持久化操作
实现方案
完全可以通过参数传递控制Service层调用不同持久化实现,下面是具体的修改方式:
基础实现(适配当前代码结构,改动最小)
第一步:修正Controller层代码
你当前Controller里接收query参数的注解错误,Spring MVC中接收查询参数需要用@RequestParam,同时直接将persistenceType作为参数传入Service的save方法即可,无需你伪代码中写的manufacturerService(persistenceType)调用形式。
修改后Controller代码:
@RestController @RequestMapping("/manufacturers") public class ManufacturesController { public static final Logger LOG = LogManager.getLogger(ManufacturesController.class); @Autowired private ManufacturerService manufacturerService; @PostMapping public ResponseEntity<Manufacturer> createManufacturer(@RequestBody ManufacturerDTO manufacturer, @RequestParam String persistenceType) { LOG.info("START - createManufacturer"); try { Manufacturer _manufacturer = ManufacturerMapper.toEntity(manufacturer); // 直接将persistenceType传入save方法 manufacturerService.save(_manufacturer, persistenceType); LOG.info("STOP - createManufacturer"); return new ResponseEntity<>(_manufacturer, HttpStatus.CREATED); } catch (Exception e) { LOG.error("Error description: ", e); LOG.info("STOP - createManufacturer"); return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); } } }
第二步:调整Service层方法
先定义枚举约束持久化类型,避免字符串拼写错误,再修改save方法增加参数和判断逻辑:
首先定义持久化类型枚举:
public enum PersistenceTypeEnum { MYBATIS, JPA }
修改后的Service代码:
@Service public class ManufacturerService implements IManufacturerService { @Autowired private ManufacturerRepository manufacturerRepository; @Autowired private ManufacturerMapper manufacturerMapper; @Override @Transactional public Manufacturer save(Manufacturer manufacturer, String persistenceType) { // 先做参数合法性校验 PersistenceTypeEnum type; try { type = PersistenceTypeEnum.valueOf(persistenceType.toUpperCase()); } catch (IllegalArgumentException e) { throw new RuntimeException("不支持的持久化类型:" + persistenceType); } // 根据类型选择实现 if (type == PersistenceTypeEnum.MYBATIS) { manufacturerMapper.insert(manufacturer); return manufacturer; } else { return manufacturerRepository.save(manufacturer); } } }
记得同步修改你Service接口IManufacturerService中save方法的签名,增加persistenceType参数。
优化实现(策略模式,适合后续扩展)
如果后续可能新增更多持久化实现,为了避免if/else逻辑臃肿,符合开闭原则,可以用策略模式重构:
- 定义持久化操作抽象接口
public interface ManufacturerPersistenceHandler { Manufacturer save(Manufacturer manufacturer); PersistenceTypeEnum getType(); }
- 分别实现MyBatis和JPA的处理器
@Component public class MyBatisManufacturerHandler implements ManufacturerPersistenceHandler { @Autowired private ManufacturerMapper manufacturerMapper; @Override public Manufacturer save(Manufacturer manufacturer) { manufacturerMapper.insert(manufacturer); return manufacturer; } @Override public PersistenceTypeEnum getType() { return PersistenceTypeEnum.MYBATIS; } }
@Component public class JpaManufacturerHandler implements ManufacturerPersistenceHandler { @Autowired private ManufacturerRepository manufacturerRepository; @Override public Manufacturer save(Manufacturer manufacturer) { return manufacturerRepository.save(manufacturer); } @Override public PersistenceTypeEnum getType() { return PersistenceTypeEnum.JPA; } }
- Service中注入所有处理器,根据参数选择对应实现
@Service public class ManufacturerService implements IManufacturerService { // Spring会自动注入所有实现了ManufacturerPersistenceHandler的Bean @Autowired private List<ManufacturerPersistenceHandler> handlerList; private Map<PersistenceTypeEnum, ManufacturerPersistenceHandler> handlerMap; // 初始化后将处理器转成Map方便查找 @PostConstruct public void initHandlerMap() { handlerMap = handlerList.stream() .collect(Collectors.toMap(ManufacturerPersistenceHandler::getType, Function.identity())); } @Override @Transactional public Manufacturer save(Manufacturer manufacturer, String persistenceType) { PersistenceTypeEnum type = PersistenceTypeEnum.valueOf(persistenceType.toUpperCase()); ManufacturerPersistenceHandler handler = handlerMap.get(type); if (handler == null) { throw new RuntimeException("不支持的持久化类型:" + persistenceType); } return handler.save(manufacturer); } }
后续新增持久化实现只需要新增对应处理器类即可,无需修改原有Service逻辑。
内容的提问来源于stack exchange,提问作者KG_stackoverflow
相关产品推荐
相关产品推荐

