Leeres Blob in ein PreparedStatement eintragen

NBK

Mitglied
Ahoi zusammen,

kann mir jemand ein funktionierendes Beispiel nennen, wie ich ein leeres Blob in ein PreparedStatement eintrage?

Ich mache gerade folgendes: ich versuche eine Klasse zu schreiben, die generisch Tabellen aus einer Datenbank in eine andere überträgt. Der zugriff erfolgt über JDBC, aber ich kann weder vorhersehen, um welches Datenbanksystem es sich zur Laufzeit handeln wird, noch den Aufbau und Inhalt der Tabellen. Ich bekomme zwei Connections übergeben, eine zum Lesen und eine zum Schreiben, und los geht's. Zunächst ermittle ich die Tabellen und den Tabellenaufbau, anschließend lese ich jeweils aus einer Tabelle die Daten ein und schreibe sie in eine andere Tabelle. Die Tabellen können Blobs enthalten, ggf. auch mehrere je Zeile.

Hierfür verwende ich ein PreparedStatement, das für jede Tabelle einmal angelegt wird und für jede Zeile dann neu bestückt wird. Das klappt auch alles ganz prima, aber wenn ich bei der Quelltabelle auf ein Blob-Feld ohne Inhalt stoße, dann knallt es immer beim Schreiben. Ich habe schon alles mögliche versucht, wie ich das leere Blob da eintragen könnte, zum Beispiel setBlob(null) oder setBinaryStream mit unterschiedlichen Streams, aber irgendwo kracht es immer, meistens mit einer NullPointerException. Es funktioniert nur, wenn ich in einem solchen Fall mindestens ein Byte in das Ziel-Blob eintrage. Aber das ist natürlich inhaltlich nicht korrekt, das Ziel-Blob soll schließlich NULL sein.

Deshalb möchte ich mal rumfragen, ob mir jemand den korrekten Weg nennen kann, ein leeres Blob in ein PreparedStatement einzutragen. Vielen Dank für jeden Tipp. Und schönes Wochenende.

NBK

- Hier zum Anschauen mal die ganze Klasse. Momentan schreibe ich die Blobs in ein Temporärverzeichnis raus und lese sie von dort wieder ein; wenn sie leer sind, schreibe ich eine Null in das Zielblob, was wie gesagt nicht korrekt ist, aber wenigstens funktioniert. Wer sich's ansehen möchte, sollte bei der Methode copyData() anfangen.

Java:
public class JdbcMoverSimple implements JdbcMover {
	private Connection sourceconnection;
	private Connection destinationconnection;
	private String workdir;
	private boolean sourcetablesAnalyzed = false;

	private final int MAXVARCHAR = 4000;
	private final List<TableData> tables = new ArrayList<TableData>();

	public class TableData {
		private String tableName;
		private final List<ColumnData> tableColumns = new ArrayList<ColumnData>();

		public String getTableName() {
			return this.tableName;
		}

		public void setTableName(final String tableName) {
			this.tableName = tableName;
		}

		public List<ColumnData> getTableColumns() {
			return this.tableColumns;
		}

		public boolean isSQLCompatible() {
			boolean result = true;
			for (final ColumnData columndata : this.getTableColumns()) {
				result = result && columndata.isSQLCompatible();
			}
			return result;
		}

	}

	private class ColumnData {
		private String columnName;
		private String columnClassName;
		private String columnTypeName;
		private int columnSize;
		private int columnScale; // Nachkommastellen
		private int columnIndex;
		private int columnType;

		public String getColumnName() {
			return this.columnName;
		}

		public boolean isSQLCompatible() {
			// Ausschließen, dass SQL-Schlüsselworte als Feldnamen verwendet
			// werden
			// erstmal nur WHERE ausgeschlossen
			boolean result = true;
			if (this.columnName.toUpperCase().equals("WHERE")) {
				result = false;
			}
			return result;
		}

		public void setColumnName(final String columnName) {
			this.columnName = columnName;
		}

		public void setColumnClassName(final String columnClassName) {
			this.columnClassName = columnClassName;
		}

		public void setColumnSize(final int columnSize) {
			this.columnSize = columnSize;
		}

		public void setColumnType(final int columnType) {
			this.columnType = columnType;
		}

		public void setColumnScale(final int columnScale) {
			this.columnScale = columnScale;
		}

