Skip to content

Commit 8e9d1d4

Browse files
authored
IGNITE-23380 Add JDBC thin BLOB and CLOB docs (#13259)
Codex co-authored-by: Dmitriy Pavlov <dpavlov@apache.org>
1 parent 083199e commit 8e9d1d4

2 files changed

Lines changed: 89 additions & 8 deletions

File tree

docs/_docs/SQL/JDBC/jdbc-driver.adoc

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,30 @@ while (rs.next()) {
231231
}
232232
----
233233

234+
=== BLOB and CLOB Values
235+
236+
The JDBC Thin driver supports standard `java.sql.Blob` and `java.sql.Clob` objects for binary and character values.
237+
Store BLOB data in SQL `BINARY` columns and CLOB data in SQL `VARCHAR` columns.
238+
239+
[NOTE]
240+
====
241+
BLOB and CLOB support in the JDBC Thin driver is available since Apache Ignite 2.17.
242+
CLOB values are intentionally stored in SQL `VARCHAR` columns, and BLOB values are stored in SQL `BINARY` columns.
243+
====
244+
245+
You can create values with `Connection.createBlob()` and `Connection.createClob()`, bind them with `PreparedStatement.setBlob()` and `PreparedStatement.setClob()`, and read them with `ResultSet.getBlob()` and `ResultSet.getClob()`.
246+
247+
[source,java]
248+
----
249+
include::{javaFile}[tags=blob-clob, indent=0]
250+
----
251+
252+
BLOB values also support binary stream APIs, including `PreparedStatement.setBlob(int, InputStream)`, `PreparedStatement.setBlob(int, InputStream, long)`, `PreparedStatement.setBinaryStream()`, `ResultSet.getBinaryStream()`, and `Blob.getBinaryStream()`.
253+
When a stream length is provided, it must be non-negative and must match the actual number of bytes read from the stream.
254+
255+
CLOB values are supported through `Clob` object methods such as `setString()`, `getSubString()`, and `getCharacterStream()`.
256+
Reader-based CLOB setter APIs, such as `PreparedStatement.setClob(int, Reader)`, and direct `ResultSet.getCharacterStream()` calls are not supported.
257+
234258
=== Partition Awareness [[partition-awareness]]
235259

236260
Partition awareness is a feature that makes the JDBC driver "aware" of the partition distribution in the cluster.

docs/_docs/code-snippets/java/src/main/java/org/apache/ignite/snippets/JDBCThinDriver.java

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,20 @@
1616
*/
1717
package org.apache.ignite.snippets;
1818

19+
import java.io.ByteArrayInputStream;
20+
import java.io.InputStream;
21+
import java.nio.charset.StandardCharsets;
22+
import java.sql.Blob;
23+
import java.sql.Clob;
1924
import java.sql.Connection;
2025
import java.sql.DriverManager;
2126
import java.sql.PreparedStatement;
2227
import java.sql.ResultSet;
2328
import java.sql.SQLException;
2429

30+
import org.apache.ignite.Ignite;
2531
import org.apache.ignite.IgniteJdbcThinDataSource;
32+
import org.apache.ignite.Ignition;
2633

2734
public class JDBCThinDriver {
2835

@@ -132,6 +139,61 @@ void partitionAwareness() throws ClassNotFoundException, SQLException {
132139
conn.close();
133140
}
134141

142+
void blobAndClob() throws ClassNotFoundException, SQLException {
143+
144+
Connection conn = getConnection();
145+
// tag::blob-clob[]
146+
// CLOB values are stored in VARCHAR columns, and BLOB values are stored in BINARY columns.
147+
conn.createStatement().executeUpdate(
148+
"CREATE TABLE IF NOT EXISTS DocumentStore (id INT PRIMARY KEY, payload BINARY, body VARCHAR)");
149+
150+
byte[] payload = "binary payload".getBytes(StandardCharsets.UTF_8);
151+
152+
PreparedStatement insert = conn.prepareStatement(
153+
"INSERT INTO DocumentStore(id, payload, body) VALUES (?, ?, ?)");
154+
155+
Blob blob = conn.createBlob();
156+
blob.setBytes(1, payload);
157+
158+
Clob clob = conn.createClob();
159+
clob.setString(1, "large text body");
160+
161+
insert.setInt(1, 1);
162+
insert.setBlob(2, blob);
163+
insert.setClob(3, clob);
164+
insert.executeUpdate();
165+
166+
PreparedStatement streamInsert = conn.prepareStatement(
167+
"INSERT INTO DocumentStore(id, payload, body) VALUES (?, ?, ?)");
168+
169+
streamInsert.setInt(1, 2);
170+
streamInsert.setBlob(2, new ByteArrayInputStream(payload), payload.length);
171+
streamInsert.setString(3, "large text body");
172+
streamInsert.executeUpdate();
173+
174+
PreparedStatement select = conn.prepareStatement("SELECT payload, body FROM DocumentStore WHERE id = ?");
175+
176+
select.setInt(1, 1);
177+
178+
ResultSet rs = select.executeQuery();
179+
180+
if (rs.next()) {
181+
Blob selectedBlob = rs.getBlob("payload");
182+
byte[] selectedPayload = selectedBlob.getBytes(1, (int)selectedBlob.length());
183+
184+
Clob selectedClob = rs.getClob("body");
185+
String selectedBody = selectedClob.getSubString(1, (int)selectedClob.length());
186+
187+
InputStream selectedPayloadStream = rs.getBinaryStream("payload");
188+
189+
assert selectedPayload.length == payload.length;
190+
assert selectedBody.equals("large text body");
191+
assert selectedPayloadStream != null;
192+
}
193+
// end::blob-clob[]
194+
conn.close();
195+
}
196+
135197
void handleException() throws ClassNotFoundException, SQLException {
136198

137199
Connection conn = getConnection();
@@ -217,21 +279,16 @@ void errorCodes() throws ClassNotFoundException, SQLException {
217279
}
218280

219281
public static void main(String[] args) throws Exception {
220-
// Ignite ignite = Util.startNode();
282+
Ignite ignite = Ignition.start();
221283
try {
222284
JDBCThinDriver j = new JDBCThinDriver();
223285

224-
// j.getConnection();
225-
// j.multipleEndpoints();
226-
// j.connectionFromDatasource();
227-
// j.partitionAwareness();
228-
229-
j.ssl();
286+
j.blobAndClob();
230287
} catch (Exception e) {
231288
e.printStackTrace();
232289
System.exit(1);
233290
} finally {
234-
// ignite.close();
291+
ignite.close();
235292
}
236293
}
237294
}

0 commit comments

Comments
 (0)