hibernate/hibernate-orm · error · JDBCException

Could not create JDBC Blob

Error message

Could not create JDBC Blob

What it means

BlobAndClobCreator.toJdbcBlob converts a Blob into a JDBC-usable form: with useConnectionToCreateLob it reads all bytes via blob.getBytes(1, (int) blob.length()) and writes them into a freshly created JDBC Blob; otherwise it delegates to the non-contextual parent. Any SQLException on that path is wrapped as JDBCException('Could not create JDBC Blob'). Note the (int) cast on length(): BLOBs larger than Integer.MAX_VALUE overflow before the driver is even reached.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/BlobAndClobCreator.java:172

	 * Obtain a {@link Blob} instance which can be written to a JDBC
	 * {@link java.sql.PreparedStatement} using
	 * {@link java.sql.PreparedStatement#setBlob(int, Blob)}.
	 */
	@Override
	public Blob toJdbcBlob(Blob blob) {
		try {
			if ( useConnectionToCreateLob ) {
//				final Blob jdbcBlob = createBlob();
//				blob.getBinaryStream().transferTo( jdbcBlob.setBinaryStream(1) );
//				return jdbcBlob;
				return createBlob( blob.getBytes( 1, (int) blob.length() ) );
			}
			else {
				return super.toJdbcBlob( blob );
			}
		}
		catch (SQLException e) {
			throw new JDBCException( "Could not create JDBC Blob", e );
		}
//		catch (IOException e) {
//			throw new HibernateException( "Could not create JDBC Blob", e );
//		}
	}

	/**
	 * 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;

View on GitHub (pinned to fad1729dce)

Solutions

  1. Enable hibernate.jdbc.lob.non_contextual_creation=true to use the non-contextual parent path (stream-based binding, no byte[] copy)
  2. Upgrade the JDBC driver if createBlob()/setBytes() is the failing link
  3. For BLOBs over 2GB, bind via setBinaryStream/stream LobCreator paths instead of toJdbcBlob
  4. Check the wrapped SQLException to identify which call failed (getBytes vs setBytes)

Example fix

# before: contextual path, byte[] copy (also caps at 2GB via (int) cast)
<property name="hibernate.jdbc.lob.non_contextual_creation" value="false"/>

# after
<property name="hibernate.jdbc.lob.non_contextual_creation" value="true"/>
Defensive patterns

Strategy: fallback

Validate before calling

// guard the 2GB int-overflow and driver weakness before converting
if ( blob.length() > Integer.MAX_VALUE ) {
    throw new IllegalArgumentException("BLOB exceeds 2GB; bind via stream instead of toJdbcBlob");
}

Try / catch

try {
    return lobCreator.toJdbcBlob(blob);
} catch (JDBCException e) {
    // fall back to stream binding, bypassing the byte[] copy entirely
    ps.setBinaryStream(index, blob.getBinaryStream(), blob.length());
}

Prevention

When it happens

Trigger: Binding a Blob to a PreparedStatement while contextual creation is enabled and either the read/create/write path throws SQLException, or blob.length() exceeds Integer.MAX_VALUE and the cast silently truncates/overflows the read length.

Common situations: Drivers whose createBlob/setBytes path fails (same root causes as errors 1317/1318); attempted binding of multi-gigabyte BLOBs; using a stale LobCreator after its connection closed.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/4a7a69a1076f23fa. Report an issue: GitHub.