Discussion:
String über mehrere Zeilen
(zu alt für eine Antwort)
Thomas Weiler
2007-01-30 19:15:26 UTC
Permalink
Hallo,

arbeite mit Eclipse 3.2

Habe einen sehr langen String, den ich in eine entspechende Variable
schreiben will. Gibt es in Java eine Syntax mit der ich dies
übersichtlich über mehrere Zeilen machen kann?

Also so (@ funkt ja nicht wie in C#):

String sql = @"select * from tabelle
where spalte1 = wert1 and
spalte2 = wert2
order by wert3";

anstatt:

String sql = "select * from tabelle where spalte1 = wert1 and spalte2 =
wert2 order by wert3";

Finde trotz intensiver Suche keine passende Antwort.

Danke für alle Antworten.
Stefan Matthias Aust
2007-01-30 19:20:54 UTC
Permalink
Post by Thomas Weiler
Habe einen sehr langen String, den ich in eine entspechende Variable
schreiben will. Gibt es in Java eine Syntax mit der ich dies
übersichtlich über mehrere Zeilen machen kann?
Nein.
Post by Thomas Weiler
where spalte1 = wert1 and
spalte2 = wert2
order by wert3";
Aber

String sql =
"select * from tabelle " +
"where spalte1 = wert1 and " +
"spalte2 = wert2 " +
"order by wert3";

ist doch auch nicht so viel anders. Und wenn du da wirklich
Zeilenumbrüche im String haben willst, fügst du halt noch \n ein.
--
Stefan Matthias Aust
Stefan Kuhne
2007-01-30 19:51:20 UTC
Permalink
Post by Stefan Matthias Aust
ist doch auch nicht so viel anders. Und wenn du da wirklich
Zeilenumbrüche im String haben willst, fügst du halt noch \n ein.
Oder System.getProperty("line.separator").

Stefan Kuhne
Stefan Matthias Aust
2007-01-30 20:26:08 UTC
Permalink
Post by Stefan Kuhne
Oder System.getProperty("line.separator").
Halte ich für unwahrscheinlich. Warum will man sich die Arbeit im
Hauptspeicher unnötig schwer machen? Wenn ich Strings in eine Datei
speichern will, benutze ich einen Writer, der sich um die Konvertierung
kümmert. Ansonsten finde ich es einfacher, mit \n als generischem
Zeilentrenner zu arbeiten.
--
Stefan Matthias Aust
Hubert Partl
2007-01-31 09:04:15 UTC
Permalink
Post by Stefan Kuhne
Post by Stefan Matthias Aust
fügst du halt noch \n ein.
Oder System.getProperty("line.separator").
oder kürzer File.separator :-)

Aber das kommt darauf an:

Beim Schreiben in eine Text-Datei muss man
entweder den File.separator in den String einbauen
oder die newLine() oder println() Methoden verwenden.

Bei Zeilenwewchseln in einer TextArea oder JTextArea
soll man nur \n nehmen,
damit nicht irgendwelche unerwünschte Nebeneffekte entstehen
wie falsche Zählung der Cursorposition oder Länge.

Zeilenwechsel in JLabel oder JButton erhält man mit
<html>....<p>....

Und die Header einer E-Mail innerhalb des Protokolls SMTP
muss man mit \r\n trennen,
wenn man die Norm einhalten will.



--
Sascha Broich
2007-01-31 09:49:15 UTC
Permalink
Post by Hubert Partl
Post by Stefan Kuhne
Post by Stefan Matthias Aust
fügst du halt noch \n ein.
Oder System.getProperty("line.separator").
oder kürzer File.separator :-)
Nein, das sind zwei verschieden Dinge.

line.separator: "\n", "\r" oder "\r\n"
File.separator: "/" oder "\"


Sascha Broich
--
Den Blick hielt er nach rechts gewandt,
der Bus kam leider linker Hand.
(VOX Werbung Six Feet Under)
Hubert Partl
2007-01-31 10:05:31 UTC
Permalink
Post by Hubert Partl
Post by Stefan Kuhne
Oder System.getProperty("line.separator").
oder kürzer File.separator
Nein, sorry, habe die beiden Separatoren verwechselt,
File.separator enthält natürlich System.getProperty("file.separator")

