2016-11-22 5 views
2

Lassen Sie uns sagen, ich habe eine generierte Entität wie folgt aus:querydsl-JPA dynamische Abfrage

public class QCandidate extends EntityPathBase<Candidate> { 

public final com.avisto.candisearch.persistance.model.enums.QAvailabilityEnum availability; 

public final DatePath<java.util.Date> birthDate = createDate("birthDate", java.util.Date.class); 

public final NumberPath<Long> cvId= createNumber("cvId", Long.class); 

public final StringPath city = createString("city"); 

} 

Meine Eingangswerte sind die Felder Namen („Verfügbarkeit“, „birth“, „Cvid“ ...) und eine Zeichenfolgenwert, den ich verwenden sollte, um ein "Gefällt mir" mit allen Feldern auszuführen.

Ich möchte aus den Feldnamen eine Abfrage erstellen beginnend:

  • Daten und Zahlen in Strings wirft und Kleinbuchstaben umwandelt sie
  • wenn das Feld ein EntityPathBase ist (wie Verfügbarkeit) extrahiert die ID und dann wieder wirft zu klein geschrieben String

Etwas wie:

lower(cast(C.cvId as varchar(255))) like 'value' 

für jedes Feld.

Ich kann dies querydsl-sql-Modul verwenden, aber ich möchte es nur mit dem Jpa-Modul erreichen.

Ich bin nicht interessiert an dem Mechanismus der Erstellung der FULL 'Where' -Klausel (ich weiß, ich muss den BooleanBuilder verwenden, oder zumindest ist das, was ich in der SQL-Version).

Was ich wissen möchte ist, wie man die individuellen 'where'-Bedingungen basierend auf dem Feldtyp erstellt.

Ich versuche, einen PathBuilder zu verwenden, aber es scheint, dass Methoden wie "getString oder getBoolean" Sie bereits den Typ des Feldes wissen müssen, das Sie extrahieren möchten. In meinem Fall, da ich gerade vom Feldnamen aus anfange, kann ich diese Methoden nicht verwenden und ich weiß nicht, wie ich den Typ jedes Felds ermitteln soll, beginnend mit dem Feldnamen, also stecke ich fest.

Antwort

1

Kann ein bisschen hässlich sein, aber praktikabler Vorschlag.

Beachten Sie, dass die Anzahl der Feldtypen, die PathBuilder akzeptiert, ziemlich begrenzt ist.

Sie können die Feldklasse eindeutig anhand des Feldnamens finden (mithilfe von Reflektion oder durch Beibehalten einer Mitgliedskarte, die mit jedem Feld aktualisiert wird).

Implementieren Sie einfach die Handhabung für jeden spezifischen Typ.

Dies kann hässlich sein Bündel von if..else oder, für elegantere Lösung, Karte von Typ-Handler [Klasse-> Handler] zu erstellen, implementiert jeder Handler Interface-Methode, um bestimmte Typen zu behandeln.

Pseudocode:

//building query 
for each field 
    Class fieldClass = findFieldClas(.., field) //use reflection or map 
    PathHandler handler = handlers.get(fieldClass) 
    handler.process(...) 

//type handler interface 
public interface Handler{ 
    public xx process(? extends DataPathBase); 
} 

//specific type handler implementation 
public class BooleanHandler implements Handler{ 
    public xx process(? extends DataPathBase path){ 
    BooleanPath bPath = (BooleanPath)path; 
    ... 
} 

//intitialize handlers map singleton or a factory in advance  
handlers.put(BooleanPath.class, new BooleanHandler()); 
... 

Hinweis dies eine generische Lösung, wenn Sie viele Klassen haben. Wenn Sie nur eine bestimmte Klasse haben, können Sie einfach eine permanente Zuordnung von fieldName-> Handler erstellen und die Suche nach der Feldklasse vermeiden.

Auch dies ist keineswegs eine schöne Lösung, sollte aber funktionieren.

+0

Danke für die Beantwortung, aber ich möchte vermeiden, jede Art von Mapping "Hardcoding". Ich fühle, dass ich tun könnte, was ich will, ohne dass ...:/ – vratojr

+0

Ich würde es nicht ganz "hardcoded" nennen. Set of DatePathBase ist ziemlich begrenzt und wird sich bei der Bibliotheksaktualisierung, wenn überhaupt, sehr selten ändern.Wenn Sie keine neuen Typen nach dem Upgrade in den verarbeiteten Feldern verwenden, müssen Sie auch nichts aktualisieren, im Grunde ist es eine einmalige Arbeit. Sie ordnen Feldbezeichnern keine Feldnamen zu, Sie ordnen Feldtypen zu, daher ist es eher eine Art "Framework" als eine hardcodierte Behandlung, eine dünne Abstraktionsschicht für API. –

+0

Sie haben Recht, Introspektion ist absolut der richtige Weg zu gehen. alberne mich dafür, dass ich nicht daran denke :) Danke. – vratojr