Relacionamento @OneToOne/@ManyToOne com FetchType.LAZY no TopLink não funciona

1 resposta
marcelocenerine

Boa noite pessoal,

Tenho uma classe em minha aplicação que possui vários atributos do tipo @OneToOne/@ManyToOne.
Esses atributos são consultados em views de um ERP, o q faz com que a consulta seja muito lenta.
Neste projeto está sendo utilizado o TopLink Essentials como implementação da JPA. Para cada atributo o toplink faz uma consulta separada (não utiliza junção).

Para reduzir o tempo das consultas, mapeei tais atributos (@OneToOne/@ManyToOne) com o fetch = LAZY. Porém, observando os SQLs gerados, verifiquei que as consultas para carregar esses atributos são feitas do mesmo jeito, ou seja, parece que mesmo colocando explicitamente (visto que o default tbm é lazy) não adiantou.
Fiz um pequeno teste com o Hibernate e o comportamento foi diferente, ou seja, funcionou.

Alguém conhece alguma limitação do TopLink que possa estar causando isso? Alguém já utilizou e deu certo? Estou fazendo alguma coisa errada?
Preciso fazer isso utilizando o TopLink, pois é o padrão na empresa onde trabalho.

Seguem abaixo as classes de um pequeno teste que realizei:

Classe (resumida) que possui a anotação do atributo :

public class Participante implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @Basic(optional = false)
    @Column(name = "id", nullable = false)
    private Integer id;

    @Basic(optional = false)
    @Column(name = "login", nullable = false, length = 20)
    private String login;

    @Basic(optional = false)
    @Column(name = "senha", nullable = false, length = 32)
    private String senha;

    @Basic(optional = false)
    @Column(name = "datacadastro", nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private Date datacadastro;

    @JoinColumn(name = "id_cidade", referencedColumnName = "id", nullable = true, insertable = false, updatable = false)
    @ManyToOne(optional = true, fetch=FetchType.LAZY)
    private Cidade idCidade;

    public Participante() {
    }

}

Classe Cidade (resumida):

public class Cidade implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @Basic(optional = false)
    @Column(name = "id", nullable = false)
    private Integer id;

    @Basic(optional = false)
    @Column(name = "uf", nullable = false, length = 2)
    private String uf;

    @Basic(optional = false)
    @Column(name = "cidade", nullable = false, length = 100)
    private String cidade;

    @Column(name = "latitude", precision = 17, scale = 17)
    private Double latitude;

    @Column(name = "longitude", precision = 17, scale = 17)
    private Double longitude;

    @Column(name = "semacento", length = 100)
    private String semacento;

    @Column(name = "id_weather", length = 8)
    private String idWeather;

    public Cidade() {
    }

}

Persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
  <persistence-unit name="TesteOneToOnePU" transaction-type="RESOURCE_LOCAL">
    <provider>oracle.toplink.essentials.PersistenceProvider</provider>
    <class>beans.Participante</class>
    <class>beans.Cidade</class>
    <properties>
      <property name="toplink.logging.level" value="FINE"/>
      <property name="toplink.jdbc.user" value="addressmobileuser"/>
      <property name="toplink.jdbc.password" value="**********"/>
      <property name="toplink.jdbc.url" value="jdbc:postgresql://localhost:5432/BD_ADDRESS_MOBILE"/>
      <property name="toplink.jdbc.driver" value="org.postgresql.Driver"/>
    </properties>
  </persistence-unit>
</persistence>

Método main:

public static void main(String[] args) {
        // TODO code application logic here
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("TesteOneToOnePU");
        EntityManager em = emf.createEntityManager();

    

        System.out.println("########################################################################");
        Query q = em.createQuery("Select p from Participante p");
        Collection<Participante> ps =  q.getResultList();
       
        
    }

Resultado da execução:

[TopLink Fine]: 2009.11.11 11:13:20.720--ServerSession(8116722)--Connection(22057969)--Thread(Thread[main,5,main])--SELECT id, endereco, bairro, login, cep, datanascimento, latitude, datacadastro, longitude, ultimoacesso, sexo, status, senha, imagem, id_cidade FROM addressmobile.participante
[TopLink Fine]: 2009.11.11 11:13:21.144--ServerSession(8116722)--Connection(22057969)--Thread(Thread[main,5,main])--SELECT id, latitude, longitude, cidade, semacento, uf, id_weather FROM addressmobile.cidade WHERE (id = ?)
        bind => [330010]
[TopLink Fine]: 2009.11.11 11:13:21.178--ServerSession(8116722)--Connection(22057969)--Thread(Thread[main,5,main])--SELECT id, latitude, longitude, cidade, semacento, uf, id_weather FROM addressmobile.cidade WHERE (id = ?)
        bind => [410010]
[TopLink Fine]: 2009.11.11 11:13:21.207--ServerSession(8116722)--Connection(22057969)--Thread(Thread[main,5,main])--SELECT id, latitude, longitude, cidade, semacento, uf, id_weather FROM addressmobile.cidade WHERE (id = ?)
        bind => [350650]
[TopLink Fine]: 2009.11.11 11:13:21.247--ServerSession(8116722)--Connection(22057969)--Thread(Thread[main,5,main])--SELECT id, latitude, longitude, cidade, semacento, uf, id_weather FROM addressmobile.cidade WHERE (id = ?)
        bind => [240810]
[TopLink Fine]: 2009.11.11 11:13:21.287--ServerSession(8116722)--Connection(22057969)--Thread(Thread[main,5,main])--SELECT id, latitude, longitude, cidade, semacento, uf, id_weather FROM addressmobile.cidade WHERE (id = ?)
        bind => [310620]
[TopLink Fine]: 2009.11.11 11:13:21.321--ServerSession(8116722)--Connection(22057969)--Thread(Thread[main,5,main])--SELECT id, latitude, longitude, cidade, semacento, uf, id_weather FROM addressmobile.cidade WHERE (id = ?)
        bind => [350010]
[TopLink Fine]: 2009.11.11 11:13:21.436--ServerSession(8116722)--Connection(6182315)--Thread(Thread[main,5,main])--SELECT id, latitude, longitude, cidade, semacento, uf, id_weather FROM addressmobile.cidade WHERE (id = ?)
        bind => [420540]
[TopLink Fine]: 2009.11.11 11:13:21.480--ServerSession(8116722)--Connection(6182315)--Thread(Thread[main,5,main])--SELECT id, latitude, longitude, cidade, semacento, uf, id_weather FROM addressmobile.cidade WHERE (id = ?)
        bind => [350280]

Se o lazyload estivesse realmente funcionando, haveria apenas a consulta da classe que contém a referência a classe cidade.

Alguém pode me ajudar?? Agradeço desde já.

1 Resposta

townray

Você usa BMT ao invés de CMT certo? Nesse caso acho que o link abaixo se aplica:

http://www.oracle.com/technology/products/ias/toplink/JPA/essentials/toplink-jpa-extensions.html#DynamicWeaving

eu uso CMT e comigo funciona de boa.

Criado 11 de novembro de 2009
Ultima resposta 12 de nov. de 2009
Respostas 1
Participantes 2