--
Alfred
2007-01-31 05:46:35 UTC
Permalink
Post by Thomas Weiler
Aber
String sql =
"select * from tabelle " +
"where spalte1 = wert1 and " +
"spalte2 = wert2 " +
"order by wert3";
ist doch auch nicht so viel anders.
Dafür nimmat man einen StringBuffer.
Post by Thomas Weiler
Und wenn du da wirklich Zeilenumbrüche im String haben willst,
Welchen Nutzen hätten diese in diesem Fall?
Post by Thomas Weiler
fügst du halt noch \n ein.
Wohl kaum - und was bitte ist an '\n' generisch?
siehe: Ansonsten finde ich es einfacher, mit \n als
generischem Zeilentrenner zu arbeiten.

Alfred
Michael Paap
2007-01-31 08:52:22 UTC
Permalink
Post by Alfred
Post by Thomas Weiler
Aber
String sql =
"select * from tabelle " +
"where spalte1 = wert1 and " +
"spalte2 = wert2 " +
"order by wert3";
ist doch auch nicht so viel anders.
Dafür nimmat man einen StringBuffer.
Nein, das tut man in *diesem* Falle eben nicht.

Gruß,
Michael Paap
Daniel Röder
2007-01-31 08:58:25 UTC
Permalink
Post by Michael Paap
Post by Alfred
Post by Thomas Weiler
Aber
String sql =
"select * from tabelle " +
"where spalte1 = wert1 and " +
"spalte2 = wert2 " +
"order by wert3";
ist doch auch nicht so viel anders.
Dafür nimmat man einen StringBuffer.
Nein, das tut man in *diesem* Falle eben nicht.
IMHO macht das der Compiler ab einer gewissen String-Länge automatisch,
um das Zusammensetzen der einzelnen Strings zu optimieren.

Viele Grüße

Daniel
Sönke Müller-Lund
2007-01-31 09:14:20 UTC
Permalink
Post by Daniel Röder
IMHO macht das der Compiler ab einer gewissen String-Länge automatisch,
um das Zusammensetzen der einzelnen Strings zu optimieren.
Ich kann mir nicht vorstellen, dass das von der Länge abhängt. AFAIK
macht der Compiler auch aus "a" + "b" ein Literal.

Sönke
Michael Paap
2007-01-31 09:20:24 UTC
Permalink
Post by Daniel Röder
IMHO macht das der Compiler ab einer gewissen String-Länge automatisch,
um das Zusammensetzen der einzelnen Strings zu optimieren.
Mehere durch + verknüpfte String-*Literale* sind für den Compiler *eine*
"string-valued constant expression".

Gruß,
Michael
Daniel Röder
2007-01-31 11:10:53 UTC
Permalink
Post by Michael Paap
Post by Daniel Röder
IMHO macht das der Compiler ab einer gewissen String-Länge automatisch,
um das Zusammensetzen der einzelnen Strings zu optimieren.
Mehere durch + verknüpfte String-*Literale* sind für den Compiler *eine*
"string-valued constant expression".
Aus Java 2 - Designmuster und Zertifizierungswissen.

http://www.galileocomputing.de/openbook/java2

<snip>

10.4.1 Compiler-Optimierung

Der Compiler wandelt allerdings das sehr aufwändige Anfügen von Strings
mit dem Operator + automatisch in das Äquivalent append() von
StringBuffer um.

Somit sind die folgenden Anweisungen äquivalent:

Compiler-Optimierung zu einfachen String-Operationen mit +

System.out.println(
"Dies "+"ist "+"eine "+"Append-"+"Operation.");

System.out.println(new StringBuffer().append("Dies ")
.append("ist ")
.append("eine ")
.append("Append-")
.append("Operation.")
.toString());



<snap>

Die Frage ist, wer hat Recht?

