Ja, du möchstest Queries durchführen. Du könntest also eine Klasse erstellen, die diese Datenbankabfragen repräsentiert, welche wiederum den Zusammenbau der einzelnen Teile der Bedingung ermöglicht. Dort wäre es ohne Probleme möglich, typsichere Methoden zu haben, deren Parameter intern bspw. als String gehandhabt werden (da die Abfrage per String an die Datenbank geschickt werden muss). Solltest du bereits ein Framework verwenden, was bereits das objektorientierte Zusammenstellen von Queries ermöglicht (statt ausschließlich mit Strings zu arbeiten), dann solltest du höchstens einen Wrapper darum bauen oder nur dieses verwenden, abhängig davon, wie viel Funktionalität bereits vorhanden ist und wie viel noch fehlt.
Eine bessere Serialisierung wäre wahrscheinlich, dass die Persistenzschicht die Modelle erhält und deren Werte in Strings umgewandelt in Abfragen einfügt. Idealerweise wird das nicht einfach nur über Stringverkettungen gemacht, siehe obere Absatz.
Anbei nöchte ich auch erwähnen, dass ich finde, dass (wenn es um die Codesauberkeit geht) Reflection nur dann verwendet werden sollte, wenn es keine andere Möglichkeit gibt. Das Problem bei der find-Methode ist meiner Meinung nach, dass sie nicht wissen kann, wie die von der Datenbank kommenden Informationen aussehen, weshalb nur per Reflection die Werte dem Objekt zugewiesen werden können. Besser würde ich es also finden, wenn es für die einzelnen Anwendungsfälle die richtigen find-Methoden gibt, die die benötigten Parameter entgegennehmen.
Man sollte aber dennoch nicht vergessen, dass Reflection richtig angewendet Zeit einsparen kann, was wieder eine wichtige Rolle spielen könnte.
@BlueCobold:
Die Modell-Klasse würde ja nicht unbedingt wissen welche Art der Persistierung verwendet wird, es ist aber schlimm genug, dass das Modell sich selbst mit dem Laden der Daten beschäftigen soll. (Das ist wohl mit der Abstraktionsschicht von Nachoman gemeint.)