SpringBoot中如何从Repository实现类调用默认save方法?
SpringBoot中MongoRepository实现类调用标准save方法编译失败的解决办法
问题分析
你在自定义FileInfoRepoImpl实现类时,尝试通过FileInfoRepo.super.save(entity)调用接口的save方法编译失败,核心原因有两点:
- Spring Data的
MongoRepository接口中的save方法并非Java 8默认方法,而是由Spring框架动态生成代理实现的,接口本身没有提供可直接调用的默认实现代码。 - Java语法规则限制:实现类仅能调用自身直接实现的接口中定义的默认方法,无法通过父接口(如
MongoRepository)的super语法调用其方法,更别说这种无默认实现的Spring Data方法。
解决方案
方案一:继承SimpleMongoRepository(推荐)
Spring Data MongoDB提供了SimpleMongoRepository作为MongoRepository的官方默认实现类,自定义实现类继承它后,可直接通过super.save(entity)调用标准save逻辑,同时保留自定义方法。
修改后的FileInfoRepoImpl代码:
@Repository public class FileInfoRepoImpl extends SimpleMongoRepository<FileInfo, String> implements FileInfoRepo { private final MongoTemplate mongoTemplate; // 构造方法注入(Spring 4.3+推荐写法,替代@Autowired) public FileInfoRepoImpl(MongoEntityInformation<FileInfo, String> entityInformation, MongoTemplate mongoTemplate) { super(entityInformation, mongoTemplate); this.mongoTemplate = mongoTemplate; } @Override public UpdateResult updateFileInfo(FileInfo fileInfo) { Query query = new Query(Criteria.where("id").is(fileInfo.getId())); Update update = new Update(); update.set("name", fileInfo.getName()); update.set("size", fileInfo.getSize()); update.set("contentType", fileInfo.getContentType()); return mongoTemplate.updateFirst(query, update, FileInfo.class); } // 重写save方法时,直接调用父类实现 @Override public <S extends FileInfo> S save(S entity) { // 可在此添加自定义前置/后置逻辑 // ... return super.save(entity); } }
方案二:直接用MongoTemplate实现save逻辑
若不想继承官方实现类,可利用已注入的MongoTemplate手动实现save逻辑,和Spring Data底层逻辑保持一致:
@Repository public class FileInfoRepoImpl implements FileInfoRepo { @Autowired MongoTemplate mongoTemplate; @Override public UpdateResult updateFileInfo(FileInfo fileInfo) { Query query = new Query(Criteria.where("id").is(fileInfo.getId())); Update update = new Update(); update.set("name", fileInfo.getName()); update.set("size", fileInfo.getSize()); update.set("contentType", fileInfo.getContentType()); return mongoTemplate.updateFirst(query, update, FileInfo.class); } @Override public <S extends FileInfo> S save(S entity) { if (entity.getId() == null || entity.getId().isEmpty()) { // 新增数据 mongoTemplate.insert(entity); } else { // 更新数据 mongoTemplate.save(entity); } return entity; } // 注意:需实现MongoRepository中所有未实现的方法,否则会抛出未实现异常 }
额外优化建议
你在FileInfoRepo中定义的updateFileInfo方法,其实可以通过Spring Data的注解直接生成实现,无需手动编写实现类:
public interface FileInfoRepo extends MongoRepository<FileInfo, String> { List<FileInfo> findByName(String name); @Query("{ 'id' : ?0 }") @Update("{ '$set' : { 'name' : ?1, 'size' : ?2, 'contentType' : ?3 } }") UpdateResult updateFileInfo(String id, String name, long size, String contentType); }
这种方式下,Spring会自动生成方法实现,省去自定义实现类的麻烦。
内容的提问来源于stack exchange,提问作者Papp Zoltán
相关产品推荐
相关产品推荐

