PreparedStatement und null

C

Camino

Gast
Hallo,

ich dachte schon, ich hätte mir eine schöne Lösung geschrieben, mit der ich über eine Methode PreparedStatements ausführen kann. Diese Methode habe ich in einer DBHandler-Klasse, auf die ich aus anderen Klassen zugreife und die Parameter übergebe. Aber jetzt ist ein Problem aufgetreten, weil einer der Werte/Objekte null ist.

Und zwar hab ich folgende Methode:
Java:
...
	protected void executeSQL2( String sql, Object[] values ) {
		
		PreparedStatement st = null;
		
		int z = 1;
		
		// DB-Verbindung holen
		Connection conn = DBConnection.getInstance();
						
		try {
			st = conn.prepareStatement( sql );
			
			for( Object obj : values ) {
			
				if ( Integer.class.isInstance(obj) ) {
					st.setInt( z, (Integer)obj );
				}
				
				if ( Double.class.isInstance(obj) ) {
					st.setDouble( z, (Double)obj );
				}
					
				if ( String.class.isInstance(obj) ) {
					st.setString( z, (String)obj );
				}
				
				if ( Boolean.class.isInstance(obj) ) {
					st.setBoolean( z, (Boolean)obj );
				}
				
				if ( BigDecimal.class.isInstance(obj) ) {
					st.setBigDecimal( z, (BigDecimal)obj );
				}
								
				if ( GregorianCalendar.class.isInstance(obj) ) {
					st.setTimestamp( z, new Timestamp( ((GregorianCalendar)obj).getTimeInMillis() ) );
				}
				
				if ( Date.class.isInstance(obj) ) {
					st.setDate( z, (Date)obj );
				}
				
				System.out.print( obj + "  " );
				
				z++;
			}

			st.executeUpdate();
			st.close();
		} catch ( SQLException e ) {
			e.printStackTrace();
		}
...

Das heisst, ich übergebe dieser Methode den SQL-String für das PreparedStatement und ein Object[ ] values mit den Werten für das PreparedStatement.
Der SQL-String sieht etwa so aus:
Java:
String sql = "INSERT INTO person VALUES " + 
		   "(DEFAULT, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, DEFAULT, " +
		   "?, DEFAULT, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
In der Methode gehe ich dann durch den Object-Array durch und schaue, welcher Typ das Object ist und setze es dementsprechend in das PreparedStatement.
Ist der Wert aber null, gibt es ein Problem, weil ja kein Objekt-Typ bekannt ist. Es gibt zwar die Möglichkeit mit setNull(), aber dafür bräuchte ich ja auch die Typangabe.

Jetzt weiss ich leider gerade nicht mehr weiter. Gibt es die Möglichkeit, diese Methode weiterhin zu nutzen und auch einen null-Wert irgendwie abzufangen? War halt ziemlich praktisch, weil ich diese Methode so für mehrere unterschiedliche Fälle universell einsetzen konnte. Oder muss ich dass zusammensetzen des PreparedStatements für jeden Fall, den ich habe, separat machen?

Ich hoffe, ich hab mein Problem einigermassen verständlich beschrieben. Vielleicht habt ihr ja Tipps, wie ihr das macht.
 

turtle

Top Contributor
Ich schlage vor, entweder ein bereits ausgereiftes Framework, nämlich myBATIS zu nutzen, oder sich anzuschauen (Open source), wie dort mit nullable columns umgegangen wird.
 

irgendjemand

Top Contributor
@turtle
ich denke ein großes framework *wobei ich hier wenn überhaupt SPRING empfehlen würde* wäre hier overkill ... diese aufgabe sollte jeder driver selbst erledigen können ... siehe unten

@TO
warum machst du dir eigentlich selbst die mühe die dir der treiber abnimmt ?

Java:
for(int i=0; i<values.length; i++)
{
	st.setObject(i+1, values[i]);
}

und den rest sollte dann eigentlich der driver machen ... da brauchst du dich gar nicht selbst drum kümmern ... denn [c]PreparedStatement.setObject(int, Object)[/code] ist ja im interface vorgeschrieben ... warum also nicht nutzen ?
 
C

Camino

Gast
warum machst du dir eigentlich selbst die mühe die dir der treiber abnimmt ?

Java:
for(int i=0; i<values.length; i++)
{
	st.setObject(i+1, values[i]);
}

und den rest sollte dann eigentlich der driver machen ... da brauchst du dich gar nicht selbst drum kümmern ... denn [c]PreparedStatement.setObject(int, Object)[/code] ist ja im interface vorgeschrieben ... warum also nicht nutzen ?

Grrrr, du hast recht, das sieht natürlich viel besser aus. Am Anfang hatte ich das alles noch mit "normalen" Statements gemacht, und dann auf PreparedStatements umgeschrieben. Dann war ich froh, diese Lösung mit der Methode und der Unterscheidung der Objekttypen gemacht zu haben. Aber so ist es natürlich perfekt. Muss ich gleich mal testen, ob der Treiber das auch so umsetzt. Und vor allem auch, wenn der Wert dann null ist. Danke für diesen Tipp...
 
C

Camino

Gast
Ich schlage vor, entweder ein bereits ausgereiftes Framework, nämlich myBATIS zu nutzen, oder sich anzuschauen (Open source), wie dort mit nullable columns umgegangen wird.

Danke für den Tipp. Ich möchte mich eigentlich erstmal direkt mit JDBC rumschlagen, bevor ich mich an andere externe Sachen ranwage. Aber vielleicht schau ich mir das ja mal an, wie das dort gemacht wird. Danke.
 

irgendjemand

Top Contributor
wie gesagt : es steht zwar auch in der doc das man diese methode nicht verwenden sollte ... und es daher einem entwickler eines drivers zum gewissen grad frei gestellt ist ob und wie er diese methode implementiert ...
aber da diese im interface nun mal vorgegeben ist kann man immer mal ruhig versuchen diese auch zu nutzen ...
 
C

Camino

Gast
Hmm, soweit ich das verstanden habe, sollte das nicht verwendet werden, weil es nicht immer gewährleistet ist, ob das bei allen Treibern oder Datenbanken auch einwandfrei funktioniert, und dass bei null-Werten eher setNull() oder setObject() mit Typangabe verwendet werden sollte.

Jetzt weiss ich nicht, was tun. Es funktioniert ja so mit dem setObject(), auch bei null-Werten, und ist natürlich viel kürzer und unkomplizierter. Ansonsten müsste ich mir überlegen, wie ich der Methode auch den Typ bei einem null-Wert mit übergebe.
 

irgendjemand

Top Contributor
das meinte ich halt mit "sollte nicht verwendet werden" ...
da ich aber selber noch nie versucht habe "NULL" in eine datenbank zu schreiben und auch nicht weis welche du verwendest kann ich dazu leider nichts sagen ...

MySQL z.b. bietet es an ein feld mit default "NULL" zu belegen ... dann brauchst du nur deinen query entsprechend schreiben und lässt die felder die nach default eh NULL werden und in die du auch NULL schreiben willst einfach aus dem query weg ... den rest macht MySQL selbst ...
wie das allerdings bei anderen , und vor allem embedded , datenbanken aussieht weis ich nicht ... ist aber glaube zum teil in SQL92 oder so spezifiziert
 
C

Camino

Gast
Ich arbeite mit PostgreSQL. Hatte das nicht erwähnt, da ich dachte, das Problem wäre unabhängig davon.

Das Feld war vorher ein VARCHAR NOT NULL UNIQUE. Um das UNIQUE beizubehalten geht es halt nicht, einfach nur einen leeren String reinzuschreiben, nur NULL wird nicht durch UNIQUE mehrfach verhindert. Deshalb musste ich das NOT NULL rausnehmen und NULL-Werte zulassen. Das Problem mit den PreparedStatements und NULL hatte ich vorher halt auch nicht.

Das mit dem DEFAULT NULL wird wohl auch nicht richtig klappen bzw. zu kompliziert, weil ich dann ja das PreparedStatement danach anpassen muss, also anstatt ein ? dann DEFAULT oder NULL schreiben müsste.
 
Zuletzt bearbeitet von einem Moderator:

irgendjemand

Top Contributor
nein ...
wenn du ein feld beim anlegen der tabelle "DEFAULT <irgendwas>" angibst ... dann lässt du es einfach komplett aus dem statement raus ... sowohl im ersten teil wo du die einzelnen felder aufzählst
[sql]INSERT INTO irgendwas ('feld1', 'feld2', 'feld4')[/sql]
als auch das entsprechende "?" im VALUES ...

denn DEFAULT steht doch genau dafür das eben beim einfügen vom datenbankserver der default wert gesetzt wird wenn kein anderer wert übergeben wird ... da musst du kein keyword ala "DEFAULT" im statement haben ... einfach das feld komplett weglassen ...


warum UNIQUE ? ... wenn du etwas nur einmal in der datenbank haben willst mache vorher ein SELECT ob es schon vorhanden ist ... denn das was du versuchst wäre missbrauch des exception-handling ... da du bewusst auf eine exception prüfen würdest die der driver liefert wenn eben versucht wird UNIQUE zu "brechen" ... also zwei mal der selbe wert ...
sowas macht man nicht ... der bessere weg wäre vorher mit dem select selbst zu prüfen und in der programm-logik zu verarbeiten ... extra den server darum bemühen und dann noch exception-handling missbrauchen ist der falsche ansatz ...
 
C

Camino

Gast
nein ...
wenn du ein feld beim anlegen der tabelle "DEFAULT <irgendwas>" angibst ... dann lässt du es einfach komplett aus dem statement raus ...
Na ja, aber ich brauch ja nicht immer den Default-Wert, manchmal wird ja auch was eingetragen. Dann bräuchte ich ja verschiedene Statements oder dynamisch erstellte. Oder seh ich das gerde irgendwie falsch?

warum UNIQUE ? ... wenn du etwas nur einmal in der datenbank haben willst mache vorher ein SELECT ob es schon vorhanden ist ... denn das was du versuchst wäre missbrauch des exception-handling ... da du bewusst auf eine exception prüfen würdest die der driver liefert wenn eben versucht wird UNIQUE zu "brechen" ... also zwei mal der selbe wert ...
sowas macht man nicht ... der bessere weg wäre vorher mit dem select selbst zu prüfen und in der programm-logik zu verarbeiten ... extra den server darum bemühen und dann noch exception-handling missbrauchen ist der falsche ansatz ...
Ich hab natürlich auch im Programm eine Überprüfung dieser Werte und eine Reaktion, wenn der identische Wert schon in der DB steht. Vielleicht hatte ich das UNIQUE nur noch aus Sicherheitsgründen dort stehen, damit auch wirklich keine identischen Werte dort einegtragen werden können.
 

irgendjemand

Top Contributor
naja ... statements dynamisch zusammenzukleben mag gehen ... aber es wird doch wohl keine X sonderfälle geben sondern vielleicht nur 3 oder 4 verschiedene ... oder ?
würde hier je nach situation dann mit switch das richtige auswählen ...


hmm ... gut ... aber diese "sicherheit" der datenbank durch UNIQUE kannst du ja nur prüfen wenn du im catch spezielle auf diese exception prüfst das eben ein "UNIQUE-DUPLICATE-ERROR" gefolgen ist .. und das ist nun mal schlechtes design wegen missbrauch des exception-handling ...
heißt : du darfst die datenbank nicht als letztes "rettungsboot" haben ... sondern musst deine software so konzipieren das es schon dort 100% ausgeschlossen wird ... was eben mit einem vorheringen SELECT möglich ist ...

ob man jetzt transactions dazu missbrauchen sollte ... hmm .. würde ich jedenfalls auch nicht machen
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
Kirby.exe PreparedStatement wird nicht ausgeführt Datenbankprogrammierung 5
V SQLite NullPointerException in preparedStatement.close(); Datenbankprogrammierung 8
Neumi5694 SQL-Statement Preparedstatement - try resource vs. Garbage Collector Datenbankprogrammierung 5
S JDBC PreparedStatement durchiterieren Datenbankprogrammierung 6
S CSV Datein in DB übernehmen:PreparedStatement bzw executeBatch() zu langsam Datenbankprogrammierung 11
P MySQL PreparedStatement vs. StoredProcedure vs. executeBatch Datenbankprogrammierung 1
P PreparedStatement IN-Funktion Datenbankprogrammierung 8
R PreparedStatement ohne Parameter? Datenbankprogrammierung 4
turmaline Oracle [PreparedStatement] Klammer fehlt Datenbankprogrammierung 9
J Problem bei Boolean in PreparedStatement Datenbankprogrammierung 5
M Variable in SQL SELECT * FROM ... WHERE mithilfe von PreparedStatement benutzen? Datenbankprogrammierung 28
D MySQL PreparedStatement mit c3p0 schlägt fehl. Warum? Datenbankprogrammierung 3
S Oracle Problem mit PreparedStatement.setString(1,"str") Datenbankprogrammierung 10
M MySQL preparedStatement und Anführungszeichen Datenbankprogrammierung 6
L MySQL Probleme mit PreparedStatement für SQL-Abfrage in Java Datenbankprogrammierung 2
G PreparedStatement und Transaktionen Datenbankprogrammierung 2
N Leeres Blob in ein PreparedStatement eintragen Datenbankprogrammierung 2
P PreparedStatement batch und getGeneratedKeys Datenbankprogrammierung 7
T MySQL PreparedStatement mit INSERTs langsam, Batch-Statement auch Datenbankprogrammierung 4
B H2 PreparedStatement SELECT * FROM ? Datenbankprogrammierung 4
M FindBugs und PreparedStatement aus einer Datei lesen Datenbankprogrammierung 11
Guybrush Threepwood PreparedStatement: execute() oder executeUpdate() Datenbankprogrammierung 3
R PreparedStatement mit verschiedenen Datenbanken Datenbankprogrammierung 2
R Frage zu PreparedStatement/ResultSet Datenbankprogrammierung 16
R Zugriff auf SQL im PreparedStatement Datenbankprogrammierung 4
W preparedStatement (MySQL - JDBC) Datenbankprogrammierung 5
Landei PreparedStatement Parameter mehrfach verwenden Datenbankprogrammierung 18
S Create Table mit PreparedStatement Datenbankprogrammierung 2
S Select mit PreparedStatement Datenbankprogrammierung 2
S PreparedStatement setArray(int i, java.sql.Array) Datenbankprogrammierung 17
M Preparedstatement SQL-string auslesen Datenbankprogrammierung 13
T PreparedStatement anzeigen Datenbankprogrammierung 10
A PreparedStatement im Servlet - Referenz speichern Datenbankprogrammierung 3
P PreparedStatement - Angabe des PK Datenbankprogrammierung 4
J Fehler beim PreparedStatement Datenbankprogrammierung 2
B PreparedStatement - anzahl ParameterValues Datenbankprogrammierung 6
J PreparedStatement Datenbankprogrammierung 5
C PreparedStatement Datenbankprogrammierung 2
R DB2 PreparedStatement Batches ungültige Reihenfolge Datenbankprogrammierung 4
Maxim6394 EclipseLink + SQLite | Unable to acquire a connection from driver [null] Datenbankprogrammierung 6
ma095 value NULL- Datenbank Postgresql Spring - intellij community Datenbankprogrammierung 0
P Herausfinden wann Query null zurück gibt? Datenbankprogrammierung 1
N DBUnit und null Datenbankprogrammierung 6
P Null Werte bei der Normalisierung Datenbankprogrammierung 2
Z ResultSet ist null warum? Datenbankprogrammierung 12
krgewb getDouble auch mit null möglich? Datenbankprogrammierung 2
D SQL Server Android App: 'int java.lang.String.length()' on a null object reference Datenbankprogrammierung 15
zhermann Data truncation: Incorrect date value: 'null' for column Datenbankprogrammierung 31
I Datenbankverbindung Oracle DB klappt nicht - getConnection returned null Datenbankprogrammierung 8
M Derby/JavaDB einen Null-Wert in die Datenbank schreiben Datenbankprogrammierung 7
D Oracle NullPointerException bei select mit Null Values Datenbankprogrammierung 5
T IllegalArgumentException: Person[ id=null ] is not a known entity type.??? Datenbankprogrammierung 0
C PostgreSQL JDBC + PostgreSQL: getLong liefert 0 statt NULL Datenbankprogrammierung 2
R JPA dynamisch auf NULL abfragen Datenbankprogrammierung 2
OnDemand LEFT JOIN id hat Null Datenbankprogrammierung 6
P executeQuery liefert null zurück Datenbankprogrammierung 5
P Datenbank- Abfrage mit null'en Datenbankprogrammierung 2
M HSQLDB EntityManager null? Datenbankprogrammierung 7
O MySQL PreparedStatements: int null Datenbankprogrammierung 7
S Null Pointer exception statement Datenbankprogrammierung 8
M JPA NOT NULL Datenbankprogrammierung 11
E H2 - Datenbankabfrage gibt NULL aus? Datenbankprogrammierung 4
Q java.lang.NullPointerException connection = null Datenbankprogrammierung 13
C Metadata der SessionFactory immer null Datenbankprogrammierung 2
N Connection bleibt null Datenbankprogrammierung 7
F Derby/JavaDB Exception - Cannot accept Null Value (help) Datenbankprogrammierung 10
G MySQL Timestamp null Datenbankprogrammierung 2
H Fehler bei null-Datum in MySQL-DB Datenbankprogrammierung 2
G getConnection() liefert null Datenbankprogrammierung 3
A MSSQL - Spalten mit der Option: NULL zulassen Datenbankprogrammierung 2
G Hibernate oneToMany Not null Datenbankprogrammierung 4
S Update mit null Datenbankprogrammierung 11
H Date null = 30.11.0002? Datenbankprogrammierung 6
P Fehler: result-set zeigt auf null, aber warum Datenbankprogrammierung 4
R Warum ist meine Connection null? Datenbankprogrammierung 6
P Wie übergebe ich einen NULL Wert in meinem Java-Programm? Datenbankprogrammierung 7
W RsultSet auf null abfragen funktioniert nicht Datenbankprogrammierung 4
D hibernate + null + primitive Datentypen Datenbankprogrammierung 2
F MySQL gibt nur null zurück Datenbankprogrammierung 3
G NULL-data processing. Datenbankprogrammierung 11

Ähnliche Java Themen

Neue Themen


Oben