Spring Data JPA自定义Repository向上转型失败 构造器注入报错
编译错误根因
报错和接口向上转型逻辑无关,核心原因是Java泛型默认不支持协变,且代码泛型参数类型不匹配:
- 自定义
CustomRepository继承AbstractRepository时,指定的ID泛型为Integer:extends abstractRepository<classThatExtendSomeEntity, Integer> - 抽象父类
AbstractService中声明的Repository字段、构造器入参,都要求ID泛型固定为Long:AbstractRepository<Entity,Long>
编译期AbstractRepository<XXX, Integer>和AbstractRepository<XXX, Long>是完全独立的两种类型,不存在继承关系,因此无法作为参数传入要求后者类型的构造方法。
修复方案
二选一即可,优先推荐方案1,灵活性更高:
方案1:抽象类增加ID泛型参数,避免写死类型
将AbstractService的ID类型也声明为泛型参数,不再硬编码为Long,子类继承时传入和Repository一致的ID类型即可。
修改后的AbstractService代码:
@Service @Transactional public abstract class AbstractService<Entity extends someEntity, DTO extends someDTO, ID> implements ComboWithSubproductsService<DTO>{ protected AbstractRepository<Entity, ID> genericRepository; @Autowired public AbstractService(AbstractRepository<Entity, ID> repository) { this.genericRepository = repository; } }
修改后的customServiceImpl代码,继承时指定ID类型为Integer,和CustomRepository的泛型对齐:
@Service @Transactional public class customServiceImpl extends abstractService<classThatExtendSomeClass, classThatExtendsSomeDTO, Integer> implements customService{ private final CustomRepository repository; public customServiceImpl (customRepository repository) { super(repository); this.repository = repository; } }
方案2:对齐Repository的ID泛型类型
如果业务中所有实体主键统一使用Long类型,直接修改CustomRepository的声明,将ID泛型从Integer改为Long即可:
@Repository public interface customRepository extends abstractRepository<classThatExtendSomeEntity, Long> { }
注意事项
不要为了快速消错在泛型中使用通配符? extends Long来绕过编译检查,这种写法会导致后续Repository的写操作出现类型安全问题,留下运行时隐患。
内容的提问来源于stack exchange,提问作者roberto fernandez
相关产品推荐
相关产品推荐