		public String getColumnSQLDefinition() {
			String result;
			if (this.columnName.toUpperCase().equals("WHERE")) {
				result = "WHEREWHERE ";
			} else {
				result = this.columnName + " ";
			}

			if (this.columnClassName == "java.lang.String") {
				if (this.columnSize > JdbcMoverSimple.this.MAXVARCHAR) {
					result += "VARBINARY(MAX)";
				} else {
					result += "VARCHAR(" + this.columnSize + ")";
				}
			} else if (this.columnClassName == "java.lang.Integer") {
				result += "INTEGER";
			} else if (this.columnClassName == "java.math.BigDecimal") {
				result += "DECIMAL(" + this.columnSize + ", "
						+ this.columnScale + ")";
			} else if (this.columnClassName == "java.sql.Date") {
				result += "DATETIME";
			} else if (this.columnClassName == "java.lang.Boolean") {
				result += "BIT";
			} else {
				// Wir verwenden den Original-Spaltentyp
				result += this.columnTypeName;
			}
			return result;
		}


		public void setColumnTypeName(final String columnTypeName) {
			this.columnTypeName = columnTypeName;
		}

		/**
		 * Ein vorbereitetes Statement mit dem Wert für diese Spalte belegen
		 * 
		 * @param targetstmt
		 * @param res
		 * @param useTempindex
		 */
		public void setStatementValue(final PreparedStatement targetstmt,
				final ResultSet res) {

			final int index = this.columnIndex;

			try {
				final Object value = res.getObject(this.getColumnName());
				// System.out.println("   " + this.getColumnName() +
				// " Value: "
				// + ((null == value) ? "null" : value.toString()));
				if (null == value) {
					targetstmt.setNull(index, this.columnType);
				} else {
					targetstmt.setObject(index, value);
				}
			} catch (final Exception e) {
				throw new ProcessException(
						"Fehler bei der Zuweisung von Daten in Feld "
								+ this.columnName + " (" + this.columnClassName
								+ ")", e);
			}

		}

		public void setColumnIndex(final int columnIndex) {
			this.columnIndex = columnIndex;
		}

		public int getColumnIndex() {
			return this.columnIndex;
		}

		public boolean isBlob() {
			return (this.columnType == Types.LONGVARBINARY);
		}


		/**
		 * Ein vorbereitetes Statement mit einem InputStream für ein Blob
		 * versehen und füllen
		 * 
		 * @param targetstmt
		 * @param workdir
		 */
		public void writeBlob(final PreparedStatement targetstmt,
				final String workdir) {

			final int index = this.columnIndex;
			try {
				final File blobfile = new File(this.getFileName(workdir));
				final FileInputStream fis = new FileInputStream(blobfile);
				targetstmt.setBinaryStream(index, fis, (int) blobfile.length());
			} catch (final Exception e) {
				throw new ProcessException(
						"Fehler bei der Zuweisung von Blob-Daten in Feld "
								+ this.columnName + " (" + this.columnClassName
								+ ")", e);
			}

		}

		/**
		 * Ein Blob aus dem Resultset in ein File auslesen
		 * 
		 * @param res
		 * @param workdir
		 */
		public void readBlob(final ResultSet res, final String workdir) {

			final String fileName = this.getFileName(workdir);
			int count = 0;
			try {
				final InputStream is = res.getBinaryStream(this
						.getColumnIndex());

				final File blobfile = new File(fileName);
				final FileOutputStream fos = new FileOutputStream(blobfile);
				if (null == is) {
					// Leere Datei schreiben
					fos.write(0);
				} else {
					final byte[] buffer = new byte[4096];
					// Get the binary stream of our BLOB data
					while (is.read(buffer) > 0) {
						fos.write(buffer);
						count++;
						System.out.println("   schreibe Puffer: " + count);
					}
				}
				fos.close();
			} catch (final Exception e) {
				throw new ProcessException(
						"Fehler bei der Zuweisung von Blob-Daten in Feld "
								+ this.columnName + " (" + this.columnClassName
								+ ")", e);
			}

		}

		private String getFileName(final String workdir) {
			String result = workdir;
			if (result.endsWith("/")) {
			} else {
				result += "/";
			}
			result += "tempblob" + this.columnIndex + ".bin";
			return result;
		}
	}

	/**
	 * {@inheritDoc}
	 */
	public void setSourceConnection(final Connection conn) {
		this.sourceconnection = conn;
		this.sourcetablesAnalyzed = false;

	}

	/**
	 * {@inheritDoc}
	 */
	public Connection getSourceConnection() {
		return this.sourceconnection;
	}

