Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring, Hibernate, Blob lazy loading

I need help with lazy blob loading in Hibernate. I have in my web application these servers and frameworks: MySQL, Tomcat, Spring and Hibernate.

The part of database config.

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">     <property name="user" value="${jdbc.username}"/>     <property name="password" value="${jdbc.password}"/>     <property name="driverClass" value="${jdbc.driverClassName}"/>     <property name="jdbcUrl" value="${jdbc.url}"/>      <property name="initialPoolSize">         <value>${jdbc.initialPoolSize}</value>     </property>     <property name="minPoolSize">         <value>${jdbc.minPoolSize}</value>     </property>     <property name="maxPoolSize">         <value>${jdbc.maxPoolSize}</value>     </property>     <property name="acquireRetryAttempts">         <value>${jdbc.acquireRetryAttempts}</value>     </property>     <property name="acquireIncrement">         <value>${jdbc.acquireIncrement}</value>     </property>     <property name="idleConnectionTestPeriod">         <value>${jdbc.idleConnectionTestPeriod}</value>     </property>     <property name="maxIdleTime">         <value>${jdbc.maxIdleTime}</value>     </property>     <property name="maxConnectionAge">         <value>${jdbc.maxConnectionAge}</value>     </property>     <property name="preferredTestQuery">         <value>${jdbc.preferredTestQuery}</value>     </property>     <property name="testConnectionOnCheckin">         <value>${jdbc.testConnectionOnCheckin}</value>     </property> </bean>   <bean id="lobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler" />  <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">     <property name="dataSource" ref="dataSource" />     <property name="configLocation" value="/WEB-INF/hibernate.cfg.xml" />     <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />     <property name="hibernateProperties">         <props>             <prop key="hibernate.dialect">${hibernate.dialect}</prop>         </props>     </property>     <property name="lobHandler" ref="lobHandler" /> </bean>  <tx:annotation-driven transaction-manager="txManager" />  <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">     <property name="sessionFactory" ref="sessionFactory" /> </bean> 

The part of entity class

@Lob @Basic(fetch=FetchType.LAZY) @Column(name = "BlobField", columnDefinition = "LONGBLOB") @Type(type = "org.springframework.orm.hibernate3.support.BlobByteArrayType") private byte[] blobField; 

The problem description. I'm trying to display on a web page database records related to files, which was saved in MySQL database. All works fine if a volume of data is small. But the volume of data is big I'm recieving an error java.lang.OutOfMemoryError: Java heap space I've tried to write in blobFields null values on each row of table. In this case, application works fine, memory doesn't go out of. I have a conclusion that the blob field which is marked as lazy (@Basic(fetch=FetchType.LAZY)) isn't lazy, actually!

like image 515
Alexey Khudyakov Avatar asked Apr 09 '10 06:04

Alexey Khudyakov


People also ask

How do you load a lazy object in Hibernate?

To enable lazy loading explicitly you must use “fetch = FetchType. LAZY” on an association that you want to lazy load when you are using hibernate annotations. @OneToMany( mappedBy = "category", fetch = FetchType.

Which method uses lazy loading in the Hibernate session?

Hibernate applies lazy loading approach on entities and associations by providing a proxy implementation of classes. Hibernate intercepts calls to an entity by substituting it with a proxy derived from an entity's class.

What is difference between lazy loading and eager loading in Hibernate?

Eager Loading is a design pattern in which data initialization occurs on the spot. Lazy Loading is a design pattern which is used to defer initialization of an object as long as it's possible.

How do you do lazy loading in JPA?

Use cascading persistence: @OneToMany(fetch=FetchType. LAZY, mappedBy="user", cascade = {CascadeType. PERSIST}) List<OAuthLogin> oauthLogins; User user = new User(name); user.


1 Answers

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).

like image 90
Pascal Thivent Avatar answered Sep 30 '22 10:09

Pascal Thivent