[Resolvido] Dúvida com JPQL: fetch Lazy para qualquer propriedade

12 respostas
Rafael_Nascimento

Tenho uma entidade Arquivo no meu modelo semelhante a esta:

@Entity
@Table(name="arquivo")
public class Arquivo implements Serializable{
    @Id
    @Column
    private Long id;
    @Column
    private String nomeArquivo;    
    @Column
    private String tipo;    
    @Column
    @Basic(fetch= FetchType.LAZY)
    private byte[] conteudo;    //conteudo do arquivo (pode ser muito grande)

    //getters e setters...
}

ao executar esta query (jpql)

o JPA está me retornando todos os campos, inclusive o Lazy [é o q mostra a query gerada no console da IDE]. Como vou primeiro exibir os arquivo em uma tabela, preciso inicialmente apenas de informações básicas, como nome e tals… é totalmente desnecessário carregar também o conteúdo de todos os arquivos ao carregar a tabela. Caso o usuário selecione algum arquivo, aí sim o conteúdo desse arquivo deve ser carregado (tenho obtido OutOfMemoryError com certa frequencia nessa query, acho q é por causa disso :slight_smile: )

como faço para q o JPA busque o campo byte[] conteudo apenas quando for necessário ??

obrigado!!

12 Respostas

Hebert_Coelho

Você está utilizando Toplink?

Hebert_Coelho

Hebert Coelho:
Você está utilizando Toplink?
Esqueci, o mais novo é o Eclipselink. É esse?
Sua aplicação é Web?

Rafael_Nascimento

não, minha implementação do JPA é o Hibernte

sim, minha app é Web (JSF 2, GlassFish 3.1, primeFaces 3.3.1)

Hebert_Coelho

Eu tinha visto esse problema com EclipseLink: http://uaihebert.com/?p=1367&page=8

Para o Hibernate eu achei o seguinte: http://docs.jboss.org/hibernate/stable/annotations/reference/en/html/entity.html#d0e342

Note
To enable property level lazy fetching, your classes have to be instrumented: bytecode is added to the original class to enable such feature, please refer to the Hibernate reference documentation. If your classes are not instrumented, property level lazy loading is silently ignored.
Creio que é o que está acontecendo com você. [=

Rafael_Nascimento

Hebert, achei isso aqui:

<target name="instrument" depends="compile">
    <taskdef name="instrument" classname="org.hibernate.tool.instrument.InstrumentTask">
        <classpath path="${jar.path}"/>
        <classpath path="${classes.dir}"/>
        <classpath refid="lib.class.path"/>
    </taskdef>

    <instrument verbose="true">
        <fileset dir="${testclasses.dir}/org/hibernate/auction/model">
            <include name="*.class"/>
        </fileset>
    </instrument>
</target>

não leve a mal a falta de experiencia :slight_smile: , mas como e onde uso essa ant task ?

Hebert_Coelho

I mano, você deve estar utilizando Eclipse/Netbeans né?

Tente fazer direto pela IDE. Eu acho que talvez te ajude com o Eclipse: https://community.jboss.org/thread/98334?_sscc=t

Caso você utilize o Maven deve ter como fazer direto do Maven: http://tricksdev.blogspot.com.br/2009/03/hibernate-bytecode-instrumentation.html

O Ant é usado para gerar o WAR/EAR (e outras coisas). Você teria um trabalho bom para criar esse arquivo.

Agora, se tu vai querer encarar o Ant mesmo, procure no google ant create EAR

É uma linguagem simples. [=

rafaduka

troque o relacionamento de sua entidade para one-to-many

pois se vc utiliza o nome do arquivo para filtro, pode colocar os arquivos em outra tabela assim e fazer o join na sua entidade
que implicitamente será lazy por padrão.

Hebert_Coelho

rafaduka:
troque o relacionamento de sua entidade para one-to-many
Hein!?
Fazer um OneToMany com um blob? Sério mesmo? Nunca vi isso…

Rafael_Nascimento

puts, mas q saco :slight_smile:

estou usando o NetBeans 7.2, sem o maven

vou ver o q da pra fazer…

obrigado pelas dicas, Hebert

Hebert_Coelho

rafaduka:
troque o relacionamento de sua entidade para one-to-many

pois se vc utiliza o nome do arquivo para filtro, pode colocar os arquivos em outra tabela assim e fazer o join na sua entidade
que implicitamente será lazy por padrão.

Aaaa ta. Agora que você editou ficou mais claro! =P

A idéia dele é boa, caso você possa implementar.

Ao invés de ter um campo lob você teria uma tabela apenas com essa informação e trocar de um simples campo para um relacionamento.

Necessariamente não precisa ser OneToMany, pode ser OneToOne também. O bom dessa abordagem é que você poderá colocar o Lazy mais facilmente.

O problema dessa abordagem é a tabela que é a mais, e uma entidade a mais. Não sei c aí é assim, mas sei de lugares que só é permitido criar campos nas tabelas com autorização de DBA/Analista e assim vai.

Rafael_Nascimento

essa proposta do rafaduka, parece interessante e mais simples de implementar

vou fazer um teste pra ver se resolve

Rafael_Nascimento

Resolveu, agora posso atribuir lazy fetching a qualquer propriedade !!
passei a usar o maven no meu projeto e segui as instruções no link do Hebert: http://tricksdev.blogspot.com.br/2009/03/hibernate-bytecode-instrumentation.html

a tag plugin do meu pom.xml referente a instrumentação das entidades ficou assim:

<plugin>
                    <artifactId>maven-antrun-plugin</artifactId>
                    <version>1.7</version>
                    <executions>
                        <execution>
                            <id>Instrument domain classes</id>
                            <configuration>
                                <tasks>
                                    <taskdef name="instrument"
                                             classname="org.hibernate.tool.instrument.javassist.InstrumentTask">
                                        <classpath>
                                            <path refid="maven.dependency.classpath"/>
                                            <path refid="maven.plugin.classpath"/>
                                        </classpath>
                                    </taskdef>
                                    <instrument verbose="true">
                                        <fileset dir="${project.build.outputDirectory}">
                                            <include name="**/entidades/*.class"/>      <!-- modelo -->
                                            <include name="**/tipos/*.class"/>             <!-- pacote q contem algumas constantes referenciadas pelo modelo -->
                                        </fileset>
                                    </instrument>
                                </tasks>
                            </configuration>
                            <phase>process-classes</phase>
                            <goals>
                                <goal>run</goal>
                            </goals>
                        </execution>
                    </executions>
                    <dependencies>
                        <dependency>
                            <groupId>org.hibernate</groupId>
                            <artifactId>hibernate-core</artifactId>
                            <version>4.1.7.Final</version>
                        </dependency>
                    </dependencies>
            </plugin>

obrigado !! :smiley:

Criado 28 de setembro de 2012
Ultima resposta 1 de out. de 2012
Respostas 12
Participantes 3