Daniel, der nun ein wenig verwirrt ist...
Michael Paap
2007-01-31 11:49:42 UTC
Permalink
Post by Daniel Röder
10.4.1 Compiler-Optimierung
Der Compiler wandelt allerdings das sehr aufwändige Anfügen von Strings
mit dem Operator + automatisch in das Äquivalent append() von
StringBuffer um.
Compiler-Optimierung zu einfachen String-Operationen mit +
System.out.println(
"Dies "+"ist "+"eine "+"Append-"+"Operation.");
System.out.println(new StringBuffer().append("Dies ")
.append("ist ")
.append("eine ")
.append("Append-")
.append("Operation.")
.toString());
Ja. Man mag ja zu dem Insel-Buch sonst stehen, wie man will, aber durch
übertreibene Präzision oder Fehlerfreiheit zeichnet es sich nicht aus.
Post by Daniel Röder
Die Frage ist, wer hat Recht?
Ich.

Kompiliere obiges Beispiel und schau dir mit javap -c <KLASSENNAME> an,
was im Bytecode steht. Danach schreibe eine Fehlermeldung an den Autor
des Buches. Ich hab das einmal gemacht, ich tu es nicht wieder.

Gruß,
Michael
Michael Paap
2007-01-31 11:57:19 UTC
Permalink
Post by Michael Paap
Post by Daniel Röder
Die Frage ist, wer hat Recht?
Ich.
Kompiliere obiges Beispiel und schau dir mit javap -c <KLASSENNAME> an,
was im Bytecode steht. Danach schreibe eine Fehlermeldung an den Autor
des Buches. Ich hab das einmal gemacht, ich tu es nicht wieder.
Oder schau in die Langspec, Abschnitt 3.10.5 String Literals:
(http://java.sun.com/docs/books/jls/second_edition/html/lexical.doc.html#101083):

"Strings computed by constant expressions (§15.28) are computed at
compile time and then treated as if they were literals."

Nachtrag: Die Frage, um die es hier geht, ist nicht zu verwechseln mit
dem Problem, was der folgende Code demonstriert:

public class Stringverkettung {
public static void main(String[] args) {

long start;
long elapsed;
int amount;

amount = 20000;
start = System.currentTimeMillis();
test1(amount);
elapsed = System.currentTimeMillis() - start;
StringBuffer sb1 = new StringBuffer(50)
.append("Plus-Operator: \t")
.append(elapsed)
.append(" ms \t(")
.append(amount)
.append(" characters appended)");
System.out.println(sb1);

amount = 20000;
start = System.currentTimeMillis();
test2(amount);
elapsed = System.currentTimeMillis() - start;
StringBuffer sb2 = new StringBuffer(50)
.append("String#concat(): \t")
.append(elapsed)
.append(" ms \t(")
.append(amount)
.append(" characters appended)");
System.out.println(sb2);

amount = 1000000;
start = System.currentTimeMillis();
test3(amount);
elapsed = System.currentTimeMillis() - start;
StringBuffer sb3 = new StringBuffer(50)
.append("StringBuffer I: \t")
.append(elapsed)
.append(" ms \t(")
.append(amount)
.append(" characters appended)");
System.out.println(sb3);

amount = 1000000;
start = System.currentTimeMillis();
test4(amount);
elapsed = System.currentTimeMillis() - start;
StringBuffer sb4 = new StringBuffer(50)
.append("StringBuffer II: \t")
.append(elapsed)
.append(" ms \t(")
.append(amount)
.append(" characters appended)");
System.out.println(sb4);

amount = 1000000;
start = System.currentTimeMillis();
test5(amount);
elapsed = System.currentTimeMillis() - start;
StringBuffer sb5 = new StringBuffer(50)
.append("StringBuilder I: \t")
.append(elapsed)
.append(" ms \t(")
.append(amount)
.append(" characters appended)");
System.out.println(sb5);

amount = 1000000;
start = System.currentTimeMillis();
test6(amount);
elapsed = System.currentTimeMillis() - start;
StringBuffer sb6 = new StringBuffer(50)
.append("StringBuilder II: \t")
.append(elapsed)
.append(" ms \t(")
.append(amount)
.append(" characters appended)");
System.out.println(sb6);
}

/*
* Verkettung mit Plus-Operator
*/
static void test1(int amount) {
String s = "";
for (int i = 0; i < amount; i++) {
s = s + "x";
}
}

/*
* Verkettung mit String#concat()
*/
static void test2(int amount) {
String s = "";
for (int i = 0; i < amount; i++) {
s = s.concat("x");
}
}

/*
* Verkettung mit StringBuffer
*/
static void test3(int amount) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < amount; i++) {
sb.append("x");
}
String s = sb.toString();
}

