【问题标题】:Maven ambiguous reference between interface methods接口方法之间的Maven模糊引用
【发布时间】:2018-04-10 02:02:50
【问题描述】:

我有一个使用 EclipseLink 的具有 JPA 持久性的 Java Spring 项目。我想为我的实体使用 JpaRepository 接口,并在大多数情况下使用默认实现,但我还需要定义一些我自己的方法,有时我需要覆盖默认方法,如保存。

我的代码在 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(...) 时会调用自定义保存方法。但是,当我执行 Maven 安装时,编译器会抱怨引用不明确:

[错误] /C:/Users/Jarno/git/Korjaamotestiraportointi/src/main/java/fi/testcenter/service/ReportService.java:[40,40] 对保存的引用是不明确的两种方法 保存(fi.testcenter.domain.report.Report)在 fi.testcenter.repository.ReportRepositoryCustom 和方法 save(S) 在 org.springframework.data.repository.CrudRepository 匹配

我发现对我的存储库进行编码有点复杂。我想为 JPA 存储库使用现成的实现,而不必编写任何额外的代码。我的代码使一切保持整洁。在服务中用作引用的存储库接口对每个实体都以相同的方式命名,方法也以相同的方式命名,并且任何自定义方法或覆盖都是通过自定义接口和实现完成的。我不需要在任何地方编写任何不必要的代码。但后来我遇到了 Maven 的问题。

我首先在 Eclipse Tomcat 服务器中运行了 Maven,从而成功地编译了我的代码。但是,如果我执行 Maven Clean 然后执行 Maven Install,我会收到一堆错误。显然,我不想在使用 Maven 编译时使用任何黑客手段。

那么,是否有允许使用 Maven 执行此操作的修复程序?还是有另一种编码方式我想在这里做什么?

【问题讨论】:

  • Spring JPA CrudRepsoitory class already have save method,为什么要定义自己的签名?
  • @Sagar Rohankar 覆盖默认方法,因为在将实体保存到数据库之前我需要做一些事情。我不想以不同的方式命名该方法,并且必须记住,对于某些实体,我需要使用 save 以外的名称调用自定义方法。
  • 那么不要在ReportRepository接口中扩展ReportRepositoryCustom
  • 这样做的原因是,当 reportRepository 自动装配时,它具有来自默认 JpaRepository 实现的方法,如删除和我的自定义方法。两者都是需要的。但是 Mavens 编译器被两个具有相同签名的方法弄糊涂了,我不知道有没有办法解决这个问题。
  • 可能是这样的帮助:stackoverflow.com/questions/13036159/…

标签: java maven jpa repository


【解决方案1】:

所以经过大量的谷歌搜索等之后,似乎无法为 Maven 的编译器定义哪个保存方法是主要的,JpaRepository 中的那个还是我的自定义存储库中的那个。我不知道 Eclipse 使用的编译器是如何做到的,但显然 Maven 在这里没有遵循相同的逻辑。这是一种耻辱,因为这种编码自定义方法和覆盖一些 JpaRepository 方法的方式将是最干净和最好的方式。如果存在多个候选者,则有一个 @Primary 注释用于确定哪个 bean 是自动装配的主要 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())的自定义名称,但实现的细节隐藏在实现类中。

如果有人有更好的解决方案,只需最少的代码,我很想听听。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多