Ich bin in einer Position, in der unser Unternehmen einen Datenbanksuchdienst hat, der hochgradig konfigurierbar ist und für den es sehr nützlich ist, Abfragen auf programmatische Weise zu konfigurieren. Die Kriterien-API ist sehr leistungsfähig, aber wenn einer unserer Entwickler eines der Datenobjekte refaktorisiert, zeigen die Kriterieneinschränkungen erst dann an, dass sie nicht mehr funktionieren, wenn wir unsere Unit-Tests laufen lassen oder, noch schlimmer, wenn sie live und in unserer Produktionsumgebung sind. Kürzlich hat sich die Arbeitszeit für ein Refactoring-Projekt aufgrund dieses Problems unerwartet verdoppelt. Hätten wir gewusst, wie lange es wirklich dauern würde, hätten wir wahrscheinlich einen anderen Ansatz gewählt.
Ich möchte die Beispiel-API verwenden, um dieses Problem zu lösen. Der Java-Compiler kann lautstark darauf hinweisen, dass unsere Abfragen fehlerhaft sind, wenn wir "where"-Bedingungen für echte POJO-Eigenschaften angeben. Die Example-API bietet jedoch nur einen begrenzten Funktionsumfang und ist in vielerlei Hinsicht einschränkend. Nehmen Sie das folgende Beispiel
Product product = new Product();
product.setName("P%");
Example prdExample = Example.create(product);
prdExample.excludeProperty("price");
prdExample.enableLike();
prdExample.ignoreCase();
Hier wird die Eigenschaft "Name" abgefragt (mit einem Namen wie "P%"), und wenn ich das Feld "Name" entfernen oder umbenennen würde, wüssten wir das sofort. Aber was ist mit der Eigenschaft "Preis"? Sie wird ausgeschlossen, weil das Product-Objekt einen Standardwert dafür hat, also übergeben wir den Namen der Eigenschaft "price" an einen Ausschlussfilter. Wenn nun "price" entfernt wurde, wäre diese Abfrage syntaktisch ungültig und Sie würden es erst zur Laufzeit merken. LAME.
Ein weiteres Problem: Was wäre, wenn wir eine zweite Where-Klausel hinzufügen würden?
product.setPromo("Discounts up to 10%");
Aufgrund des Aufrufs von enableLike() passt dieses Beispiel auf den Werbetext "Rabatte bis zu 10%", aber auch auf "Rabatte bis zu 10.000.000 Dollar" oder alles andere, was passt. Im Allgemeinen sind die abfrageweiten Änderungen des Example-Objekts, wie enableLike() oder ignoreCase(), nicht immer auf jede Eigenschaft anwendbar, die überprüft wird.
Ein dritter und wichtiger Punkt: Was ist mit anderen besonderen Kriterien? Es gibt keine Möglichkeit, jedes Produkt mit einem Preis von mehr als 10 $ mit dem Standard-Beispielrahmen zu erhalten. Es gibt keine Möglichkeit, die Ergebnisse nach Verkaufsförderung absteigend zu sortieren. Wenn das Produktobjekt mit einem Hersteller verknüpft ist, gibt es auch keine Möglichkeit, ein Kriterium für das zugehörige Herstellerobjekt hinzuzufügen. Es gibt auch keine Möglichkeit, den FetchMode für die Kriterien für den Hersteller sicher zu spezifizieren (obwohl dies ein Problem mit der Criteria API im Allgemeinen ist - ungültig abgeholte Beziehungen schlagen stillschweigend fehl, noch mehr eine Zeitbombe)
Für alle oben genannten Beispiele müssten Sie auf die Kriterien-API zurückgreifen und String-Darstellungen von Eigenschaften verwenden, um die Abfrage durchzuführen - auch hier entfällt der größte Vorteil von Beispielabfragen.
Welche Alternativen zur Example-API gibt es, die die Art von Kompilierzeit-Hinweisen liefern können, die wir brauchen?