/*
* Verkettung mit StringBuffer mit Laengenvorgabe
*/
static void test4(int amount) {
StringBuffer sb = new StringBuffer(amount);
for (int i = 0; i < amount; i++) {
sb.append("x");
}
String s = sb.toString();
}

/*
* Verkettung mit StringBuilder
*/
static void test5(int amount) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < amount; i++) {
sb.append("x");
}
String s = sb.toString();
}

/*
* Verkettung mit StringBuilder mit Laengenvorgabe
*/
static void test6(int amount) {
StringBuilder sb = new StringBuilder(amount);
for (int i = 0; i < amount; i++) {
sb.append("x");
}
String s = sb.toString();
}
}

Gruß,
Michael
Daniel Röder
2007-01-31 12:41:29 UTC
Permalink
Danke für die Hinweise...

Habs ausprobiert. Ihe habt Recht (Michael+Ralf).

Viele Grüße

Daniel
Michael Paap
2007-01-31 12:53:08 UTC
Permalink
Post by Daniel Röder
Habs ausprobiert. Ihe habt Recht (Michael+Ralf).
Und? Schreibst du eine Mail? *g*

Gruß,
Michael
Daniel Röder
2007-01-31 13:29:11 UTC
Permalink
Post by Michael Paap
Post by Daniel Röder
Habs ausprobiert. Ihe habt Recht (Michael+Ralf).
Und? Schreibst du eine Mail? *g*
Wenn du mich nicht _gewarnt_ hättest, vermutlich...

Daniel
Ralf Ullrich
2007-01-31 12:20:17 UTC
Permalink
Post by Daniel Röder
Aus Java 2 - Designmuster und Zertifizierungswissen.
http://www.galileocomputing.de/openbook/java2
<snip>
10.4.1 Compiler-Optimierung
Der Compiler wandelt allerdings das sehr aufwändige Anfügen von Strings
mit dem Operator + automatisch in das Äquivalent append() von StringBuffer
um.
Compiler-Optimierung zu einfachen String-Operationen mit +
System.out.println(
"Dies "+"ist "+"eine "+"Append-"+"Operation.");
System.out.println(new StringBuffer().append("Dies ")
.append("ist ")
.append("eine ")
.append("Append-")
.append("Operation.")
.toString());
<snap>
Die Frage ist, wer hat Recht?
Wenn das so in der "Insel" steht, dann ist das eindeutig falsch!

Aus dem Source

System.out.println("Dies " + "ist " + "eine "
+ "Append-" + "Operation.");

macht der Compiler

System.out.println("Dies ist eine Append-Operation.");

Aber aus dem Source

String a = "Dies ";
String b = "ist ";
String c = "eine ";
String d = "Append-";
String e = "Operation.";
System.out.println(a + b + c + d + e);

macht der Compiler tatsächlich

String a = "Dies ";
String b = "ist ";
String c = "eine ";
String d = "Append-";
String e = "Operation.";
System.out.println(
new StringBuilder().append(a).append(b)
.append(c).append(d).append(e).toString());

Aber:

Aber aus dem Source

static final String a = "Dies ";
static final String b = "ist ";
static final String c = "eine ";
static final String d = "Append-";
static final String e = "Operation.";
System.out.println(a + b + c + d + e);

macht der Compiler dennoch

static final String a = "Dies ";
static final String b = "ist ";
static final String c = "eine ";
static final String d = "Append-";
static final String e = "Operation.";
System.out.println("Dies ist eine Append-Operation.");

Alles klar?

Der Compiler wird grundsätzlich alle konstanten Ausdrücke berechnen und
nur das Ergebnis in den Bytecode einbauen. Dies gilt nicht nur für Strings
sondern auch für alle primitiven Typen:

int x = 3 * 4 * 5;

wird zu

int x = 60;

HTH