	/**
	 * {@inheritDoc}
	 */
	public void setDestinationConnection(final Connection conn) {
		this.destinationconnection = conn;

	}

	/**
	 * {@inheritDoc}
	 */
	public Connection getDestinationConnection() {
		return this.destinationconnection;
	}

	/**
	 * {@inheritDoc}
	 */
	public void move(final String tablename, final String workDirectory)
			throws ProcessException {
		if (!this.sourcetablesAnalyzed) {
			this.analyzeDataStructure();
		}
		final TableData tabledata = this.findTabledataFor(tablename);
		this.workdir = workDirectory;
		if (null == tabledata) {
			throw new ProcessException(
					"Die Tabelle "
							+ tablename
							+ " existiert nicht in der Quelldatenbank oder ist nicht SQL-kompatibel.",
					null);

		} else {
			if (this.createTable(tabledata)) {
				this.copyData(tabledata);
			}
		}
	}

	private boolean createTable(final TableData tabledata)
			throws ProcessException {
		final Connection connection = this.getDestinationConnection();
		String statement = null;
		Statement stmt;
		boolean result = false;
		try {
			stmt = connection.createStatement();
			statement = "DROP TABLE " + tabledata.getTableName();
			// System.out.println("   " + statement);
			try {
				stmt.execute(statement);
			} catch (final Exception e) {
				// Drop table darf schiefgehen
			}

			statement = "CREATE TABLE " + tabledata.getTableName() + " (";
			for (final ColumnData columndata : tabledata.getTableColumns()) {
				statement += columndata.getColumnSQLDefinition() + ", ";
			}
			// Letztes Komma wieder weg
			statement = statement.substring(0, statement.length() - 2);
			statement += ")";
			// System.out.println("   " + statement);
			stmt.execute(statement);
			stmt.close();
			result = true;
		} catch (final SQLException e) {
			throw new ProcessException(e.getMessage()
					+ ((null == statement) ? "" : " Statement: " + statement),
					e);
		}
		return result;
	}

	private void copyData(final TableData tabledata) throws ProcessException {
		final Connection targetconnection = this.getDestinationConnection();
		String sourcestatement = null, targetstatement = null;
		Statement sourcestmt;
		PreparedStatement targetstmt;
		try {
			final Connection sourceconnection = this.getSourceConnection();
			sourcestmt = sourceconnection.createStatement();

			// Statements zum Lesen und Schreiben zusammenbauen
			sourcestatement = "SELECT ";
			targetstatement = "INSERT INTO " + tabledata.getTableName() + " (";
			for (final ColumnData columndata : tabledata.getTableColumns()) {
				sourcestatement += columndata.getColumnName() + ", ";
				targetstatement += columndata.getColumnName() + ", ";
			}
			// Letztes Komma wieder weg
			sourcestatement = sourcestatement.substring(0,
					sourcestatement.length() - 2)
					+ " FROM " + tabledata.getTableName();
			targetstatement = targetstatement.substring(0,
					targetstatement.length() - 2)
					+ ") VALUES (";
			for (@SuppressWarnings("unused")
			final ColumnData columndata : tabledata.getTableColumns()) {
				targetstatement += "?, ";
			}
			// Letztes Komma entfernen
			targetstatement = targetstatement.substring(0,
					targetstatement.length() - 2)
					+ ")";
			targetstmt = targetconnection.prepareStatement(targetstatement);

			// Daten aus der Quelltabelle lesen
			// System.out.println("   " + sourcestatement);
			final ResultSet res = sourcestmt.executeQuery(sourcestatement);

			while (res.next()) {
				// Erstmal die einfachen Datentypen übertragen
				for (final ColumnData columndata : tabledata.getTableColumns()) {
					if (columndata.isBlob()) {

					} else {
						columndata.setStatementValue(targetstmt, res);
					}
				}
				// Nun die Blobs auslesen
				for (final ColumnData columndata : tabledata.getTableColumns()) {
					if (columndata.isBlob()) {
						columndata.readBlob(res, this.workdir);
					}
				}
				// und die Blobs schreiben
				for (final ColumnData columndata : tabledata.getTableColumns()) {
					if (columndata.isBlob()) {
						columndata.writeBlob(targetstmt, this.workdir);
					}
				}
				targetstmt.executeUpdate();
			}
			sourcestmt.close();
			targetstmt.close();

		} catch (final Exception e) {
			throw new ProcessException(e.getMessage()
					+ ((null == sourcestatement) ? "" : " Source-Statement: "
							+ sourcestatement)
					+ ((null == targetstatement) ? "" : " Insert-Statement: "
							+ targetstatement), e);
		}

	}

