Problem: Mehrere Datenbankzugriffe bei Join-Tabellen notwendig

JPA ist eine weitverbreitete Schnittstelle für Datenbankzugriffe und objektrelationales Mapping (ORM). Mit Hilfe der Annotationen @ManyToMany und @JoinTable können n:m-Beziehungen zwischen Datenbank-Tabellen komfortabel, schnell und lesbar beschrieben werden. Aufgrund dieser Beschreibung existiert jedoch keine eigene Java-Klasse der Join-Tabelle, was dazu führt, dass zuerst alle Objekte des „linken“ Teils der Join-Tabelle abgerufen werden müssen, bevor über Lazy-Loading der „rechte“-Teil aggregiert werden kann, um letztlich die Information der Join-Tabelle verwenden zu können.

Lösung: JPQL Projection

JPQL kann bei SELECT-Abfragen mit Hilfe des Schlüsselworts NEW und der Angabe eines Konstruktors pro Datensatz ein Objekt erstellen, wodurch es möglich ist, die Join-Tabelle mit EINEM Datenbankzugriff zu erhalten. Das heißt, es wird eine Projektion von Tabellen-Spalten auf ein Objekt durchgeführt.

Beispiel

Ein Projekt hat mehrere Mitarbeitende und jede*r kann in mehreren Projekten arbeiten.

1)
@Entity
public class Project {
    @Id @Column(name = "ID")
    private long id;
 
    @ManyToMany @JoinTable(name = "PROJECT_EMPLOYEE",
      joinColumns = @JoinColumn(name = "PROJECT_ID", referencedColumnName = "ID"),
      inverseJoinColumns = @JoinColumn(name = "EMPLOYEE_ID", referencedColumnName = "ID"))
    private List<Employee> employees;
}
@Entity
public class Employee {
    @Id @Column(name = "ID")
    private long id;
 
    @ManyToMany(mappedBy = "employees")
    private List<Project> projects;
}
2)
public class JoinTable {
    private long projectId, employeeId;
 
    public JoinTable(long projectId, long employeeId) {
        this.projectId = projectId; this.employeeId = employeeId;
    }
}
// Spring Data
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface ProjectRepository extends JpaRepository<Project, Long> {
    @Query("SELECT NEW com.jambit.toiletpaper.JoinTable(p.id, e.id) FROM Project p " +
            "JOIN p.employees e WHERE p.id = ?1")
    List<JoinTable> getAllJoinTableById(long id);
}

Weiterführende Aspekte

---

Autor: Matthias Mair / Senior Software Architect / Business Division Automotive Bavaria

Zum Toilet Paper #116: SELECT n:m-Tabellen mit JPQL Projection (pdf)

SELECT n:m-Tabellen mit JPQL Projection

SCHREIB UNS

* Pflichtfeld

SCHREIB UNS

* Pflichtfeld

Cookie-Einstellungen

Diese Website verwendet Cookies, um Inhalte und Anzeigen zu personalisieren, Funktionen für soziale Medien anbieten zu können und Zugriffe auf die Website zu analysieren. Zudem werden Informationen zu Ihrer Verwendung der Website an Partner für soziale Medien, Werbung und Analysen weitergegeben. Die Partner führen diese Informationen möglicherweise mit weiteren Daten zusammen, die Sie ihnen bereitgestellt haben oder die sie im Rahmen Ihrer Nutzung der Dienste gesammelt haben.

Weitere Informationen finden Sie in unserer Datenschutzerklärung. Dort können Sie nachträglich auch Ihre Cookie-Einstellungen ändern.

contact icon

Kontakt aufnehmen