Duvida em hibernate?[AINDA NÃO RESOLVIDO]!

36 respostas
dicabeca

pessoal me tira uma duvida,eu tenho uma relacao ManyToMany(Servidor e BancoDados),vamos dar nomes aos bois,tenho Servidor,BancoDados e tabelas,ja da para ver as relacoes,entao minha duvida e a seguinte,no metodo Servidor.getBancoDados() ele me retorna uma coleção de BancoDados,sendo q ele esta carregando as propiedades dentro do BancoDados de cada um,no meu caso, esta executando tb o metodo BancoDados.getTabelas(),e eu nao quero q ele faca isso eu so quero pegar os nomes dos bancos,ja coloquei servidor.getBancoDados().toString e mesmo assim carrega o getTabela(),eu achava q o fetch = lazy resolveria,alguem pode me ajudar, o metodo esta assim

@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy = "bancoDados") 
    @Cascade({org.hibernate.annotations.CascadeType.ALL, org.hibernate.annotations.CascadeType.DELETE_ORPHAN})
    @OrderBy("nome")
    public Set<Tabela> getTabelas() {
        return this.tabelas;
    }

36 Respostas

bland

Dica,

Eu não tenho certeza, mas acho que você terá que fazer uma query onde traga apenas o que você deseja, só que essa query deve estar na sua classe Servidor.

Entenda, quando você tem uma relação como a que você descreveu o Hibernate trará tudo, tudo mesmo, a não ser que você especifique o que deseja trazer. E pra fazer isso, você tem que determinar isso usando uma query na sua anotação.

Bem, como disse, não tenho certeza disso, mas acho que deva ser por aí. Se estiver errado, ou se alguém tiver uma solução melhor, posta aí.

Abraço.

dicabeca

eu acho q dever ter alguma forma melhor usando o relacionamento, alguem tem mais alguma ideia sabe c é possivel???

L

Não entendi, por que você chama toString()? Isso faz com que todos os dados da qual o objeto depende sejam carregados, estragando a estratégia lazy. É isso mesmo?

dicabeca

na verdade isso foi erro meu, eu digitei toString na verdade e toArray,mais me explica isso como assim estraga o lazy,nao entendi isso???

dicabeca

ai pessoal ta sinistro ja tentei d todos os jeitos, alguem pode me dizer c é possivel, para eu nao ficar dando murro em ponta de faca,c é possivel q qnd eu pegue uma colecao, ela nao execute um associação dela,ou seja,so me retorne aquele Objeto sem me retornar os outros objetos relacionados a ele(OneToMany)???

Marky.Vasconcelos

O FethType.LAZY é pra evitar você trazer na memória só o objeto, mas já carrega todo o Collection.
Se realmente nãohá necessidade de carregar tudo isso retire o LAZY do @ManyToMany

O

dicabeca nao sei se esta correto. Mas eu sei assim como os outros disseram

Query query = session.createQuery("select b from Servidor as s join s.banco as b");
List<Banco> banco = query.list();

Espero ter te ajudado…

ate mais

dicabeca

Mark_Ameba uma duvida tu ta falando para eu tirar o LAZY no caso, da classe Servidor?,pq ela é quem tem ManyToMany para BancoDados,de BancoDados para tabela e OneToMany seria isso?

Marky.Vasconcelos

Pode tirar dos dois lados se você realmente não quer “procurar um carrinho de compras e achar todos os produtos que tem dentro”
Entretanto com o carrinho em mãos você poderá olhar oque tem dentro.

Entende?

dicabeca

na verdade eu so queria saber aproveitando o seu exemplo,seria, eu ja tenho o carrinho(Servidor),so queria saber o NOME dos produtos(BancoDados) q sao pertencente a ele,mais eu nao quero carregar oq tem dentro dos produtos(Tabela)!!!

Marky.Vasconcelos

Nesse caso você teria que carregar os objetos ou então fazer uma query que te mostre só oque você quer.

Exemplo:
SELECT nome FROM produtos WHERE carrinho_fk = 10;

dicabeca

