hibernate/hibernate-orm · error · UnsupportedOperationException
Clobs are not cacheable
Error message
Clobs are not cacheable
What it means
ClobJavaType.ClobMutabilityPlan.disassemble throws UnsupportedOperationException('Clobs are not cacheable') when the second-level cache serializes an entity (or collection element) that holds a java.sql.Clob attribute. A Clob is a live handle to driver/connection state, so Hibernate refuses to put it into the cache region.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ClobJavaType.java:181
return dialect.getDefaultLobLength();
}
/**
* MutabilityPlan for Clob values
*/
public static class ClobMutabilityPlan implements MutabilityPlan<Clob> {
public static final ClobMutabilityPlan INSTANCE = new ClobMutabilityPlan();
public boolean isMutable() {
return false;
}
public Clob deepCopy(Clob value) {
return value;
}
public Serializable disassemble(Clob value, SharedSessionContract session) {
throw new UnsupportedOperationException( "Clobs are not cacheable" );
}
public Clob assemble(Serializable cached, SharedSessionContract session) {
throw new UnsupportedOperationException( "Clobs are not cacheable" );
}
}
}
View on GitHub (pinned to fad1729dce)
Solutions
- Map the attribute as String with @Lob (materialized and cacheable) instead of java.sql.Clob.
- Mark the entity @Cacheable(false) if it must keep the Clob attribute.
- Move the CLOB to a separate, non-cached entity (one-to-one) and cache the rest.
Example fix
// before
@Entity @Cacheable
public class Document {
@Lob private java.sql.Clob content; // cache put -> UnsupportedOperationException
}
// after
@Entity @Cacheable
public class Document {
@Lob private String content; // materialized, serializable, cacheable
} Defensive patterns
Strategy: validation
Validate before calling
// run once at startup: refuse to enable caching on Clob-bearing entities
for (EntityType<?> t : metamodel.getEntities()) {
boolean cached = t.getJavaType().isAnnotationPresent(jakarta.persistence.Cacheable.class);
for (Attribute<?,?> a : t.getAttributes()) {
if (cached && a.getJavaType() == java.sql.Clob.class) {
throw new IllegalStateException(t.getName() + '.' + a.getName() + " is Clob and not cacheable");
}
}
} Prevention
- Never map java.sql.Clob on entities you plan to cache; use @Lob String.
- Watch hibernate.cache.default_cache_concurrency_strategy — it can cache entities you never audited.
- Cover caching rollout with an integration test that inserts every cached entity once.
When it happens
Trigger: Annotating an entity with java.sql.Clob attributes as @Cacheable (or enabling hibernate.cache.default_cache_concurrency_strategy globally); the cache put happens on the first insert/load of such an entity and fails.
Common situations: Rolling out caching onto legacy entities during performance work; a global default cache strategy setting catching entities with LOB fields; framework upgrades that enable caching by default.
Related errors
- The INSERT statement for table [%s] contains no column, and
- cannot recreate collection while filter is enabled: " + coll
- cannot recreate collection while filter is enabled [%s : %s]
- '@AttributeAccessor' annotation must specify a 'strategy'
- <mapping/> named unexpected reference type
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/9eeb08d515bfe396.
Report an issue: GitHub.