Das Abrufen durch Angabe nur einer bestimmten Spalte in der SELECT-Klausel wird als Projektion bezeichnet. Wenn es jedoch unpraktisch ist, alle Spalten abzurufen (es gibt zu viele Spalten, gibt es große Spalten, z. B. LOBs). Dies ist eine bequeme Methode.
Dieses Mal werde ich erklären, wie die Projektion mit der Kriterien-API von Doma ausgedrückt wird.
Es gibt zwei Möglichkeiten, um mit der Kriterien-API eine Projektion zu erzielen.
Die hier verwendete Version von Doma ist 2.43.0.
Eine Übersicht über Doma und die Kriterien-API finden Sie in den anderen Artikeln unter Einführung in Doma.
Ich werde es mit einem vereinfachten Code erklären. Im vollständigen Projekt finden Sie den vollständigen Beispielcode.
Die Datenbank verfügt über eine Mitarbeitertabelle, die Mitarbeiter darstellt.
schema.sql
create table employee (
id integer not null primary key,
name varchar(255) not null,
age integer not null,
salary integer,
job_type varchar(20),
hiredate timestamp,
department_id integer,
version integer not null,
insertTimestamp timestamp,
updateTimestamp timestamp);
Bereiten Sie die Employee-Klasse vor, die der Employee-Tabelle entspricht.
Employee.java
@Entity(metamodel = @Metamodel)
public class Employee {
@Id
Integer id;
String name;
Age age;
Salary salary;
@Column(name = "JOB_TYPE")
JobType jobType;
LocalDate hiredate;
@Column(name = "DEPARTMENT_ID")
Integer departmentId;
@Version
@Column(name = "VERSION")
Integer version;
LocalDateTime insertTimestamp;
LocalDateTime updateTimestamp;
// getter, setter
}
Bereiten Sie ein DTO (ValueObject) vor, das das projizierte Ergebnis enthält.
NameAndSalaryDto.java
public class NameAndSalaryDto {
private final String name;
private final Salary salary;
public NameAndSalaryDto(String name, Salary salary) {
this.name = name;
this.salary = salary;
}
// getter
}
Wir werden "EmployeeRepository" vorbereiten und dieser Klasse einige Methoden hinzufügen, um ein Beispiel zu zeigen.
EmployeeRepository.java
public class EmployeeRepository {
private final Entityql entityql;
private final NativeSql nativeSql;
public EmployeeRepository(Config config) {
this.entityql = new Entityql(config);
this.nativeSql = new NativeSql(config);
}
}
Dies ist eine sehr bequeme Methode in dem Sinne, dass Sie vorhandene Datenstrukturen wiederverwenden können.
Mit der Methode selectTo
können Sie den projizierten Wert auf eine bestimmte Eigenschaft der Entität festlegen (andere Eigenschaften werden auf Null oder Anfangswerte festgelegt).
public List<Employee> selectNameAndSalaryAsEntityList() {
Employee_ e = new Employee_();
return entityql.from(e).selectTo(e, e.name, e.salary).fetch();
}
Die ausgegebene SQL lautet wie folgt.
select t0_.id, t0_.name, t0_.salary from Employee t0_
Die beiden Spalten Name und Gehalt sind die in der SELECT-Klausel angegebenen SQL. Es enthält einen nicht angegebenen Primärschlüssel, der beabsichtigt ist und verwendet wird, um die Eindeutigkeit der Entität innerhalb der Ergebnismenge sicherzustellen.
Doma bietet Klassen im Paket "org.seasar.doma.jdbc.criteria.tuple", die Kombinationen von Werten wie "Tuple2", "Tuple3", ..., "Tuple9" darstellen. Die Zahl am Ende des Klassennamens gibt an, wie viele Werte die Klasse verarbeiten kann.
Das Folgende ist ein Beispiel für die Projektion von zwei Spalten mit der Klasse "Tuple2".
public List<Tuple2<String, Salary>> selectNameAndSalary() {
Employee_ e = new Employee_();
return nativeSql.from(e).select(e.name, e.salary).fetch();
}
Beachten Sie, dass wir "nativeSql" anstelle von "entityql" verwenden. Wenn Sie keine Entitäten mit einzelnen Bezeichnern verarbeiten müssen (z. B. Ergebnisse ohne Primärschlüssel abrufen oder Aggregatfunktionen verwenden), ist nativeSql eine gute Wahl.
Die ausgegebene SQL lautet wie folgt.
select t0_.name, t0_.salary from Employee t0_
Nur zwei Spalten, Name und Gehalt, sind die in der SELECT-Klausel angegebenen SQL.
Es liegt an Ihnen, wie Sie die Tuple2-9-Klasse in welcher Ebene verwenden, aber es ist ein schönes Design, sie als temporäre Datenstruktur zu verwenden, bis sie wie unten gezeigt in das DTO (oder ValueObject) der Anwendung konvertiert wird. Überlegen.
public List<NameAndSalaryDto> selectNameAndSalaryAsNameAndSalaryDtoList() {
Employee_ e = new Employee_();
return nativeSql.from(e).select(e.name, e.salary).stream()
.map(tuple -> new NameAndSalaryDto(tuple.getItem1(), tuple.getItem2()))
.collect(Collectors.toList());
}
Wenn Sie 10 oder mehr Spalten angeben und diese empfangen, können Sie sie mit der Schnittstelle org.seasar.doma.jdbc.criteria.tuple.Row
ausdrücken. Wenn Sie jedoch eine große Anzahl von Spalten haben, verwenden Sie eine schreibgeschützte Entitätsklasse. Es ist einfacher zu verstehen, wenn Sie es erstellen.
Ich habe erklärt, wie eine Projektion mit der Kriterien-API dargestellt wird.
Wenn es so etwas wie die Tuple-Klasse im Java-Standard gibt, würde ich sie gerne verwenden, aber es ist ärgerlich, dass sie tatsächlich nicht existiert.
Darüber hinaus wissen die Tupel 2-9-Klassen von Doma, dass sie in Kotlin verwendet werden, und unterstützen daher die Destrukturierungsdeklaration. Daher kann Kotlin wie folgt damit umgehen.
val (number, string) = Tuple2(1, "a")