essa solucao eu sei q da para fzr,eu quero saber c é possivel fzr isso, sem query,configurando no annotation,eu achava q o fetchType.LAZY resolveria,mais acho q nao,nao sei c é possivel fzr isso d outra forma???

dicabeca

alguem sabe c isso é possivel???

tRuNkSnEt

Eu vi que está havendo confusão com o Fetch LAZY.
O conceito é:

? FetchType.EAGER: sempre que o objeto “pai” for trazido da base de
dados, o atributo mapeado com fetch=FetchType.EAGER fará com que o
seu conteúdo também seja trazido;
? FetchType.LAZY: sempre que o objeto “pai” for trazido da base de dados,
o atributo mapeado com fetch=FetchType.LAZY fará com que o seu
conteúdo somente seja trazido quando acessado pela primeira vez.

Se você quer que um objeto seu não traga as coleções use fetch=FetchType.LAZY e esqueça que esse objeto tem relacionamentos. Se for configurado via annotação isso é pra sempre! Toda vez que você carregar seu objeto as coleções não existiram. Exemplo:

@Entity
public class Servidor {
   //...
  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name="id_banco", insertable=true, updatable=true)
  @Fetch(FetchMode.JOIN)
  @Cascade(CascadeType.ALL)
  private BancoDeDados banco;
  //...
}

@Entity
public class BancoDeDados{
   //..
  @OneToMany(mappedBy="banco", fetch = FetchType.LAZY)
  @Cascade(CascadeType.ALL)
   private Collection<Servidor> servidores;
   //...
}

Agora, se daqui a pouco você precisar de uma coleção mapeada como LAZY ai você vai precisar de Critéria, como abaixo:

List servidores = sess.createCriteria(servidores.class)
          .add( Restrictions.like("name", "XYZServer%") )
          .setFetchMode("banco", FetchMode.EAGER)
          .list();

Agora você esta trazendo as coleções de Servidor!

Espero que eu tenha entendido sua dúvida.

Att, Eliezer Reis

dicabeca

ai q ta,a relacao de Servidor para o BancoDados nao é de ManyToOne é de ManyToMany!!!

P

Qual o default? lazy ou eager?

dicabeca

é lazy!!!
vou colocar os relacionamentos aki em ordem

Classe Servidor

@ManyToMany(cascade={CascadeType.ALL}, fetch=FetchType.LAZY)
    @JoinTable(name="BancoDadosServidor",joinColumns={@JoinColumn(name="Servidor")},
     inverseJoinColumns={@JoinColumn(name="BancoDados")})
    @Cascade({org.hibernate.annotations.CascadeType.ALL, org.hibernate.annotations.CascadeType.DELETE_ORPHAN})
    @OrderBy("nome")
    public Set<BancoDados> getBancosDados() 
    {
        return bancosDados;
    }

Classe BancoDados

@ManyToMany(cascade={}, fetch=FetchType.LAZY)
    @JoinTable(
        name="BancoDadosServidor",
        joinColumns={@JoinColumn(name="BancoDados")},
        inverseJoinColumns={@JoinColumn(name="Servidor")}
    )
    public Set<Servidor> getServidores() {
        return servidores;
    }

    private void setServidores(Set<Servidor> value) {
        Set<Servidor> oldValue = this.servidores;
        this.servidores = value;
        pcs.firePropertyChange(PROPERTYNAME_SERVIDORES, oldValue, value);
    }
    
    @OneToMany(cascade={CascadeType.ALL}, fetch=FetchType.LAZY, mappedBy = "bancoDados") 
    @Cascade({org.hibernate.annotations.CascadeType.ALL, org.hibernate.annotations.CascadeType.DELETE_ORPHAN})
    @OrderBy("nome asc")
    public Set<Tabela> getTabelas()
    {
        return this.tabelas;
    }

Classe Tabela

@ManyToOne(cascade={},fetch=FetchType.LAZY)
    @JoinColumn(name="BancoDados")
    public BancoDados getBancoDados() {
        return bancoDados;
    }
Marky.Vasconcelos

Acho que o default é eager e eu realmente confundi lazy com eager.

dicabeca