cu
Volker Glave
2007-01-31 14:02:02 UTC
Permalink
Post by Ralf Ullrich
Der Compiler wird grundsätzlich alle konstanten Ausdrücke berechnen und
nur das Ergebnis in den Bytecode einbauen. Dies gilt nicht nur für Strings
int x = 3 * 4 * 5;
wird zu
int x = 60;
Aber mit Ausnahmen [sic].
Bei
int x = 3 * 4 / 0;
wird Bytecode für die Division generiert.

Gruß
Volker
Paul Ebermann
2007-01-31 21:10:04 UTC
Permalink
Post by Volker Glave
Post by Ralf Ullrich
Der Compiler wird grundsätzlich alle konstanten Ausdrücke berechnen und
nur das Ergebnis in den Bytecode einbauen. Dies gilt nicht nur für Strings
int x = 3 * 4 * 5;
wird zu
int x = 60;
Aber mit Ausnahmen [sic].
Bei
int x = 3 * 4 / 0;
wird Bytecode für die Division generiert.
Ich vermute, dass es auch zulässig wäre, direkt ein

trow new ArithmeticException("Division by zero");

in den Bytecode einzubauen.


Paul
--
Nun ludigxas: : ()
Paul Ebermann
2007-01-31 14:34:29 UTC
Permalink
"Ralf Ullrich" skribis:

[...]
Post by Ralf Ullrich
Aber aus dem Source
static final String a = "Dies ";
static final String b = "ist ";
static final String c = "eine ";
static final String d = "Append-";
static final String e = "Operation.";
System.out.println(a + b + c + d + e);
macht der Compiler dennoch
static final String a = "Dies ";
static final String b = "ist ";
static final String c = "eine ";
static final String d = "Append-";
static final String e = "Operation.";
System.out.println("Dies ist eine Append-Operation.");
Alles klar?
Und damit man es so in eine Methode schreiben kann,
sollte man noch die static weglassen. (Es klappt
trotzdem noch.)


Paul
--
Zitieren im Usenet: http://einklich.net/usenet/zitier.htm
Warum Realnamen: http://www.wschmidhuber.de/realname/
Stefan Matthias Aust
2007-02-01 09:11:15 UTC
Permalink
Post by Daniel Röder
Die Frage ist, wer hat Recht?
Use the Source, Luke, ä Daniel, ä ich meine den javac-Compiler.

Na du weisst schon. Das kann man doch flux selbst herausfinden. :)
--
Stefan Matthias Aust
Stefan Matthias Aust
2007-01-31 09:21:03 UTC
Permalink
Post by Daniel Röder
Post by Michael Paap
Nein, das tut man in *diesem* Falle eben nicht.
IMHO macht das der Compiler ab einer gewissen String-Länge automatisch,
um das Zusammensetzen der einzelnen Strings zu optimieren.
Nein, das tut er in *diesem* Falle eben nicht.

Das "+" wird zur Übersetzungszeit ausgewertet.
--
Stefan Matthias Aust
Alfred
2007-02-02 19:12:22 UTC
Permalink
Post by Michael Paap
Post by Alfred
Post by Thomas Weiler
String sql =
"select * from tabelle " +
"where spalte1 = wert1 and " +
"spalte2 = wert2 " +
"order by wert3";
ist doch auch nicht so viel anders.
Dafür nimmat man einen StringBuffer.
Nein, das tut man in *diesem* Falle eben nicht.
Das kannst du sicher auch begründen?...

Alfred
Michael Paap
2007-02-02 23:49:48 UTC
Permalink
Post by Alfred
Das kannst du sicher auch begründen?...
Das ist im Verlaufe dieses Threads hinreichend geschehen.

<eppn1u$uaj$***@online.de>
<eppn0j$o26$***@newsreader3.netcologne.de>

usw.

Gruß,
Michael

Marcus Woletz
2007-01-31 08:38:54 UTC
Permalink
Hallo Alfred,

Alfred schrieb:
[...]
Post by Alfred
Dafür nimmat man einen StringBuffer.
Würde ich bei statischem Text nicht empfehlen.
"Dies ist" + " ein Text" bastelt der Compiler zu einem
einzigen Stringobjekt zusammen (kurz getestet mit javap).
Nimmst Du einen StringBuffer, ergibt das doch einigen
Overhead.

