# PreparedStatement setArray(int i, java.sql.Array)



## SilentJ (20. Sep 2007)

Hallo,

zwei Fragen zu der Methode in der Überschrift:

1. Unterstützt Microsoft Access via JDBC-ODBC-Bridge diesen Aufruf?

2. Wie transformiere ich ein String-Array in ein Objekt, das die Schnittstelle java.sql.Array implementiert, wenn (1.) gilt, was ich bisher nicht überprüfen konnte, da ich bei (2.) nicht weiterkomme.

Alles ist manchmal wie ein Möbiusband.   

Für Antworten wäre ich sehr dankbar.

PS: Die Verwendung von Access ist für mich immer noch Legion.


----------



## SilentJ (20. Sep 2007)

Die JdbcOdbcPreparedStatement Methode wirft eine UnsupportedOperationException für setArray.
Echt toll. Vielen Dank, Sun.


----------



## tuxedo (20. Sep 2007)

Danke für den Hinweis. Mit der Info hab ich jetzt mein jPMdbc angepasst. Hatte immer eine SQLException geworden. die UnsupportedOperationException ist dann bei nicht unterstützten Methoden doch geschickter ;-)

- Alex


----------



## SilentJ (20. Sep 2007)

Schön, dass ich helfen konnte. 

Doch das Problem, dass Du die fehlende setArray-Unterstützung von Sun entsteht, kann ich nicht ohne Performanzeinbußen lösen, scheint mir. Alles ein Käse.  :x


----------



## tuxedo (20. Sep 2007)

Hmm, ich habdie Erfagrung gemacht dass Sun auch nur mit Wasser kocht: Viele der JDBC-Methoden bauen auf anderen auf.

Schau doch mal in die Quellen anderen JDBC-Treiber, vielleicht findest du eine elegante Lösung ohne den Treiber verändern zu müssen (eigene setArray-Methode basteln die existierende Methoden  der PreparedStatement-Klasse nutzt).

- Alex

[update]

Hab gerade geschwind in die Quellen des Connector/J von MySQL geworfen: Die haben die Methode auch nicht implementiert... werfen aber keine UnsupportedOperationException sondern eine "eigene":


```
public class NotImplemented extends java.sql.SQLException {
	// ~ Constructors
	// -----------------------------------------------------------

	/**
	 * Creates a new NotImplemented object.
	 */
	public NotImplemented() {
		super(
				Messages.getString("NotImplemented.0"), SQLError.SQL_STATE_DRIVER_NOT_CAPABLE); //$NON-NLS-1$
	}
}
```

- Alex


----------



## SilentJ (20. Sep 2007)

Ich habe keinen blassen Schimmer, wie ich überhaupt einen Blick in die Klassen werfe. Die Source des JdbcOdbc-Pakets finde ich nicht. 

Ganz super. Danke für deine Bemühungen.


----------



## tuxedo (20. Sep 2007)

Es hilft dir ja nichts in den JDBC-ODBC Treiber reinzuschauen. Denn wie du ja schon festgestellt hast ist die Funktion da gar nicht implementiert. Mein Rat war in andere JDBC-Treiber reinzuschauen ob du da vielleicht was abgucken kannst.

Mal was anderes: 
Du willst mit dem Befehl in eine Spalte ein "Array" schreiben. Vermutlich kann der ODBC Treiber das deshalb nicht weil Access keinen solchen Typ kennt? Wäre das möglich?

Bin kein Access-Profi. Aber ich hab auf die schnelle in Access keine Möglichkeit gefunden einer Spalte einen Typ "ähnlich" Array zu geben. 

Was willst du denn als Array speichern? Und wie sieht der Spaltentyp in Access wirklich aus?

- Alex


----------



## SilentJ (20. Sep 2007)

Der JdbcOdbcTreiber stellt keine direkte Verbindung zwischen Java und Access her. Vielmehr muss dabei die in Java formulierte Anfrage in einen ODBC konformen Ausdruck umgewandelt werden. Da wäre mir schon ein Blick in die zuvor genannte Klasse was wert. 

Ganz trivial scheint mir die Sache nicht zu sein, wenn ich mir die Preise für kommerzielle Produkte ansehe. Ich gebe an dieser Stelle auf und werde meine Ergebnisse weiterreichen. Tja, was habe ich nicht schon Spaß mit Access gehabt.    :x


----------



## maki (20. Sep 2007)

Du solltest ml einen Blick auf Frontend Plus (bzw. JAD) werfen: http://www.kpdus.com/jad.html#gui

Damit lassen sich kompilierte Java Klassen dekompilieren 

Abgsehen davon den alten Treiber umzuschreiben, könntest du nicht etwas in dieser Art machen:


