2008-10-21 6 views
10

Tengo una propiedad en un objeto de dominio que se declara en un elemento de varios a uno. La sintaxis básica de esta propiedad es el siguiente:Cómo detener a Hibernate de buscar con entusiasmo el objeto asociado de muchos a uno

<many-to-one name="propertyName" class="propertyClass" fetch="select" not-found="ignore" lazy="proxy" /> 

Ahora, la idea es tener Hibernate NO ir a buscar ansiosamente esta propiedad. Puede ser nulo, por lo que se establece el ignorar no encontrado.

Pero, Hibernate, al cargar la clase que contiene esta asociación, se encarga de cargar la instancia de la clase real (ni siquiera un proxy) cuando se carga la clase padre. Dado que algunas propiedades tienen más de 1 MB de tamaño, ocupan gran parte del espacio de almacenamiento dinámico.

Si, sin embargo, no encontrado está configurado como excepción (o predeterminado a excepción), las clases padre que tienen esta propiedad cargan un proxy.

¿Cómo puedo detener la hibernación por no cargar un proxy, al mismo tiempo que dejo que esta propiedad sea nula?

Encontré lazy = no-proxy, pero la documentación habla de algún tipo de modificación de bytecode y no entra en detalles. ¿Alguien me puede ayudar?

Si es importante, es la versión de Hibernate de Java, y es al menos la versión 3 (puedo buscar la versión actual si ayuda, pero por ahora es Hibernate 3+).

No especifiqué antes, pero la versión de Java es 1.4. Por lo tanto, las anotaciones Java no son compatibles.

Respuesta

9

Si el otro extremo de la asociación puede ser nula, creo que Hibernate tiene que consulta para el extremo de la asociación con el fin de determinar si debe usar un proxy o no (sin necesidad de proxy si el otro extremo es nula). No puedo encontrar la referencia a esto ahora, pero recuerdo haberlo leído en alguna parte.

Con el fin de proporcionar la carga lenta de campos la documentación se refiere a las mejoras de bytecode en los campos en el tiempo de compilación: Using lazy property fetching. Aquí está un extracto:

Hibernate3 admite la recuperación perezosa de propiedades individuales. Esta técnica de optimización también se conoce como como grupos de búsqueda. Tenga en cuenta que este es principalmente una función de marketing, como en la práctica , la optimización de las lecturas de fila es mucho más importante que la optimización de las lecturas de columna de .Sin embargo, solo cargar algunas propiedades de una clase puede ser útil en casos extremos, cuando las tablas heredadas tienen cientos de columnas y no se puede mejorar el modelo de datos.

La carga de la propiedad Lazy requiere instrumentación bytecode buildtime! Si sus clases persistentes no son mejoradas, Hibernate silenciosamente ignorará la configuración de propiedad perezosa y caerá a para recuperar inmediatamente.

+0

Esto parece prometedor ... Aceptaré su respuesta si funciona. ¡Gracias! – MetroidFan2002

+0

No hay problema, pero creo que básicamente no se puede tener un proxy diferido con asociaciones de terminación única que puede ser nulo (uno a uno o muchos para activar). En cuanto al gran consumo de heap, tuve un problema similar debido a los clobs, terminé tirando de los clobs a otra clase y cargándolos según sea necesario. –

+0

Creo que lo que vamos a hacer es poner el campo en la clase que es enorme (es un documento XML que finalmente se envía a un servicio web) en el campo de carga lenta, usando las cosas de código de bytes que señaló. Lamentablemente, el modelo de dominio está fuera de mis manos. – MetroidFan2002

0

Si pasa el objeto de hibernación del modelo a la vista a través del controlador, ¡no lo haga!

En su lugar crea un "objeto de instantánea" para almacenar los valores del objeto Hibernate que desea pasar a la vista y mostrarse.

¿Por qué? El proxy aún puede recuperar los valores cuando está en el controlador ... pero cuando pasa el proxy/objeto a la vista ya no puede recuperar los valores porque la transacción ya ha finalizado. Y es por eso que he sugerido lo que tengo arriba.