o default é LAZY!!!

Marky.Vasconcelos

Cabei de le, percebi que me confundi fui fala e me confundi denovo, ainda bem que não uso FethType nas minhas relações.

dicabeca

como vc faz entao???

Marky.Vasconcelos

Deixo sem o fetch, por default é eage mesmo.

dicabeca

mais o EAGE carrega as herancas e é isso q eu nao quero, mesmo com o LAZY ta carregando eu nao to intendendo mais nada,alguem pode me dar uma LUZ(de preferencia um CLARAO haha)!!!

Marky.Vasconcelos

Pelo que entendi(que tava confundindo)
Voltamos ao carrinho de compras

Com o LAZY os produtos(coleção de objetos) estarão lá mas você só os pegara na mão(carregar do banco) quando quiser acessa-los pela primeira vez, depois vai ficando pendurado com você até descarregar(flush).

Com o EAGER assim que você tiver o carrinho você vai estar com todos os produtos na mão. Assim acho que ficaria um pouco mais carregado caso a coleção seja um pouco grande.
(Por exemplo meu sistema que tem 693000 ruas de todo brasil, é StackOverFlowError na serta)

dicabeca

ou seja, nao tem saida???,
pelo q eu sei é a assim,o EAGER qnd executar o programa ele ja vai carregar todos os relacionamento,os filhos,os filhos dos filhos e a vai…,ja o LAZY,ele so carrega qnd for chamado,sendo q ai a ta minha duvida, eu tem uma tabela,ai ela tem relacao com outra,no caso o relacionamento e de N:N,sendo q a outra tabela eu nao quero q os filhos dela sejam carregados eu so quero ela mesma,minha pergunta é se mesmo com LAZY essas filhas vao ser carregadas???

Marky.Vasconcelos

Eles não vão ser carregados na sessão.

Mas se você pegar um item da coleção esse será carregado.

dicabeca

esse item q vc esta falando seria oq ???

Marky.Vasconcelos

Um Objeto da Coleção

dicabeca

mais é isso q ta acontecendo,eu dou um getBancoDados,ele me retorna todos os bancos com todas as tabelas carregadas tb e eu nao quero eu so quero os bancos carregados e a tabela q c fod… hehehe,mais esta carregando a tabela nao sei pq?

dicabeca

alguem ainda tem uma ideia???

Marky.Vasconcelos

Como você sabe que está sendo tudo carregado?

dicabeca

q la na .properties eu coloquei show_query = true,entao eu vejo as querys montadas,e demoro pra burro pq ele carrega todas tabelas do banco sleecionado,todos os atributos d todas as tabelas do banco,e ai vai,mais c eu matar o problema com a tabela eu mato com todos,e isso amigo demora pra burro

dinegri

Meu amigo você pode ter o seguinte

select new BancoDados(b.nome) from BancoDados as d where d.servidor.id = ?

executa isso em um objeto Query, ele vai te retornar ou nada ou uma lista com o objetos BancoDados, aonde a única propriedade carregada é o nome do banco de dados mas não se esqueça que na sua classe BancoDados você precisa dessa propriedade passada como argumento no construtor.

ex:

public class BancoDados {

private int id;

private String nome;

private String qualquerCoisa;
/**
  Constructor
**/

public BancoDados(String nome) {
     this.nome = nome
}

/**
 getters e setters

**/

}

dicabeca

mas não se esqueça que na sua classe BancoDados você precisa dessa propriedade passada como argumento no construtor.

por acaso esse argumento q vc falou seria um @Transient ?

dinegri

Não sei bem com JPA, mas acredito que não seja necessário ser transient, faço o teste e me avise por favor!!!

dicabeca

bom com query eu sei q funciona,EU NAO QUERO USAR QUERY,eu quero mexer no relacionamento,pq ele pode me retornar os nomes mais depois eu vou precisar usar os objetos carregados O Q EU QUERO SABER é se tem como eu chamar um getBancoDados e nao carrega o getTabelas!!!

Criado 17 de outubro de 2007
Ultima resposta 23 de out. de 2007
Respostas 36
Participantes 8