Maven接口方法之间的模糊参考

时间:2017-10-28 17:17:41

标签: java maven jpa repository

我有一个使用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执行此操作的修复程序?还是有另一种方法来编码我想要做的事情吗?

1 个答案:

答案 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(),但实现的细节隐藏在实现类中。

如果有人有更好的解决方案,只需要极少量的代码,我就有兴趣了解它。