[...]
Post by Alfred
Alfred
ciao

Marcus
Hubert Partl
2007-01-31 09:09:02 UTC
Permalink
Dafr nimmat man einen StringBuffer.
nur, wenn diese Zeit- und Platz-Optimierung wirklich notwendig ist,
also innerhalb von zeitkritischen Schleifen,
und auch dann besser StringBuilder als StringBuffer.
was bitte ist an '\n' generisch?
Dass es auch in Java in bestimmten Fällen wie z.B. in einer TextArea
einen Zeilenwechsel definiert.

Und dass es in manchen anderen Sprachen wie z.B. C
den systemabhängigen Line-Separator bedeutet
bzw. diesen zur Laufzeit bewirkt, erzeugt, generiert.


--
Michael Paap
2007-01-31 09:22:45 UTC
Permalink
Post by Hubert Partl
nur, wenn diese Zeit- und Platz-Optimierung wirklich notwendig ist,
also innerhalb von zeitkritischen Schleifen,
und auch dann besser StringBuilder als StringBuffer.
Gerade da lässt man es für den gegebenen Fall, in dem es lediglich darum
geht, String-*Literale* auf mehrere Zeilen zu verteilen, bitte bleiben.

Gruß,
Michael
Stefan Ram
2007-01-30 21:10:02 UTC
Permalink
Post by Thomas Weiler
schreiben will. Gibt es in Java eine Syntax mit der ich dies
übersichtlich über mehrere Zeilen machen kann? (...)
where spalte1 = wert1 and
spalte2 = wert2
order by wert3";
public class Main
{ public static void main( final java.lang.String[] args )
throws java.lang.Exception
{ final java.lang.CharSequence source = source();
final java.lang.CharSequence sql = string( source ) /*select * from tabelle
where spalte1 = wert1 and
spalte2 = wert2
order by wert3*/;

java.lang.System.out.println( sql ); }

public static java.lang.CharSequence string
( final java.lang.CharSequence source )
{ final java.lang.String s = source.toString();
final java.util.regex.Matcher matcher =
java.util.regex.Pattern.compile( "/\\*([^\\001]*?)\\*/" ).matcher( s );
matcher.find();
return matcher.group( 1 ); }

public static java.lang.CharSequence source()
throws java.io.FileNotFoundException,
java.io.UnsupportedEncodingException,
java.io.IOException
{ final java.lang.String sourceFileName = "Main.java";

final java.io.File sourceFile = new java.io.File( sourceFileName );

/* java.io.FileNotFoundException */
final java.io.FileInputStream fileInputStream =
new java.io.FileInputStream( sourceFile);

/* java.io.UnsupportedEncodingException */
final java.io.InputStreamReader inputStreamReader =
new java.io.InputStreamReader( fileInputStream, "UTF-8" );

final java.io.BufferedReader bufferedReader =
new java.io.BufferedReader( inputStreamReader );

final java.lang.StringBuilder stringBuilder =
new java.lang.StringBuilder();

while( true )
{ final java.lang.String line = bufferedReader.readLine();
if( line != null )
{ stringBuilder.append( line );
stringBuilder.append( '\n' ); }
else break; }

bufferedReader.close();
inputStreamReader.close();
fileInputStream.close();

return stringBuilder;
}
}
Volker Glave
2007-01-31 10:00:40 UTC
Permalink
Post by Thomas Weiler
Habe einen sehr langen String, den ich in eine entspechende Variable
schreiben will. Gibt es in Java eine Syntax mit der ich dies
übersichtlich über mehrere Zeilen machen kann?
where spalte1 = wert1 and
spalte2 = wert2
order by wert3";
String sql = "select * from tabelle where spalte1 = wert1 and spalte2 =
wert2 order by wert3";
Finde trotz intensiver Suche keine passende Antwort.
Ich würde mir eine kleine Hilfsklasse bauen, die solche Strings
aufzubauen in der Lage ist, und die man dann ungefähr so
nutzen würde:

