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

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

Você está utilizando Toplink?

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

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

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

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

[quote]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.[/quote]Creio que é o que está acontecendo com você. [=

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 ?

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. [=

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.

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

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

[quote=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.[/quote]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.

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

vou fazer um teste pra ver se resolve

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: