jambit ToiletPaper #116

SELECT n:m-Tabellen mit JPQL Projection

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 Mitarbeiter und ein Mitarbeiter 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

Wir verwenden Cookies, um unsere Webseite für Sie zu optimieren. Mit dem Besuch unserer Webseite erklären Sie sich damit einverstanden. // Our website is using cookies to improve your experience. By continuing to browse the site, you are agreeing to our use of cookies.

Weitere Informationen finden Sie in unserer Datenschutzerklärung. // For more information, please refer to our privacy policy.