Storing and retrieving URIs in a database using Java can sometimes be tricky, especially when the URI is stored in a VARBINARY column. Developers often encounter issues when reading such data from the database, resulting in unexpected symbols or deserialization errors. In this article, we will explore how to correctly retrieve and handle VARBINARY-stored URIs using JDBC and Java’s PreparedStatement.
Understanding the Problem
When storing a URI in a VARBINARY column, it can either be stored as a raw UTF-8 encoded string or as a serialized Java object. The retrieval approach depends on the format in which the data was stored. A common mistake developers make is assuming that VARBINARY data can be directly converted to a string without proper encoding or deserialization.
A typical issue occurs when a developer tries to retrieve a VARBINARY column using getString() or getBytes() and encounters unreadable characters such as:
??♣srjava.net.URI?☺x.C?I?♥☺L♠stringt↕Ljava/lang/String;xpt(https://192.168.50.118:18081/1.0.6/tokenx
This usually indicates that the data is stored as a serialized Java object rather than a simple UTF-8 string.
Correctly Storing and Retrieving URIs
Storing URIs as UTF-8 Encoded Strings
The simplest and most recommended way to store URIs in a database is to save them as VARCHAR or TEXT. However, if a VARBINARY column is necessary, ensure the URI is encoded as bytes before storage.
PreparedStatement stmt = connection.prepareStatement("INSERT INTO bank_accounts (acc_balances_uri) VALUES (?)");
String uriString = "https://192.168.50.118:18081/1.0.6/token";
stmt.setBytes(1, uriString.getBytes(StandardCharsets.UTF_8));
stmt.executeUpdate();
Retrieving and Decoding UTF-8 Stored URIs
If the URI was stored as a UTF-8 encoded string in a VARBINARY column, use getBytes() and convert it back to a string:
if (resultSet.getBytes("acc_balances_uri") != null) {
String uriString = new String(resultSet.getBytes("acc_balances_uri"), StandardCharsets.UTF_8);
bank.setAccountBalancesBaseUri(URI.create(uriString));
}
Handling Serialized URI Objects
If the URI was stored as a serialized java.net.URI object, it must be deserialized properly when retrieved. Use ObjectOutputStream to store the serialized object and ObjectInputStream to read it back.
Storing a Serialized URI Object
PreparedStatement stmt = connection.prepareStatement("INSERT INTO bank_accounts (acc_balances_uri) VALUES (?)");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(URI.create("https://192.168.50.118:18081/1.0.6/token"));
oos.flush();
stmt.setBytes(1, bos.toByteArray());
stmt.executeUpdate();
Retrieving a Serialized URI Object
if (resultSet.getBytes("acc_balances_uri") != null) {
try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(resultSet.getBytes("acc_balances_uri")))) {
Object obj = ois.readObject();
if (obj instanceof URI) {
bank.setAccountBalancesBaseUri((URI) obj);
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
Best Practices
- Use VARCHAR/TEXT Instead of VARBINARY: Whenever possible, store URIs as plain strings to avoid unnecessary complexity.
- Ensure Consistent Encoding: If using
VARBINARY, always encode and decode usingStandardCharsets.UTF_8. - Use Serialization Only When Necessary: Avoid serializing objects unless there is a strict requirement.
- Handle Exceptions Properly: When deserializing objects, always handle potential
IOExceptionorClassNotFoundExceptionerrors. - Validate URIs After Retrieval: Always verify that the retrieved data is a valid URI before using it.
Conclusion
Handling VARBINARY-stored URIs in Java requires understanding how the data is stored and retrieved. The best approach is to store URIs as simple strings, but if VARBINARY must be used, ensure consistent encoding and decoding methods. Following these best practices will help you avoid common pitfalls and ensure smooth database interactions with Java and JDBC.


