2010-04-09 35 views
21

Necesito ayuda con lazy peg loading en Hibernate. Tengo en mi aplicación web estos servidores y frameworks: MySQL, Tomcat, Spring e Hibernate.Spring, Hibernate, Blob perez loading

La parte de la configuración de la base de datos.

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

La parte de la clase de entidad

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

La descripción del problema. Intento mostrar en una página web los registros de la base de datos relacionados con los archivos, que se guardaron en la base de datos MySQL. Todo funciona bien si un volumen de datos es pequeño. Pero el volumen de datos es grande Estoy recibiendo un error java.lang.OutOfMemoryError: Java heap space He intentado escribir en valores nulos de blobFields en cada fila de la tabla. En este caso, la aplicación funciona bien, la memoria no desaparece. Tengo una conclusión de que el campo blob que está marcado como flojo (@Basic(fetch=FetchType.LAZY)) no es perezoso, de hecho! ¿Cómo puedo resolver el issie? Muchas gracias por el avance.

+0

Véase también https://hibernate.onjira.com/browse/HHH-5255 – Vadzim

Respuesta

2

Le sugiero que use herencia para manejar este escenario. Tener una clase base sin el blob y una clase derivada que contiene el conjunto de bytes. Utilizarías la clase derivada solo cuando necesites mostrar el blob en la UI.

+0

Gracias, Darin. Pero quiero saber por qué el campo flojo no es tan vago como quiero :) Pero, de cource, usaré su sugerencia, si no encuentro la otra manera de resolver el problema. –

24

Estoy confundido. Emmanuel Bernard escribió en ANN-418 que @Lob son flojos por defecto (es decir, ni siquiera necesita usar la anotación @Basic(fetch = FetchType.LAZY)).

Algunos usuarios informan que la carga lenta de un @Lobdoesn't work with all drivers/database.

Algunos usuarios informados sobre el funcionamiento de bytecode instrumentation (javassit? Cglib?).

Pero no puedo encontrar ninguna referencia clara de todo esto en la documentación.

Al final, recommended workaround es usar una correspondencia "falsa" de uno a uno en lugar de propiedades. Elimine los campos LOB de su clase existente, cree nuevas clases que hagan referencia a la misma tabla, la misma clave principal y solo los campos LOB necesarios como propiedades. Especifique las asignaciones como uno-a-uno, fetch = "select", lazy = "true". Siempre que su objeto principal todavía esté en su sesión, debería obtener exactamente lo que desea. (solo transponer esto a las anotaciones).

+0

Gracias, Pascal. No entendí cómo puedo especificar el mapeo uno a uno con la clase padre. ¿Te importaría ayudarme con eso? Gracias de nuevo. –

+3

Parent class @OneToOne (cascade = CascadeType.ALL, fetch = FetchType.LAZY) private FileBlobBean fileBlobBean; clase Niño: @Id @GeneratedValue (estrategia = GenerationType.IDENTITY) @Basic (opcional = false) @Column (name = "uid", anulable = false) UID largo privada; @Lob @Basic (fetch = FetchType.LAZY) @Column (name = "BlobField", columnDefinition = "LONGBLOB") byte privado [] blobField; @OneToOne (mappedBy = "fileBlobBean") @JoinColumn (name = "Uid", referenciadoColumnName = "Uid", nullable = falso) public FileBean fileBean; –

+0

Hibernate creó un nuevo campo en la tabla "archivos". Y el campo estaba vacío. ¿Qué estoy haciendo mal? P.S. Lo siento por el horrible formato del código. –

5

Por supuesto podría extraer ese valor y ponerlo en una nueva tabla con una relación "@OneToOne" que es perezoso, sin embargo, en nuestra solicitud de los LOB se cargan con pereza en la demanda utilizando sólo esta configuración

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

Esto se prueba en nuestro proyecto de forma simultánea en PostgreSQL, MySQL, SQL Server y Oracle, así que debería funcionar para u

+1

Esto no funcionó para mí –

+0

Didn Tampoco funciona para mí. Hibernate 4.3.1. Oracle 10g XE. ¿Quizás hayas implementado la instrumentación del código de bytes? –

+0

PrimitiveByteArrayBlobType está en desuso, repalced con MaterializedBlobType, y no funcionó para mí también (hibernate 5.0.7.Final, postgresql) –

2

carga propiedad Lazy requiere Buildtime código de bytes de instrumentación.

Hibernate docs: Using lazy property fetching

Si se quiere evitar la instrumentación de código de bytes Una opción es la creación de dos entidades que utilizan una misma mesa, una con la burbuja fuera. Entonces solo usa la entidad con blob cuando necesites el blob.