	public List<TableData> getTables() {
		return this.tables;
	}

	private TableData findTabledataFor(final String tablename) {
		TableData tabledata = null;
		for (final TableData td : this.tables) {
			if (td.getTableName().equals(tablename)) {
				tabledata = td;
			}
		}
		return tabledata;
	}

	/**
	 * Analysiert die gesamte Datenstruktur der Quelldatenbank und merkt sie
	 * sich.
	 */
	public void analyzeDataStructure() throws ProcessException {
		try {

			final Connection connection = this.getSourceConnection();

			final DatabaseMetaData meta = connection.getMetaData();
			final ResultSet res = meta.getTables(null, null, null,
					new String[] { "TABLE" });

			this.tables.clear();
			TableData tabledata;
			ColumnData columndata;
			ResultSet resSelect;
			Statement stmSelect;
			ResultSetMetaData rsmdSelect;
			int numColumnsSelect;
			String tableName;
			String statement;

			// System.out.println("List of tables: ");
			while (res.next()) {
				tableName = res.getString("TABLE_NAME");
				// System.out.println("   " + ", " +
				// res.getString("table_owner")
				// + ", " + tableName + ", " + res.getString("TABLE_TYPE")
				// + ", " + res.getString("REMARKS"));

				tabledata = new TableData();
				tabledata.setTableName(tableName);

				// Tabellenstruktur ermitteln
				try {
					stmSelect = connection.createStatement();
					statement = "SELECT * FROM " + tableName;
					resSelect = stmSelect.executeQuery(statement);
					rsmdSelect = resSelect.getMetaData();
					numColumnsSelect = rsmdSelect.getColumnCount();

					for (int i = 1; i <= numColumnsSelect; i++) {
						columndata = new ColumnData();
						columndata.setColumnName(rsmdSelect.getColumnName(i));
						columndata.setColumnClassName(rsmdSelect
								.getColumnClassName(i));
						columndata.setColumnTypeName(rsmdSelect
								.getColumnTypeName(i));
						columndata.setColumnType(rsmdSelect.getColumnType(i));
						columndata.setColumnSize(rsmdSelect
								.getColumnDisplaySize(i));
						columndata.setColumnScale(rsmdSelect.getScale(i));
						columndata.setColumnIndex(i);
						tabledata.getTableColumns().add(columndata);

						// System.out.println("   " +
						// rsmdSelect.getColumnName(i)
						// + " Typ: " + rsmdSelect.getColumnType(i) + " ("
						// + rsmdSelect.getColumnTypeName(i) + ")"
						// + " Klasse: "
						// + rsmdSelect.getColumnClassName(i)
						// + " DisplaySize: "
						// + rsmdSelect.getColumnDisplaySize(i)
						// + " Scale: " + rsmdSelect.getScale(i)
						// + " Label: " + rsmdSelect.getColumnLabel(i));

					}
					stmSelect.close();
					// Sonderfall: Feldname "where" muss ausgeschlossen werden,
					// Tabelle wird ignoriert
					if (tabledata.isSQLCompatible()) {
						this.tables.add(tabledata);
					}
				} catch (final Exception e) {
					// Tabelle kann nicht gelesen werden, wahrscheinlich leer.
					throw new ProcessException(
							"Fehler beim Ermitteln der Datenstrukturen in der Quelldatenbank: "
									+ e.getMessage(), e);
				}

			}
			res.close();

			this.sourcetablesAnalyzed = true;
		} catch (final Exception e) {
			throw new ProcessException(
					"Fehler beim Ermitteln der Datenstrukturen in der Quelldatenbank: "
							+ e.getMessage(), e);
		}

	}
}
 

Michael...

Top Contributor
Hab den vielen Code jetzt nicht angeschaut, aber kannst Du bei einem leeren Blob nicht einfach
Code:
null
an das PreparedStatement übergeben oder besser noch gar nichts in die Datenbank schreiben?
 

NBK

Mitglied
Hab den vielen Code jetzt nicht angeschaut, aber kannst Du bei einem leeren Blob nicht einfach
Code:
null
an das PreparedStatement übergeben oder besser noch gar nichts in die Datenbank schreiben?

