能否创建抽象类封装通用CRUD逻辑,让Service直接继承复用?
通用CRUD服务的实现方案
做完几个入门级项目后,我发现所有业务Service都围绕CRUD操作展开,因此想通过泛型封装通用CRUD逻辑,避免重复编写代码。以下是具体实现思路和优化后的代码:
核心设计逻辑
- 定义泛型通用Service接口,统一CRUD方法规范
- 基于JPA封装泛型Repository,复用JPA的持久层能力
- 抽象类实现通用Service接口,封装CRUD基础逻辑
- 业务Service继承抽象类,直接复用父类逻辑,按需扩展自定义业务
代码实现
1. 通用Service接口
public interface BasicService<T> { T add(T model); T update(T model, int id); void delete(int id); T getById(int id); }
2. 通用Repository接口
@Repository public interface BasicRepository<T> extends JpaRepository<T, Integer> { }
3. 业务Service接口
public interface CarService extends BasicService<Car> { // 可在此定义Car业务特有的方法 }
4. 通用Service抽象实现类
这里修正了原代码中的语法错误,并补充了数据存在性校验,避免无意义操作或意外新增数据:
public abstract class BasicServiceImpl<T> implements BasicService<T> { private final BasicRepository<T> basicRepository; public BasicServiceImpl(BasicRepository<T> basicRepository) { this.basicRepository = basicRepository; } @Override public T getById(int id) { // 数据不存在时抛出异常,可根据业务调整为返回null或自定义异常 return basicRepository.findById(id) .orElseThrow(() -> new RuntimeException("请求的数据不存在")); } @Override @Transactional public void delete(int id) { // 先校验数据存在,再执行删除 if (basicRepository.existsById(id)) { basicRepository.deleteById(id); } } @Override @Transactional public T update(T model, int id) { // 校验待更新数据存在,避免save操作变为新增 if (!basicRepository.existsById(id)) { throw new RuntimeException("待更新的数据不存在"); } return basicRepository.save(model); } @Override @Transactional public T add(T model) { return basicRepository.save(model); } }
5. 业务Service实现类
修正了原代码的语法错误,并且如果不需要自定义逻辑,无需重写父类方法:
@Service public class CarServiceImpl extends BasicServiceImpl<Car> implements CarService { // 注入业务专属Repository,父类会自动使用它处理CRUD public CarServiceImpl(CarRepository carRepository) { super(carRepository); } // 仅当需要自定义Car业务逻辑时才重写方法,例如: // @Override // public Car add(Car model) { // // 新增前校验品牌不能为空 // if (model.getBrand() == null || model.getBrand().trim().isEmpty()) { // throw new RuntimeException("车辆品牌不能为空"); // } // return super.add(model); // } }
优化建议
- 自定义异常:替换代码中的
RuntimeException为自定义业务异常,便于统一异常处理 - 泛型主键:将主键类型也设为泛型(如
BasicService<T, ID>),适配Long、String等不同主键类型 - 分页与条件查询:在
BasicService中添加分页、条件查询方法,进一步提升通用性 - 参数校验:新增/更新方法中加入
@Valid注解,结合JSR-380实现参数合法性校验
内容的提问来源于stack exchange,提问作者KingNotJoke
相关产品推荐
相关产品推荐

