We're updating the issue view to help you get more done. 

Issue with Blobs when selective caching is used

Description

Playing due to HHH-12588, I've discovered that an embeddable object with a blob is not cacheable. Moving the blob to an embeddable object is a workaround to bypass HHH-12555.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Entity @Polymorphism(type = PolymorphismType.EXPLICIT) @Inheritance(strategy = InheritanceType.JOINED) @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, include = "non-lazy") public abstract class Base extends DatabaseEntity { private Set<Attachment> attachments = new LinkedHashSet<>(); @OneToMany(mappedBy = "parent", fetch = FetchType.LAZY) @Fetch(FetchMode.SUBSELECT) public Set<Attachment> getAttachments() { return attachments; } public void setAttachments(Set<Attachment> attachments) { this.attachments = attachments; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 @Entity @Cacheable public class Attachment extends Base { private Base parent; @Access(AccessType.FIELD) @AttributeOverrides(@AttributeOverride(name = "blob", column = @Column(name = "filedata", length = 500 * 1024 * 1024))) @Basic(fetch = FetchType.LAZY) private DataHolder data = new DataHolder(); public DataHolder getData() { if (data == null) { data = new DataHolder(); } return data; } @ManyToOne(fetch = FetchType.LAZY) public Base getParent() { return parent; } public void setParent(Base parent) { this.parent = parent; } @Embeddable public static class DataHolder { private Blob blob; @Lob @Basic(fetch = FetchType.LAZY) public Blob getBlob() { return blob; } public void setBlob(Blob blob) { this.blob = blob; } } }

results in

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 java.lang.RuntimeException: java.lang.UnsupportedOperationException: Blobs are not cacheable at org.hibernate.bugs.AbstractTestCase.doInOpenTransaction(AbstractTestCase.java:55) at org.hibernate.bugs.TestCase.hhh12601(TestCase.java:20) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.hibernate.testing.junit4.ExtendedFrameworkMethod.invokeExplosively(ExtendedFrameworkMethod.java:45) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:298) at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:292) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.lang.Thread.run(Thread.java:748) Caused by: java.lang.UnsupportedOperationException: Blobs are not cacheable at org.hibernate.type.descriptor.java.BlobTypeDescriptor$BlobMutabilityPlan.disassemble(BlobTypeDescriptor.java:51) at org.hibernate.type.descriptor.java.BlobTypeDescriptor$BlobMutabilityPlan.disassemble(BlobTypeDescriptor.java:36) at org.hibernate.type.AbstractStandardBasicType.disassemble(AbstractStandardBasicType.java:318) at org.hibernate.type.ComponentType.disassemble(ComponentType.java:619) at org.hibernate.type.TypeHelper.disassemble(TypeHelper.java:132) at org.hibernate.cache.spi.entry.StandardCacheEntryImpl.<init>(StandardCacheEntryImpl.java:53) at org.hibernate.persister.entity.AbstractEntityPersister$StandardCacheEntryHelper.buildCacheEntry(AbstractEntityPersister.java:5460) at org.hibernate.persister.entity.AbstractEntityPersister.buildCacheEntry(AbstractEntityPersister.java:4460) at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:113) at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604) at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:478) at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:356) at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1452) at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1438) at org.hibernate.bugs.TestCase.lambda$hhh12601$1(TestCase.java:25) at org.hibernate.bugs.AbstractTestCase.doInOpenTransaction(AbstractTestCase.java:50) ... 16 more

To me, it seems that DataHolder is not instrumented properly, I don't see any lazy code in the decompiled class.

Test case: https://github.com/nikowitt/hibernate-test-case-templates/tree/HHH-12613-inheritance-caching-blobs

Environment

None

Status

Assignee

Unassigned

Reporter

Niko Wittenbeck

Fix versions

None

Labels

None

backPortable

None

Suitable for new contributors

None

Requires Release Note

None

Pull Request

None

backportDecision

None

Affects versions

5.3.3

Priority

Major