static String sql =
new SqlSup()
.select("*")
.from("tabelle")
.where()
.term("spalte1", "=", "wert1")
.and()
.term("spalte2", "=", "wert2")
.orderBy("wert3")
.toString()
;

U. a. wirkt das auch Syntax-Flüchtigkeitsfehlern (ein wenig) entgegen,
und
führt zu einem (ein wenig) einheitlich(er)en Erscheinungsbild der
resultieren
SQL-Strings.

Hilfsklasse:

final class SqlSup {
public SqlSup and() { return add(AND); }
public SqlSup where() { return add(WHERE); }
public SqlSup from(Object x) { return add(FROM, x); }
public SqlSup orderBy(Object x) { return add(ORDER_BY, x); }
public SqlSup select(Object x) { return add(SELECT, x); }
public SqlSup term(Object... x) { return add(x); }

public String toString() { return buf.toString(); }

private SqlSup add(Object... x) {
for (final Object o : x) {
buf.append(buf.length() > 0 ? " " : "").append(o);
}
return this;
}

private static final Object AND = "and";
private static final Object FROM = "from";
private static final Object ORDER_BY = "order by";
private static final Object SELECT = "select";
private static final Object WHERE = "where";

private final StringBuilder buf = new StringBuilder();
}

Das ist so natürlich noch (viel zu) primitiv, kann man dann
aber ja sukzessive aufbohren.

Ich nehme aber mal an, dass es so etwas schon irgendwo
geben wird ... (keine Ahnung, habe mit SQL nix zu tun ...)

Gruß
Volker
Stefan Matthias Aust
2007-01-31 10:28:58 UTC
Permalink
Post by Volker Glave
Ich würde mir eine kleine Hilfsklasse bauen, die solche Strings
aufzubauen in der Lage ist, und die man dann ungefähr so
Damit verlierst du aber den Vorteil, dass der String schon zur
Übersetzungszeit existiert. Wenn's dir darum geht, keine Syntaxfehler im
SQL zu machen, ist es vielleicht einfacher, die IDE entsprechend
aufzurüsten. IDEA mit dem IntelliLang-Plugin kann Strings nach
Minisprachen syntaxchecken. Ob SQL unterstützt wird, weiss ich nicht,
aber das könnte man nachrüsten.

Ansonsten finde ich die Idee - eine DSL - schon richtig, auch wenn's in
Java leider sehr mühsam ist (man braucht viel Boilerplate-Code).
Post by Volker Glave
static String sql =
new SqlSup()
.select("*")
.from("tabelle")
.where()
.term("spalte1", "=", "wert1")
.and()
.term("spalte2", "=", "wert2")
.orderBy("wert3")
.toString()
;
Diese Repräsentation ist aber leider suboptimal, da du Vorrangregeln bei
komplexeren Ausdrücken nicht berücksichtigst. Besser wäre IMHO sowas

select(
SQL.STAR,
tables("tabelle"),
where(
and(
eq("sp1", lit("wert1")),
eq("sp2", lit("wert2")))),
orderBy("sp3"))

wobei zur Lesbarkeit beiträgt, dass alle Funktionen static imports sind.
Dies ahmt besser den AST eines SQL-Ausdrucks nach und hilft noch mehr
Fehler zu vermeiden.

static String select(Columns c, Tables t, Where w, OrderBy o ) {
return "select " + c + " " + t " where " + w + " " + o;
}
static Tables tables(String... names) {
return new Tables(names);
}
static class Tables {
private final String[] names;
Tables(String... names) { this.names = names; }
String toString() { return join(names, ", "); }
}
...
static abstract class Expr {}
static class Op extends Expr {
private String op;
private Expr left, right;
...
String toString() {
return "(" + left + " " + op + " " + right + ")";
}
}
static Expr and(Expr left, Expr right) {
return new Op("AND", left, right);
}
...

Ich hoffe, das Prinzip wird so klar. Einfach nur Strings zu
konkatenieren ist natürlich ineffizient. Besser ist, einen StringBuilder
in eine lokalen Objekte hineinzureichen und dann da immer zu appenden.
--
Stefan Matthias Aust
Volker Glave
2007-01-31 10:57:45 UTC
Permalink
Post by Stefan Matthias Aust
Post by Volker Glave
Ich würde mir eine kleine Hilfsklasse bauen, die solche Strings
aufzubauen in der Lage ist, und die man dann ungefähr so
Damit verlierst du aber den Vorteil, dass der String schon zur
Übersetzungszeit existiert.
Ich verliere die _Eigenschaft_. Ob Vorteil oder Nachteil, ist
Anwendungsfallsache.