+1

excepto cuando utiliza el patrón Abrir sesión en vista – miceuz

+1

Esto no tiene nada que ver con la pregunta. Esto no se trata de ninguna tecnología o controlador de vista en particular. Incluso en las pruebas JUnit, este comportamiento ocurre. El tipo de objeto que sugiere es un "Objeto de transferencia de datos", por cierto. Pero eso no tiene relevancia aquí. – MetroidFan2002

+0

La razón por la que no tiene relevancia es que el objeto está completamente cargado cuando el padre está cargado (con not-found = "ignore"), o se carga a través del proxy, pero puede lanzar una excepción (con not-found = "exception") si es nulo. Quiero la posibilidad de que sea nulo y cargarlo a través del proxy. – MetroidFan2002

0

Al utilizar las anotaciones de Hibernate, poniendo @ManyToOne (fetch = FetchType.LAZY) en la asociación, logra lo que quiere. ¿Has probado configurar fetch = "lazy" para ver si funciona?

+0

Ni siquiera estoy seguro de que fetch = "lazy" sea una propiedad válida para la configuración XML . Según http://www.hibernate.org/hib_docs/v3/reference/en-US/html/mapping.html (5.1.12), fetch está limitado a "join | select". Además, la versión de Java es solo 1.4, por lo que las anotaciones están desactivadas. Voy a editar la pregunta. – MetroidFan2002

0

@Miguel Ping: Creo que la página a la que se refiere es [http://www.hibernate.org/162.html]. Por lo que yo entiendo, el SELECCIONAR adicional es necesario en el caso del lado uno a uno, donde la clave externa no está presente. El ajuste constrained="true" le dice a Hibernate que el otro lado siempre está presente y no se necesita SELECCIONAR adicional.

Así, por el lado de muchos-a-uno, donde reside la clave externa, que no debería ser necesario ejecutar otro SELECT ya que el valor del FK indica si el otro extremo está presente o null. Al menos, así es como lo entiendo.

Hasta ahora para la teoría. El proxy funciona para mí en el lado de la clave externa/de muchos a uno. El mapeo utilizado para la asociación es:

<many-to-one name="haendler" column="VERK_HAENDLOID" lazy="proxy" />

Pero proxy no funciona para mí en el lado de uno a uno usando un mapeo como el descrito en la URL dada (constrained="true"). Hmm, creo que abriré una pregunta para esto. ;-)

2

me pareció vago = no-proxy, pero los documentación habla de algún tipo de modificación código de bytes y no se va en detalles. ¿Puede alguien ayudarme ?

Supongo que está utilizando ANT para construir su proyecto.

<property name="src" value="/your/src/directory"/><!-- path of the source files --> 
<property name="libs" value="/your/libs/directory"/><!-- path of your libraries --> 
<property name="destination" value="/your/build/directory"/><!-- path of your build directory --> 

<fileset id="applibs" dir="${libs}"> 
    <include name="hibernate3.jar" /> 
    <!-- include any other libraries you'll need here --> 
</fileset> 

<target name="compile"> 
    <javac srcdir="${src}" destdir="${destination}" debug="yes"> 
    <classpath> 
     <fileset refid="applibs"/> 
    </classpath> 
    </javac> 
</target> 

<target name="instrument" depends="compile"> 
    <taskdef name="instrument" classname="org.hibernate.tool.instrument.javassist.InstrumentTask"> 
    <classpath> 
     <fileset refid="applibs"/> 
    </classpath> 
    </taskdef> 

    <instrument verbose="true"> 
    <fileset dir="${destination}"> 
     <!-- substitute the package where you keep your domain objs --> 
     <include name="/com/mycompany/domainobjects/*.class"/> 
    </fileset> 
    </instrument> 
</target> 
2

¡Asegúrese de que su clase no sea definitiva!

+0

Esto plantea la pregunta: ¿por qué? – JBert

+1

Para cualquier otra persona, que pregunta por qué, me encontré con esto: http://stackoverflow.com/a/5594863/280924 – brainydexter

Cuestiones relacionadas