Wenn ich null übergebe, bekomme ich eine Nullpointerexception. Und "gar nichts" schreiben geht nicht, ich muss ja die Zeile mit den übrigen Daten in die DB schreiben. Das PreparedStatement enthält alle Felder, und deshalb muss ich auch alle Felder befüllen.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
PaulG Leeres ResultSet initialisieren Datenbankprogrammierung 6
M Hibernate liefert mir bei many-to-one leeres Feld Datenbankprogrammierung 5
A Leeres ResultSet mit H2 unter Vista Datenbankprogrammierung 3
Y Hibernate - 1:1 Beziehung liefert leeres Objekt Datenbankprogrammierung 19
@ Like-Klausel; NPE bzw. leeres ResultSet Datenbankprogrammierung 4
R MySQL + JDBC: Leeres datetime-Feld einlesen Datenbankprogrammierung 4
S .leeres Resultset abfangen Datenbankprogrammierung 2
krgewb Breite und Höhe von Blob Datenbankprogrammierung 7
H Oracle Resize eines Images in Java und Rückgabe des Image als BLOB an die Oracle Datebank Datenbankprogrammierung 14
H Java Class zum komprimieren von Jpeg-Images zum Einbinden in Oracle DB - Bild als blob (in und out) Datenbankprogrammierung 23
D MySQL Sicherheitslücke als Blob? Datenbankprogrammierung 3
buggy84 MySQL BLOB Geschwindigkeit Datenbankprogrammierung 16
L H2 Blob Dateien in der DB komprimieren? Datenbankprogrammierung 8
L H2 Blob Spalte im Client anzeigen Datenbankprogrammierung 2
E Wie kann man das Problem mit der BLOB-Spalte lösen? Datenbankprogrammierung 1
E Wie kann ich textdateien, die als BLOB abgespeichert sind, aus der Datenbanktabelle auslesen? Datenbankprogrammierung 23
E Wie kann man BLOB-Spalten in DB2 einfügen? Datenbankprogrammierung 9
R MySQL Blob aus DB auslesen und einer Tabelle ausgeben Datenbankprogrammierung 7
J BLOB to ImageIcon? Datenbankprogrammierung 3
Kenan89 Sinnvoller URL oder BLOB? Datenbankprogrammierung 2
F H2:Wie kann man insert eine Reihe "int" wert als blob in table? Datenbankprogrammierung 12
C MySQL Fragen zu BLOB zu byte[], Date zu java.util.Date uvm. Datenbankprogrammierung 6
D Blob MimeTyp auslesen Datenbankprogrammierung 2
P MySQL Objekt aus BLOB auslesen Datenbankprogrammierung 3
M Problem Array in BLOB-Feld in DerbyDB zu speichern Datenbankprogrammierung 5
C MP3 in DB als Blob, wieder auslesen und als MP3 speichern??? Datenbankprogrammierung 8
S BLOB in Datei speichern Datenbankprogrammierung 8
S Hibernate Blob mit Stream speichern Datenbankprogrammierung 3
V PostgreSQL langsam (Blob) Datenbankprogrammierung 10
G Blob aus Oracle-Datenbank Datenbankprogrammierung 2
O Vector als Blob in Oracle Datenbank speichern Datenbankprogrammierung 3
D Insert Oracle BLOB Datenbankprogrammierung 1
B Java Derby Datenbank mit CLOB & BLOB Datenbankprogrammierung 5
J Bild aus Mysql Blob in Webseite einbinden Datenbankprogrammierung 9
H Blob erzeugen Datenbankprogrammierung 2
T Inhalt von Blob in Console ausgeben Datenbankprogrammierung 2
G Sybase IMAGE-Daten zu MySQL als BLOB schreiben. Datenbankprogrammierung 2
T Datei (Blob) mit verknüpfter Software öffnen? Datenbankprogrammierung 4
G File nach Blob konvertieren ? Datenbankprogrammierung 6
G JPEG to BLOB Datenbankprogrammierung 7
H File into blob Datenbankprogrammierung 3
A Blob in Oracle-DB einfügen (veraltete Methode) Datenbankprogrammierung 3
EagleEye Blob -> backup Datenbankprogrammierung 6
Y Problem mit Ablage einer Datei in einer Datenbank als BLOB Datenbankprogrammierung 6
O Oracle Blob in MySQL Blob umwandeln Datenbankprogrammierung 2
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
C PreparedStatement und null Datenbankprogrammierung 13
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
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

Ähnliche Java Themen

Neue Themen


Oben