# Baukasten-SQL?



## Landei (15. Okt 2008)

Komische Überschrift, ich weiß...

Ein Kollege bastelt an etwas, das das dynamische Zusammenbauen von Abfragen erleichertern soll. Als Beispiel für die Verwendung hat er mir das hier geschickt:


```
whereClause . and ().
        openParanthesis().
        like(OrderHeadDAB. PROFORMA_VALIDITY_DATE_VALUE , poNumber ).
        or().exists().
          openParanthesis().
                      select().star().
                      from(OrderItemDAB. OID_VALUE .getTableName()).
                      where().equals(OrderItemDAB. ORDER_OID_VALUE , OrderHeadDAB. OID_VALUE ).
                              and().like(OrderItemDAB. PURCHASE_ORDER_IDVALUE , poNumber ).                              
          closeParanthesis().        
        closeParanthesis();
```

Ich finde das bezüglich der Syntax ... sagen wir mal "lustig grenzwertig". Dazu muss man wissen, dass "harte" SQL-Strings mit String.format oder so in der Firma verpönt sind (da sind wohl schon welche tüchtig auf die Nase gefallen beim DB-System wechseln), also Operatoren usw. nur an einer Stelle kodiert sein sollen.

1) Gibt es für soetwas in dieser Art vielleicht schon einen Baukasten?
2) mich stören die ...paranthesis() Methoden. Bekommt man die weg, ohne die launige Syntax kaputt zu machen?
3) Wie bekommt man da ein wenig Typsicherheit rein (ich vermute mal, bisher steckt da nur ein "cleverer StringBuilder" dahinter
4) Haltet ihr das generell für eine gute Idee? Gibt es "bewährte" Alternativen?


----------



## Gelöschtes Mitglied 5909 (15. Okt 2008)

http://www.google.de/search?hl=de&q=java+sql+query+builder&btnG=Suche&meta=

Besser: Hibernate, Ibatis, JPA, ...


----------



## maki (15. Okt 2008)

>>  Gibt es für soetwas in dieser Art vielleicht schon einen Baukasten? 

iBatis bietet genau so etwas, die sog. SQL Maps, SQL gibt es da nur in XML Dateien.
Mit JPA/Hibernate spart man sich SQL gefrickel komplett.


----------



## Landei (16. Okt 2008)

> iBatis bietet genau so etwas, die sog. SQL Maps, SQL gibt es da nur in XML Dateien.


Ich suche nach einer nur-Java Lösung.



> Mit JPA/Hibernate spart man sich SQL
> gefrickel komplett.


Amen! Aber wir hängen noch mit EJB2.x rum (bitte jetzt nicht die EJB QL vorschlagen - zumindest in EJB 2.0 unbrauchbar). Beileidsbekundungen bitte hier eintragen: ...................


----------



## maki (16. Okt 2008)

>> Ich suche nach einer nur-Java Lösung. 

Sehe da keinen Vorteil, ganz im Gegenteil.

Was dein Kollege da gemacht hat nennt sich "eDSL", "embedded Domain Specific Language", ist also schon eine Sprache  für einen speziellen Problembereich (SQL aus Java erstellen), "normales" Java sieht anders aus, du doch selbst auch,. ist also schon mal keine "reine" Java Lösung.
Da ist die Trennung von iBatis genau richtig imho, sehr flexibel.

>>  Aber wir hängen noch mit EJB2.x rum

Na und? Hibernate kann auch ohne EJB3 einsetzen, müsst halt auf JPA verzichten, seit 2004 machen wir das so in unseren EJB2.1 Projekten, oder habt ihr etwa EJB2.1 EntityBeans verwendet? Böse Böse böse....


----------



## Harr (16. Okt 2008)

Landei hat gesagt.:
			
		

> 4) Haltet ihr das generell für eine gute Idee? Gibt es "bewährte" Alternativen?



Kommt drauf an, was man damit erreichen will.
Die genannten Alternativen kuemmern sich halt nicht nur um SQL-Queries, sondern auch um solche Dinge wie Persistierung oder auch Komposition von Objekten, Inheritence, lazy loading, usw...
Wenn es Dir nur darum geht, (prepared-)statements typsicher zusammenzustoepseln, dann tut's auch eine simple selbstgestrickte "Query"-Klasse mit 'ner varargs-methode a la ".add(String sql, Object... args)", die dann mit Hilfe von instanceof das ganze setBlah-Geraffel uebernimmt. Sowas ist ein 10-Zeiler. (ok, 20... ) Hilft aber nicht wirklich, wenn es um DB-Unabhaengigkeit geht.
Alternativ gibt es noch (sehr wenige) Active Record Implementierungen fuer Java.
Wie immer, Geschmacksache.


----------



## Landei (22. Okt 2008)

Die Funktionalität, aus den gefundenen RecordSets Objekte zu machen, ist in unserem Framework schon vorhanden (nicht hübsch, aber es läuft). Das Problem ist wirklich nur, eine ordentliche Query zusammenzubauen. Wir wollen also nicht das ganze EJB ersetzen, sondern nur die (wie schon erwähnt unbrauchbare) EJB-QL.

Ich habe vorgeschlagen, das die Verkettungs-Klasse mehrere Interfaces implementiert und bei der Verkettung zurückliefert, also wie ein Chamäleon ihren Typ dauernd ändert. Mini-Beispiel:

```
public interface Ping {  public Pong pong(); }

public interface Pong { public Ping ping(); }

public class PingPong implements Ping, Pong {

  private PingPong() {  } //der Klient sieht niemals den "wahren" Typ
  public static Ping createPing() {  
    System.out.print("PING...");
    return new PingPong();
  }

  public Pong pong() {
    System.out.print("pong...");
    return this;
  }

  public Ping ping() {
    System.out.print("ping...");
    return this;
  }
}

PingPong.createPing().pong().ping().pong().ping(); //OK
PingPong.createPing().pong().ping().ping().pong(); //Compilier-Fehler
```

Mir ist klar, dass man damit nicht alle Fehler abfangen kann, aber so Sachen wie and().or() sollten sich damit vermeiden lassen.


----------

