2017-10-28 4 views
0

Ich habe ein Java-Spring-Projekt mit JPA-Persistenz mit EclipseLink. Ich möchte JpaRepository-Schnittstellen für meine Entitäten und die Standardimplementierungen für die meisten Fälle verwenden, aber ich muss auch einige meiner eigenen Methoden definieren, und ich muss manchmal die Standardmethoden wie Speichern überschreiben.Maven mehrdeutige Referenz zwischen Interface-Methoden

Mein Code funktioniert, wenn in Eclipse kompiliert, aber ich bekomme immer einen mehrdeutigen Referenzfehler beim Kompilieren mit Maven.

Was ich getan habe ist dies (zB speichern außer Kraft zu setzen, weil ich brauche bestimmte Dinge an das Unternehmen zu tun, um gerettet zu werden):

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; 
} 

Diese feine in Eclipse funktioniert, wenn ich es kompilieren auf denen sie laufen Kater. Das Objekt ReportRepository reportRepository verfügt über Methoden aus der JPA-Repository-Implementierung und meinen eigenen Methoden. Die benutzerdefinierte Save-Methode wird aufgerufen, wenn ich reportRepository.save (...) aufruft. Allerdings, wenn ich Maven installiere, beschwert sich der Compiler eine unklare Referenz:

[ERROR] /C:/Users/Jarno/git/Korjaamotestiraportointi/src/main/java/fi/Testcenter/service/ReportService.java:[40,40] Referenz zu speichern ist mehrdeutig beide Methode Speichern (fi.testcenter.domain.report.Report) in fi.testcenter.repository.ReportRepositoryCustom und Methode speichern (S) in org.springframework .data.repository.CrudRepository Übereinstimmung

Ich habe die Codierung meiner Repositories ein wenig kompliziert gefunden. Ich möchte die vorgefertigten Implementierungen für JPA-Repositories verwenden und muss nichts extra programmieren. Mein Code hält alles schön und sauber. Die Repository-Schnittstelle, die als Referenz in Services verwendet werden soll, wird für jede Entität auf dieselbe Weise benannt, und Methoden werden auch gleich benannt, und benutzerdefinierte Methoden oder Außerkraftsetzungen werden über benutzerdefinierte Schnittstellen und Implementierungen ausgeführt. Ich muss nirgendwo unnötigen Code schreiben. Aber dann stieß ich auf mein Problem mit Maven.

Ich habe es geschafft, meinen Code mit Maven zu kompilieren, indem ich ihn zuerst in Eclipse Tomcat Server laufen lasse. Aber wenn ich Maven Clean und dann Maven Install mache, bekomme ich eine Reihe von Fehlern. Und ich möchte natürlich nicht auf irgendeinen Hack zurückgreifen müssen, um Maven zu kompilieren.

Also gibt es eine Lösung, die dies mit Maven tun würde? Oder gibt es eine andere Art zu kodieren, was ich hier machen möchte?

+0

[Spring JPA CrudRepsoitory Klasse haben bereits speichern Methode] (https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/repository/CrudRepository.html#save- S-), warum benennst du deine eigene Signatur? –

+0

@Sagar Rohankar Die Standardmethode überschreiben, weil ich bestimmte Dinge vor dem Speichern der Entität in der Datenbank tun muss. Ich möchte die Methode nicht anders benennen und muss daran denken, dass ich für bestimmte Entitäten eine benutzerdefinierte Methode mit einem anderen Namen als save aufrufen muss. – hubbabubba

+0

dann erweitern Sie 'ReportRepositoryCustom' in' ReportRepository' nicht. –

Antwort

0

So nach vielen Googeln und so weiter, scheint es nicht möglich, für Maven Compiler zu definieren, welche der Speichermethoden primär ist, die in JpaRepository oder die in meinem benutzerdefinierten Repository. Ich weiß nicht, wie der von Eclipse verwendete Compiler es tut, aber Maven folgt hier nicht der gleichen Logik. Das ist eine Schande, denn diese Art, benutzerdefinierte Methoden zu schreiben und einige JpaRepository-Methoden zu überschreiben, wäre der sauberste und netteste Weg. Es gibt eine @ Primary-Annotation, um zu ermitteln, welche Bean für das Autowiring primär ist, wenn mehrere Kandidaten existieren, aber es scheint keine äquivalente Lösung für Schnittstellenimplementierungsmethoden zu geben. Ich habe keine andere Möglichkeit gefunden, dies zu tun, wo ich keinen zusätzlichen Code schreiben müsste. Die Erweiterung der SimpleJpaRepository-Klasse scheint eine etwas hässliche Lösung zu sein, da ich dann sicherstellen müsste, dass die Implementierung als JpaRepository-Implementierung verwendet wird.

Also habe ich beschlossen, dass dies in einem geraden Weg nach vorn zu lösen:

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] 
} 

Es ist keine saubere Lösung, da ich die Standardmethoden umfassen muß ich in meiner Schnittstelle und deren Umsetzung zu verwenden, mit nur Anrufen zu den Standard-JpaRepository-Methoden. Aber es funktioniert und die Verwendung meiner ReportRepository-Schnittstelle ist insofern sauber, als ich keine benutzerdefinierten Namen für benutzerdefinierte Methoden wie customSave() habe, aber die Details der Implementierung sind in der implementierenden Klasse verborgen.

Wenn jemand eine bessere Lösung hat, eine mit nur minimaler Menge an Code, würde mich das interessieren.

Verwandte Themen