hibernate/hibernate-orm · error · JDBCException
Could not create JDBC Clob
Error message
Could not create JDBC Clob
What it means
Thrown by BlobAndClobCreator.toJdbcClob when Hibernate converts an existing java.sql.Clob into a JDBC Clob that can be written through a PreparedStatement. When the dialect/environment says LOBs are created via the connection (useConnectionToCreateLob), Hibernate materializes the value with clob.getSubString(1, (int) clob.length()) and Connection.createClob(String); any SQLException from those calls is wrapped in a JDBCException with this message.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/BlobAndClobCreator.java:198
* Obtain a {@link Clob} instance which can be written to a JDBC
* {@link java.sql.PreparedStatement} using
* {@link java.sql.PreparedStatement#setClob(int, Clob)}.
*/
@Override
public Clob toJdbcClob(Clob clob) {
try {
if ( useConnectionToCreateLob ) {
// final Clob jdbcClob = createClob();
// clob.getCharacterStream().transferTo( jdbcClob.setCharacterStream(1) );
// return jdbcClob;
return createClob( clob.getSubString( 1, (int) clob.length() ) );
}
else {
return super.toJdbcClob( clob );
}
}
catch (SQLException e) {
throw new JDBCException( "Could not create JDBC Clob", e );
}
// catch (IOException e) {
// throw new HibernateException( "Could not create JDBC Clob", e );
// }
}
/**
* Obtain an {@link NClob} instance which can be written to a JDBC
* {@link java.sql.PreparedStatement} using
* {@link java.sql.PreparedStatement#setNClob(int, NClob)}.
*/
@Override
public NClob toJdbcNClob(NClob clob) {
try {
if ( useConnectionToCreateLob ) {
// final NClob jdbcClob = createNClob();
// clob.getCharacterStream().transferTo( jdbcClob.setCharacterStream(1) );
// return jdbcClob;View on GitHub (pinned to fad1729dce)
Solutions
- Materialize the value into a String or a Hibernate-created Clob while the owning connection is still open (e.g. Hibernate.getLobHelper().createClob(text) or map the attribute as String/@Lob)
- Keep the Session and its connection open until the flush that binds the Clob completes; do not reuse Clobs across transactions
- Inspect the wrapped SQLException (getCause()) to see the driver-level reason and fix privileges/driver accordingly
- Upgrade the JDBC driver if Connection.createClob is known to be buggy for your database version
Example fix
// before: locator-backed Clob reused after its connection closed entity.setDoc(clobFromPreviousSession); // fails at flush // after: materialize while the source connection is open String text = clob.getSubString(1, (int) clob.length()); entity.setDoc(session.getLobHelper().createClob(text));
Defensive patterns
Strategy: try-catch
Validate before calling
// materialize while the owning connection is alive, before binding
String text;
try {
text = clob.getSubString(1, (int) clob.length());
}
catch (SQLException e) {
throw new IllegalStateException("source Clob no longer valid", e);
}
entity.setText(text); // String/@Lob mapping avoids locator issues Try / catch
try {
session.persist(entity);
session.flush();
}
catch (JDBCException e) {
SQLException sql = e.getSQLException();
// inspect sql.getErrorCode()/SQLState for the driver-level LOB failure
log.warn("LOB bind failed: {}", sql, e);
} Prevention
- Map large text to String or @Lob String instead of java.sql.Clob
- Never reuse a Clob obtained from another session/transaction
- Keep the session and connection open until flush completes
When it happens
Trigger: Persisting or binding an attribute of type java.sql.Clob while the source Clob is invalid: its LOB locator was freed (connection/transaction that produced it already committed or closed), Connection.createClob() fails on the driver, or the Clob is larger than Integer.MAX_VALUE so the (int) length cast/getSubString fails.
Common situations: Copying a Clob read in one transaction into an entity saved by another session; detaching entities that hold locator-backed Clobs; older Oracle/Sybase drivers that invalidate LOB locators after commit; DB users lacking LOB creation privileges.
Related errors
- Unable to set CLOB string after creation
- Start position 1-based; must be 1 or more.
- Start position [${start}] cannot exceed overall CLOB length
- Length must be great-than-or-equal to zero.
- Can't deal with Clobs larger than 'Integer.MAX_VALUE'
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/f313120b6bb74443.
Report an issue: GitHub.