```
for( int i= 0; i < stringArray.length; i++ )
    pstmt.setString (i, (String) stringArray[i]);
```

oder so ähnlich?


----------



## SilentJ (20. Sep 2007)

Ich glaube nicht, dass etwas in der Art


```
PreparedStatement ps = conn.prepareStatement("Select x.a FROM x WHERE x.b in (?)", ...);
```

Mit einer Laufvariable richtig zu inititialisieren wäre. Der einzige Parameter ? hat stets den Index 1.


----------



## maki (20. Sep 2007)

wie wär es dann mit

pstmt.setString (i+1, (String) stringArray_); 

aber wahrscheinlich versteh ich dichgearde nicht und wir reden deshalb an einander vorbei_


----------



## tuxedo (20. Sep 2007)

Ich schnalls auch nicht.

Oder soll die Abfrage so irgendwie aussehen (wenn sie fix und fertuig ausgefüllt wurde):


```
Select x.a FROM x WHERE x.b in (Wert1, Wert2, Wert3, Wert4,...Wertn)
```


Das ließe sich ja auch anders machen:


```
Select x.a FROM x WHERE x.b = Wert1
OR x.b = Wert2,
OR x.b = Wert3,
OR x.b = Wert4,
...,
OR x.b = Wertn
```

- Alex


----------



## maki (20. Sep 2007)

Ich versteh diese setArray nicht, auch nicht mithilfe der api doc, was sollte es denn machen?


----------



## tuxedo (20. Sep 2007)

maki hat gesagt.:
			
		

> Ich versteh diese setArray nicht, auch nicht mithilfe der api doc, was sollte es denn machen?





> public void setArray(int i,
> Array x)
> throws SQLException
> 
> ...



Ich schätze wenn du ein INSERT mit den Prepared Statements machst kannst du damit den Wert für eine Spalte setzen. Und der Wert ist vom Typ Array. So wie man einer String-Spalte einen String zuweisen kann, kannst du damit einer Array-Spalte einen Array-Wert zuweisen. Problem ist nur: Access kennt kein Spaltentyp "Array", und auch nix was so ähnlich ist. MySQL kanns ja wie gesagt auch nicht.

[update]
ich glaub ich hab die lösung.. momentchen...

- Alex


----------



## SilentJ (20. Sep 2007)

Ich meinte nur, dass Parameter in einem parametrisierten PrepareStatement, also alle "?" mit einem Index versehen sind. *Diesen* Index kann ich ansprechen. In meinem Beispiel ps.setString(1, "Wert");

Ok. Aber was, wenn ich eine variable Anzahl von abzufragenden Werten *eines* Parameters habe?

Ich möchte schlicht sagen:


```
SELECT x.a FROM x WHERE ("Wert1","Wert2","Wert3" {,... usw.})
```

Ich weiß im Vorfeld nicht, wie viele Werte ich haben werde, deshalb baue ich mir den String bis jetzt dynamisch zusammen, was mit Zeiteinbußen bei der String-Konkatenation und einen nicht vorkompilierten Query-Statement einhergeht. Das zusammen jage ich über die JDBC-ODBC-Bridge und kann sprichwörtlich Kaffee trinken gehen.

ps.setArray(1, java.sql.Array) ist auch kein Allheilmittel, aber damit wären einige der Probleme behoben. In beiden Fällen, per PreparedStatement wie mit normalem Statement muss man darauf achten, dass der Abfragestring nicht zu lang für Access wird, aber das ist zu verschmerzen - und gar kein Problem, so wie ich das bisher implementiert habe.

Ich lasse mich gerne eines Besseren belehren.

Michael[/b]


----------



## maki (20. Sep 2007)

Danke alex0801,

wieder was gelernt.


----------



## SilentJ (20. Sep 2007)

Danke für die Bemühungen, 

ich werde auf meine seit gestern laufende Lösung mit Zeichenkettenkonkatenation zurückgreifen. Die ist zwar schnarchlangsam, läuft aber.

Microsoft Access sage ich für heute adieu.

Michael


----------



## tuxedo (20. Sep 2007)

Okay, jetzt weiß ich was du willst.
Aber wo liegt das Problem denn folgendes zu tun:


```
SELECT * FROM meineTabelle
WHERE feldName1 IN( ? );
```


```
public String getArrayString(String[] a){
		
		StringBuffer sb = new StringBuffer();
		for(int i=0;i<a.length-1;i++)
			sb.append(a[i]+", ");
		sb.append(a[a.length-1]);
		
		return sb.toString();

	}

pstm.setString(1,getArrayString(meinArray));
```


Normale konkatenation ist zu langsam. Deshalb Stringbuffer. Ist noch ncith ganz Fehlerfrei beim durchlaufen des Arrays, aber es geht ja auch mehr um den Weg ...

- Alex


----------

