O Hibernate JPA) como fazer uma ansioso consulta, o carregamento de todos os objetos filho

StackOverflow https://stackoverflow.com/questions/70992

  •  09-06-2019
  •  | 
  •  

Pergunta

Referentes ao meu pergunta anterior, Eu quero garantir que todos os objetos filho são carregados como eu tenho vários segmentos que podem precisar de acesso a dados (e, assim, evitar o carregamento lento exceções).Eu entendo a maneira de fazer isso é usar a "busca palavra-chave" na consulta (EJB QL).Como esta:

select distinct o from Order o left join fetch o.orderLines

Assumindo um modelo com um Order classe que tem um conjunto de OrderLines em ti.

A minha pergunta é a de que o "distinto" palavra-chave parece ser necessário, pois caso contrário, eu consigo ter de volta um Order para cada OrderLine.Eu estou fazendo a coisa certa?

Talvez mais importante, há uma maneira de puxar a todos os objetos filho, não importa quão profunda?Nós temos em torno de 10 a 15 classes de e para o servidor que vai precisar de tudo carregado...Eu estava evitando usando FetchType.EAGER como que significava sempre ansioso e, em particular, o front-end da web carrega tudo - mas talvez seja o caminho a percorrer é que o que você faz?Eu me lembro de nós a tentar isso antes e, em seguida, ficando muito lento de páginas da web, mas talvez o que significa que deve ser o uso de um segundo nível de cache?

Foi útil?

Solução

Alterar a anotação é uma má idéia, IMO.Como ela não pode ser alterada a preguiça em tempo de execução.Melhor fazer tudo o preguiçoso, e buscar, conforme necessário.

Eu não tenho certeza se entendi o seu problema sem mapeamentos.Left join fetch deve ser tudo o que você precisa para o caso de uso que descrevem.Claro, você receberá de volta uma ordem para cada orderline se orderline tem um fim como o seu pai.

Outras dicas

Eu não tenho certeza sobre como usar a busca palavra-chave em sua EJBQL, você pode estar ficando-lo confundido com a anotação de...

Você já tentou adicionar a FetchType propriedade para o seu atributo de relacionamento?

@OneToMany(fetch=FetchType.ANSIOSO)?

Veja:

http://java.sun.com/javaee/5/docs/api/javax/persistence/FetchType.html http://www.jroller.com/eyallupu/entry/hibernate_exception_simultaneously_fetch_multiple

Você já tentou usar um resultado transformador?Se você usar consultas de Critérios, você pode aplicar um resultado transformador (embora existem alguns problemas com a paginação e o resultado transformador):

Criteria c = ((Session)em.getDelegate()).createCriteria(Order.class);
c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
c.list();

o em.getDelegate() é um hack que só funciona se você estiver usando o modo de hibernação.

Talvez a mais importante, é que existe um forma de puxar todos os objetos filho, não importa quão profundo?Nós temos em torno de 10 a 15 classes e para o servidor que irá precisamos de tudo carregado...Eu era evitar o uso de FetchType.ANSIOSOS como que significava sempre ansioso e em em particular, o front-end da web carrega tudo - mas talvez seja o caminho para percorrer, é que o que você faz?Eu me lembro de nós a tentar isso antes e, em seguida, ficando muito lento de páginas web - mas, talvez, o que significa que deve ser o uso de um segundo nível de cache?

Se você ainda estiver interessado, eu respondi uma pergunta semelhante neste segmento como serializar o hibernate coleções.

Basicamente você usar um utilitário chamado dozer que mapeia o feijão para outra feijão, e fazendo isso você acionar todos os seus preguiçosos cargas.Como você pode imaginar, isso funciona melhor se todas as coleções são procurada.

Você pode ser capaz de fazer algo parecido com que o uso de um (separadas) critérios de consulta, e a definição do modo de busca.E. g.,

Session s = ((HibernateEntityManager) em).getSession().getSessionFactory().openSession();
DetachedCriteria dc = DetachedCriteria.forClass(MyEntity.class).add(Expression.idEq(id));
dc.setFetchMode("innerTable", FetchMode.JOIN);
Criteria c = dc.getExecutableCriteria(s);
MyEntity a = (MyEntity)c.uniqueResult();

Que só funcionaria para ManyToOne relações e para eles @ManyToOne(fetch=FetchType.ANSIOSO) provavelmente apropriado.

A obtenção de mais do que um OneToMany relação com avidez é desencorajado e/ou não funciona, como você pode ler no link Jeremy postou.Basta pensar sobre a instrução de SQL que seria necessário para fazer uma busca...

O que eu tenho feito é refatorar o código para manter um mapa de objetos para gestores de entidades e cada vez que eu preciso para atualizar, fechar o antigo entitymanager para o objeto e abrir uma nova.Eu usei a consulta acima, sem a buscar como que está a ir muito fundo para as minhas necessidades - apenas fazendo uma simples associação recebe o OrderLines - o buscar faz com que ele vá ainda mais fundo.

Há apenas alguns objetos que eu preciso deste para, em torno de 20 anos, então eu acho que o recurso de sobrecarga em ter 20 abrir entitymanagers não é um problema - embora os DBAs podem ter uma visão diferente quando este vai viver...

Eu também re-trabalhadas as coisas de modo que o banco de dados trabalho é a thread principal e tem a entidade gestora.

Chris

Se o problema é apenas LazyInitializationExceptions, você pode evitar que a adição de um OpenSessionInViewFilter.
Isto irá permitir que os objetos a serem carregados na vista, mas não vai ajudar com a velocidade problema.

     <filter>
        <filter-name>hibernateFilter</filter-name>
        <filter-class> org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
        </filter-class>
    </filter>
    <filter-mapping>
        <filter-name>hibernateFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top