Spring Data JPA - Hinzufügen einer Methode in allen Repositorys

Spring Data JPA - Hinzufügen einer Methode in allen Repositorys

1. Überblick

Spring Data vereinfacht die Arbeit mit Entitäten erheblich, indem lediglich Repository-Schnittstellen definiert werden. Diese kommen mit einer Reihe von vordefinierten Methoden und ermöglichen das Hinzufügen von benutzerdefinierten Methoden in jeder Schnittstelle.

Wenn Sie jedoch eine benutzerdefinierte Methode hinzufügen möchten, die in allen Repositorys verfügbar ist, ist der Prozess etwas komplexer. Das werden wir hier mit Spring Data JPA untersuchen.

Weitere Informationen zum Konfigurieren und Verwenden von Spring Data JPA finden Sie in unseren vorherigen Artikeln:Guide to Hibernate with Spring 4 undIntroduction to Spring Data JPA.

2. Definieren einer Basis-Repository-Schnittstelle

Zuerst müssen wir eine neue Schnittstelle erstellen, die unsere benutzerdefinierte Methode deklariert:

@NoRepositoryBean
public interface ExtendedRepository
  extends JpaRepository {

    public List findByAttributeContainsText(String attributeName, String text);
}

Unsere Schnittstelle erweitert dieJpaRepository-Schnittstelle, sodass wir vom gesamten Standardverhalten profitieren.

Sie werden auch feststellen, dass wir die Annotation@NoRepositoryBeanhinzugefügt haben. Dies ist erforderlich, da ansonsten das Standardverhalten von Spring darin besteht, eine Implementierung für alle Subschnittstellen vonRepository. zu erstellen

Hier möchten wir unsere Implementierung bereitstellen, die verwendet werden sollte, da dies nur eine Schnittstelle ist, die durch die tatsächlichen entitätsspezifischen DAO-Schnittstellen erweitert werden soll.

3. Implementieren einer Basisklasse

Als Nächstes stellen wir unsere Implementierung derExtendedRepository-Schnittstelle bereit:

public class ExtendedRepositoryImpl
  extends SimpleJpaRepository implements ExtendedRepository {

    private EntityManager entityManager;

    public ExtendedRepositoryImpl(JpaEntityInformation
      entityInformation, EntityManager entityManager) {
        super(entityInformation, entityManager);
        this.entityManager = entityManager;
    }

    // ...
}

Diese Klasse erweitert dieSimpleJpaRepository-Klasse. Dies ist die Standardklasse, mit der Spring Implementierungen für Repository-Schnittstellen bereitstellt.

Dies erfordert, dass wir einen Konstruktor mit den ParameternJpaEntityInformation undEntityManager erstellen, der den Konstruktor aus der übergeordneten Klasse aufruft.

Wir benötigen auch die EigenschaftEntityManager, um sie in unserer benutzerdefinierten Methode verwenden zu können.

Außerdem müssen wir die benutzerdefinierte Methode implementieren, die von derExtendedRepository-Schnittstelle geerbt wurde:

@Transactional
public List findByAttributeContainsText(String attributeName, String text) {
    CriteriaBuilder builder = entityManager.getCriteriaBuilder();
    CriteriaQuery cQuery = builder.createQuery(getDomainClass());
    Root root = cQuery.from(getDomainClass());
    cQuery
      .select(root)
      .where(builder
        .like(root.get(attributeName), "%" + text + "%"));
    TypedQuery query = entityManager.createQuery(cQuery);
    return query.getResultList();
}

Hier sucht die MethodefindByAttributeContainsText()nach allen Objekten vom Typ T, die ein bestimmtes Attribut haben, das den als Parameter angegebenen Wert vonStringenthält.

4. JPA-Konfiguration

Um Spring anzuweisen, unsere benutzerdefinierte Klasse anstelle der Standardklasse zum Erstellen von Repository-Implementierungen zu verwenden,we can use the repositoryBaseClass attribute:

@Configuration
@EnableJpaRepositories(basePackages = "org.example.persistence.dao",
  repositoryBaseClass = ExtendedRepositoryImpl.class)
public class StudentJPAH2Config {
    // additional JPA Configuration
}

5. Erstellen eines Entitätsrepositorys

Als nächstes wollen wir sehen, wie wir unsere neue Benutzeroberfläche verwenden können.

Fügen wir zunächst eine einfacheStudent-Entität hinzu:

@Entity
public class Student {

    @Id
    private long id;
    private String name;

    // standard constructor, getters, setters
}

Dann können wir ein DAO für die EntitätStudenterstellen, das die SchnittstelleExtendedRepositoryerweitert:

public interface ExtendedStudentRepository extends ExtendedRepository {
}

Und das ist es! Jetzt wird unsere Implementierung die benutzerdefiniertefindByAttributeContainsText()-Methode haben.

In ähnlicher Weise hat jede Schnittstelle, die wir durch Erweitern derExtendedRepository-Schnittstelle definieren, dieselbe Methode.

6. Repository testen

Erstellen wir einenJUnit-Test, der die benutzerdefinierte Methode in Aktion zeigt:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { StudentJPAH2Config.class })
public class ExtendedStudentRepositoryIntegrationTest {

    @Resource
    private ExtendedStudentRepository extendedStudentRepository;

    @Before
    public void setup() {
        Student student = new Student(1, "john");
        extendedStudentRepository.save(student);
        Student student2 = new Student(2, "johnson");
        extendedStudentRepository.save(student2);
        Student student3 = new Student(3, "tom");
        extendedStudentRepository.save(student3);
    }

    @Test
    public void givenStudents_whenFindByName_thenOk(){
        List students
          = extendedStudentRepository.findByAttributeContainsText("name", "john");

        assertEquals("size incorrect", 2, students.size());
    }
}

Der Test verwendet zuerst die BeanextendedStudentRepository, um 3 Studentendatensätze zu erstellen. Dann wird die MethodefindByAttributeContains()aufgerufen, um alle Schüler zu finden, deren Name den Text „john“ enthält.

Die KlasseExtendedStudentRepository kann sowohl Standardmethoden wiesave() als auch die von uns hinzugefügte benutzerdefinierte Methode verwenden.

7. Fazit

In diesem kurzen Artikel haben wir gezeigt, wie wir allen Repositorys in Spring Data JPA eine benutzerdefinierte Methode hinzufügen können.

Den vollständigen Quellcode für die Beispiele finden Sie inover on GitHub.