Wenn Sie die WHERE-Klausel von SQL erstellen, um mehrere Bedingungen anzugeben, müssen Sie mit logischen Operatoren wie AND und OR verketten. Dieser Artikel zeigt, wie eine solche Verkettung logischer Operatoren durch die Kriterien-API in Doma 2.43.0 dargestellt werden kann.
Die Verkettung logischer Operatoren ist eine einfache Funktion, die in SQL ausgedrückt werden kann. Die Realisierung als Programmiersprache ist jedoch eine zu berücksichtigende Frage. Das Merkmal von Doma ist, dass es unter Verwendung eines Lambda-Ausdrucks ausgedrückt werden kann.
Eine Übersicht über Doma und die Kriterien-API finden Sie in den anderen Artikeln unter Einführung in Doma.
Die Datenbank enthält nur 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,
version integer not null);
Bereiten Sie die Employee-Klasse als Entitätsklasse vor, die der Employee-Tabelle entspricht.
Employee.java
@Entity(metamodel = @Metamodel)
public class Employee {
@Id
public Integer id;
public String name;
public Integer age;
@Version public Integer version;
}
Wir werden ein "EmployeeRepository" vorbereiten und die "select" -Methode dieser Klasse neu schreiben, um einige Beispiele zu zeigen.
public class EmployeeRepository {
private final Entityql entityql;
public EmployeeRepository(Config config) {
this.entityql = new Entityql(config);
}
public List<Employee> select() {
//Hier ist ein Codebeispiel, das auf verschiedene Arten umgeschrieben wurde
}
}
Wenn die Suchbedingungen (eq (..., ...)
in diesem Beispiel) angeordnet sind, werden sie implizit durch AND verkettet.
Employee_ e = new Employee_();
return entityql.from(e).where(c -> {
c.eq(e.id, 1);
c.eq(e.name, "aaa");
c.eq(e.age, 20);
}).fetch();
Das generierte SQL sieht folgendermaßen aus: (Im Folgenden wird die SQL mit dem eingebetteten gebundenen Wert angezeigt. In Wirklichkeit wird die SQL jedoch mit der Bindungsvariablen "?" Ausgegeben.)
select t0_.id, t0_.name, t0_.age, t0_.version from Employee t0_ where t0_.id = 1 and t0_.name = 'aaa' and t0_.age = 20
Im vorherigen Beispiel wurde die Methode, die AND entspricht, nicht aufgerufen, aber es ist auch möglich, die Methode "und", die AND entspricht, wie folgt explizit aufzurufen. Die Methode and
empfängt einen Lambda-Ausdruck.
Employee_ e = new Employee_();
return entityql.from(e).where(c -> {
c.eq(e.id, 1);
c.and(() -> c.eq(e.name, "aaa"));
c.and(() -> c.eq(e.age, 20));
}).fetch();
Das generierte SQL lautet wie folgt und es wird dasselbe SQL wie im vorherigen Beispiel generiert (es gibt jedoch Unterschiede wie das Vorhandensein oder Fehlen von Klammern).
select t0_.id, t0_.name, t0_.age, t0_.version from Employee t0_ where t0_.id = 1 and (t0_.name = 'aaa') and (t0_.age = 20)
Um durch ODER zu verketten, rufen Sie die Methode oder
wie folgt auf: Die Methode or
empfängt einen Lambda-Ausdruck.
Employee_ e = new Employee_();
return entityql.from(e).where(c -> {
c.eq(e.id, 1);
c.or(() -> {
c.eq(e.name, "aaa");
c.eq(e.age, 20);
});
}).fetch();
Das generierte SQL sieht folgendermaßen aus:
select t0_.id, t0_.name, t0_.age, t0_.version from Employee t0_ where t0_.id = 1 or (t0_.name = 'aaa' and t0_.age = 20)
Ähnlich wie im vorherigen Beispiel, aber welche Art von SQL generiert der folgende Code?
Employee_ e = new Employee_();
return entityql.from(e).where(c -> {
c.or(() -> {
c.eq(e.name, "aaa");
c.eq(e.age, 20);
});
c.eq(e.id, 1);
}).fetch();
Sie könnten denken, dass ein zusätzliches ODER unmittelbar nach der WHERE-Klausel generiert wird, aber Doma entfernt automatisch das UND und das ODER am Anfang der WHERE-Klausel, sodass die folgende SQL generiert wird.
select t0_.id, t0_.name, t0_.age, t0_.version from Employee t0_ where (t0_.name = 'aaa' and t0_.age = 20) and t0_.id = 1
Diese Funktion ist nützlich, wenn die Notwendigkeit von UND oder ODER aufgrund einer bedingten Verzweigung in der WHERE-Klausel nicht statisch bestimmt wird.
Employee_ e = new Employee_();
return entityql.from(e).where(c -> {
if (Ein Zustand) {
c.or(() -> {
c.eq(e.name, "aaa");
c.eq(e.age, 20);
});
}
if (Einige Bedingung 2) {
c.or(() -> {
c.eq(e.name, "bbb");
c.eq(e.age, 30);
});
}
}).fetch();
Sie können beliebig viele "und" und "oder" ohne Einschränkungen verschachteln.
Employee_ e = new Employee_();
return entityql.from(e).where(c -> {
c.eq(e.id, 1);
c.or(() -> {
c.eq(e.name, "aaa");
c.eq(e.age, 20);
c.or(() -> {
c.eq(e.name, "bbb");
c.eq(e.age, 30);
});
});
}).fetch();
Der obige Code generiert das folgende SQL:
select t0_.id, t0_.name, t0_.age, t0_.version from Employee t0_ where t0_.id = 1 or (t0_.name = 'aaa' and t0_.age = 20 or (t0_.name = 'bbb' and t0_.age = 30))
Ich habe gezeigt, wie die Verkettung logischer Operatoren in der Doma Criteria API ausgedrückt werden kann.
Wie eingangs erwähnt, drückt die Criteira-API von Doma die Verkettung logischer Operatoren als Lambda-Ausdruck aus. Es gibt eine Methodenkette als eine andere Ausdrucksmethode, aber ich persönlich denke, dass die Methodenkette eine Schwäche hat. Es ist anfällig für bedingte Verzweigungen. Wenn es einen bedingten Zweig gibt, bricht die Kette und die Komplexität nimmt sofort zu. Dies liegt daran, dass Sie das zu verkettende Objekt in einer Variablen speichern müssen, um die Kette zu verbinden. Andererseits ist die Methode, die einen Lambda-Ausdruck wie die Criteria-API von Doma verwendet, einfach und gut lesbar, da es keinen Unterschied im Schreibstil gibt, je nachdem, ob eine bedingte Verzweigung enthalten ist oder nicht (nur weil sie von if-Blöcken umgeben ist). Ich denke.