Vom OP war ...
| String sql = "select * from tabelle where spalte1 = wert1 and
spalte2 =
| wert2 order by wert3";
... als Beispiel gegeben, das dürfte für die Diskussion hier
vereinfacht dargestellt gewesen sein. spalte1, wert1, ... sollen
höchtvermutlich variable Anteile sein. D. h. der String steht eh
erst zur Laufzeit fest.
Post by Stefan Matthias Aust
Diese Repräsentation ist aber leider suboptimal, da du Vorrangregeln bei
komplexeren Ausdrücken nicht berücksichtigst. Besser wäre IMHO sowas
...
Darauf spielte ich mit meinem Hinweis ...
| Das ist so natürlich noch (viel zu) primitiv, kann man dann
| aber ja sukzessive aufbohren.
... an.
Post by Stefan Matthias Aust
Ich hoffe, das Prinzip wird so klar. Einfach nur Strings zu
konkatenieren ist natürlich ineffizient. Besser ist, einen StringBuilder
in eine lokalen Objekte hineinzureichen und dann da immer zu appenden.
Ja. (Wie ich es in meinem Vorschlag übrigens tat.)

Gruß
Volker
Stefan Matthias Aust
2007-02-01 09:09:36 UTC
Permalink
Post by Volker Glave
Ich verliere die _Eigenschaft_. Ob Vorteil oder Nachteil, ist
Anwendungsfallsache.
Du hast Recht.
Post by Volker Glave
Darauf spielte ich mit meinem Hinweis ...
| Das ist so natürlich noch (viel zu) primitiv, kann man dann
| aber ja sukzessive aufbohren.
... an.
Ich wollte meinen Vorschlag auch einfach als Erweiterung deiner
Grundidee verstanden wissen.
--
Stefan Matthias Aust
Oliver Haupt
2007-01-31 14:29:57 UTC
Permalink
Post by Stefan Matthias Aust
Ich hoffe, das Prinzip wird so klar. Einfach nur Strings zu
konkatenieren ist natürlich ineffizient.
Eben nicht.

Due musst sonst allerlei DB Syntax Eigenheiten abbilden, bekommst
Probleme mit

SELECT
BENUTZER.NAME AS ANMELDENAME
FROM
(
SELECT ...
)
WHERE ..

und das ist noch ein simples Beispiel.

Unions, joins, PL/SQL aufrufe, CASE ... whatever.
Post by Stefan Matthias Aust
Besser ist, einen StringBuilder
in eine lokalen Objekte hineinzureichen und dann da immer zu appenden.
SQL Statements durch eine Obecthierarchie abzubilden ist alles andere
als trivial, speziell wenn Du komplexe Abfragen durchfuehrst.

Ich benutze nur noch (fast) fertige prepared statements, die als
einzige dynamische Komponente noch beliebig viele Listen fuer
Variablen haben. Die SQL stehen in einer Konfiguration und gut ist.

cu,

olli
Volker Glave
2007-01-31 10:44:31 UTC
Permalink
Post by Volker Glave
Post by Thomas Weiler
String sql = "select * from tabelle where spalte1 = wert1 and spalte2 =
wert2 order by wert3";
Finde trotz intensiver Suche keine passende Antwort.
Ich würde mir eine kleine Hilfsklasse bauen, die solche Strings
aufzubauen in der Lage ist, und die man dann ungefähr so
...
Ich nehme aber mal an, dass es so etwas schon irgendwo
geben wird ... (keine Ahnung, habe mit SQL nix zu tun ...)
Vielleicht etwa (... kurze Google-Suche ...)
http://www.crossdb.com/docs/api/com/crossdb/sql/DefaultSelectQuery.html
http://www.docjar.com/docs/api/opennlp/quaks/query/MysqlQuery.html
Loading...