我有一个使用EclipseLink的JPA持久化Java Spring项目。我想为我的实体使用JpaRepository接口和大多数情况下的默认实现,但我还需要定义一些自己的方法,我有时需要覆盖默认方法,如save。
我的代码在Eclipse中编译时可以正常工作,但在使用Maven进行编译时,我仍然遇到一个模糊的引用错误。
我所做的就是这个(例如覆盖保存,因为我需要对要保存的实体做某些事情):
public interface ReportRepository extends JpaRepository<Report, Long>, ReportRepositoryCustom {
}
public interface ReportRepositoryCustom {
public Report save(Report report);
public int getReportCountForImporter(Long importerId);
...
}
public class ReportRepositoryCustomImplementation implements ReportRepositoryCustom {
public Report save(Report report) { ... }
public int getReportCountForImporter(Long importerId) { ... }
}
public class ReportService {
@Autowired
private ReportRepository reportRepository;
}
当我编译它以在Tomcat上运行时,这在Eclipse中工作正常。 ReportRepository reportRepository对象具有JPA存储库实现和自定义方法的方法,并且在调用reportRepository.save(...)时调用自定义save方法。但是,当我执行Maven Install时,编译器会抱怨模糊引用:
[ERROR] /C:/Users/Jarno/git/Korjaamotestiraportointi/src/main/java/fi/testcenter/service/ReportService.java:[40,40] 保存参考是两种方法都不明确 保存(fi.testcenter.domain.report.Report)in fi.testcenter.repository.ReportRepositoryCustom和方法save(S) 在org.springframework.data.repository.CrudRepository中匹配
我发现我的存储库编码有点复杂。我想使用JPA存储库的现成实现,而不必编写任何额外的代码。我的代码保持一切美观干净。在服务中用作引用的存储库接口以相同的方式命名为每个实体,并且方法也被命名为相同,并且任何自定义方法或覆盖都是通过自定义接口和实现完成的。我不需要在任何地方编写任何不必要的代码。但后来我遇到了Maven的问题。
我已经设法使用Maven编译我的代码,首先在Eclipse Tomcat服务器中运行它。但如果我做Maven Clean然后Maven Install,我会收到一堆错误。显然,我不想在与Maven编译时采用任何形式的黑客攻击。
那么是否有一个可以通过Maven执行此操作的修复程序?还是有另一种方法来编码我想要做的事情吗?
答案 0 :(得分:2)
所以经过大量的谷歌搜索等等,似乎没有可能为Maven编译器定义哪些保存方法是主要的,JpaRepository中的那个或我的自定义存储库中的那个。我不知道Eclipse使用的编译器是如何做到的,但显然Maven并没有遵循相同的逻辑。这是一种耻辱,因为这种编写自定义方法和覆盖一些JpaRepository方法的方式将是最干净和最好的方式。如果存在多个候选者,则有一个@Primary注释用于确定哪个bean是自动装配的主要注释,但似乎并不是接口实现方法的等效解决方案。我没有找到任何其他方式来做这个,我不必编写任何额外的代码。扩展SimpleJpaRepository类似乎有点难看,因为我必须确保将实现用作JpaRepository实现。
所以我决定以直截了当的方式解决这个问题:
public interface ReportRepository {
public List<Report> findAll();
public Report findOne(Long id);
public void delete(Report report);
public Report save(Report report) throws OptimisticLockException;
public Long getReportCountForImporter(Long importerId);
.... [other custom methods]
}
public interface ReportRepositoryDefaultMethods extends JpaRepository<Report, Long> {
}
public class ReportRepositoryImpl implements ReportRepository {
@PersistenceContext()
EntityManager entityManager;
@Autowired
ReportRepositoryDefaultMethods reportRepositoryDefaultMethods;
public List<Report> findAll() {
return reportRepositoryDefaultMethods.findAll();
}
public Report findOne(Long id) {
return reportRepositoryDefaultMethods.findOne(id);
}
public void delete(Report report) {
reportRepositoryDefaultMethods.delete(report);
}
@Transactional
public Report save(Report report) throws OptimisticLockException {
[custom implementation using entityManager methods]
}
.... [other custom methods]
}
它不是一个简洁的解决方案,因为我必须包含我在我的界面及其实现中使用的默认方法,只需调用标准的JpaRepository方法。但它的工作原理和我的ReportRepository接口的使用是干净的,因为我没有自定义方法的自定义名称,如customSave(),但实现的细节隐藏在实现类中。
如果有人有更好的解决方案,只需要极少量的代码,我就有兴趣了解它。