wake-up-neo.com

Beste Methode zum Behandeln der Vererbung von Entitäten in Spring Data JPA

Ich habe drei JPA-Entität Klassen A, B und C mit der folgenden Hierarchie:

    A
    |
+---+---+
|       |
C       B

Das ist:

@Entity
@Inheritance
public abstract class A { /* ... */ }

@Entity
public class B extends A { /* ... */ }

@Entity
public class C extends A { /* ... */ }

Mit Spring Data JPA, wie schreibt man Repositorys Klassen für solche Entitäten am besten?

Ich weiß, dass ich diese schreiben kann:

public interface ARespository extends CrudRepository<A, Long> { }

public interface BRespository extends CrudRepository<B, Long> { }

public interface CRespository extends CrudRepository<C, Long> { }

aber wenn es in der Klasse A ein Feld name gibt und ich diese Methode im ARepository hinzufüge:

public A findByName(String name);

Ich muss eine solche Methode auch in die anderen beiden Repositories schreiben, und das ist ein bisschen nervig. Gibt es eine bessere Möglichkeit, mit einer solchen Situation umzugehen?

Ein weiterer Punkt, den ich gerne hätte, ist, dass ARespository ein schreibgeschütztes Repository sein sollte (d. H. Die Klasse Repository erweitern), während die beiden anderen Repositorys alle CRUD-Operationen offen legen sollten.

Lassen Sie mich mögliche Lösungen wissen.

42
Andrea

Ich habe die Lösung verwendet, die auch in diesem Beitrag aus Netgloos Blog beschrieben ist.

Die Idee ist, eine generische Repository-Klasse wie die folgende zu erstellen:

@NoRepositoryBean
public interface ABaseRepository<T extends A> 
extends CrudRepository<T, Long> {
  // All methods in this repository will be available in the ARepository,
  // in the BRepository and in the CRepository.
  // ...
}

dann kann ich die drei repositories so schreiben:

@Transactional
public interface ARepository extends ABaseRepository<A> { /* ... */ }

@Transactional
public interface BRepository extends ABaseRepository<B> { /* ... */ }

@Transactional
public interface CRepository extends ABaseRepository<C> { /* ... */ }

Um ein schreibgeschütztes Repository für ARepository zu erhalten, kann ABaseRepository als schreibgeschützt definiert werden:

@NoRepositoryBean
public interface ABaseRepository<T> 
extends Repository<T, Long> {
  T findOne(Long id);
  Iterable<T> findAll();
  Iterable<T> findAll(Sort sort);
  Page<T> findAll(Pageable pageable);
}

und erweitern Sie von BRepository auch die CrudRepository der JPA für Spring-Daten, um ein Lese-/Schreib-Repository zu erhalten:

@Transactional
public interface BRepository 
extends ABaseRepository<B>, CrudRepository<B, Long> 
{ /* ... */ }
53
Andrea