Spring, Hibernate, Blob lazy loading

Solution 1:

I'm confused. Emmanuel Bernard wrote in ANN-418 that @Lob are lazy by default (i.e. you don't even need to use the @Basic(fetch = FetchType.LAZY) annotation).

Some users report that lazy loading of a @Lob doesn't work with all drivers/database.

Some users report that it works when using bytecode instrumentation (javassit? cglib?).

But I can't find any clear reference of all this in the documentation.

At the end, the recommended workaround is to use a "fake" one-to-one mappings instead of properties. Remove the LOB fields from your existing class, create new classes referring to the same table, same primary key, and only the necessary LOB fields as properties. Specify the mappings as one-to-one, fetch="select", lazy="true". So long as your parent object is still in your session, you should get exactly what you want. (just transpose this to annotations).

Solution 2:

I would suggest you to use inheritance to handle this scenario. Have a base class without the blob and a derived class containing the byte array. You would use the derived class only when you need to display the blob on the UI.

Solution 3:

Of course you could extract that value and put it into a new table with a "@OneToOne" relation that is lazy, however in our application the LOBs are loaded lazily on demand using just this configuration

@Lob
@Fetch(FetchMode.SELECT)
@Type(type="org.hibernate.type.PrimitiveByteArrayBlobType")
byte[] myBlob;

This is tested in our project simultaneously on PostgreSQL, MySQL, SQLServer and Oracle, so it should work for u

Solution 4:

Lazy property loading requires buildtime bytecode instrumentation.

Hibernate docs: Using lazy property fetching

If you want to avoid bytecode instrumentation one option is to to create two entities that use same table, one with the blob one without. Then only use the entity with blob when you need the blob.

Solution 5:

I had the same issue and this was my fix:

My Entity:

@Entity
@Table(name = "file")
public class FileEntity {

@Id
@GeneratedValue
private UUID id;

@NotNull
private String filename;

@NotNull
@Lob @Basic(fetch = FetchType.LAZY)
private byte[] content;

...

Added plugin to pom.xml:

        <plugin>
            <groupId>org.hibernate.orm.tooling</groupId>
            <artifactId>hibernate-enhance-maven-plugin</artifactId>
            <executions>
                <execution>
                    <phase>compile</phase>
                    <configuration>
                        <failOnError>true</failOnError>
                        <enableLazyInitialization>true</enableLazyInitialization>
                    </configuration>
                    <goals>
                        <goal>enhance</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>