Hibernate - Insert em tabela na terceira tabela em @ManyToMany

Galera, eu tenho uma relação entre Post NxM Category.

Quando vou inserir um post, eu adiciono as categorias também, como abaixo:


Post p = new Post();

p.setDescription("Teste");
//outras propriedades

if(p.setCategories == null){
  List<Category> cat = new ArrayList<Category>();
  cat.add(p);
  p.setCategories(cat);
}

Minhas coleções estão Lazy, e assim minhas coleções sempre estão null, mais isso não é verdade pois na minha terceira tabela do relacionamento eu tenho as informações que o post 1 por exemplo tem as categorias 1,2,3.
Dessa forma eu inicializo o List e adiciono as categorias, mais vi pelo log que o hibernate sempre apaga as categorias que já tenho e adiciona novamente, e nunca adiciona a que eu estou tentando inserir.
Detalhe: NÂO posso deixar o hibernate carregar todas as coleções, minhas coleções tem que ser Lazy mesmo.

Como faço para adicionar as novas categorias ao post?

Alguem???

Na verdade quando eu vou atualizar um post que ja tenha categoria, o hibernate esta excluido as categorias existentes e adicionando as novas, onde era para manter as existentes e adicionar as novas.

Como você está atualizando?

Post p = dao.load(id);

p.getCategorias().add(outraCategoria);

ou

Post p = dao.load(id);

p.setCategorias(umaListaDeCategorias);

?

o primeiro jeito é o certo

[]'s

No caso eu estou atualizando um registro que tenha posts, na inserção esta fazendo correto mais na atualização esta com esse problema.
Estou usando a primeira forma, mais eu vejo que o hibernate deleta os posts antigos e adiciona os
novos, onde era somente para adicionar.

você está fazendo um relacionamento many-to-many, certo?

qual é o lado forte do relacionamento?
(o que não tem o mapped-by)

atualizar usando o lado forte sempre…

manda um pedaço do código que vc usa pra inserir e atualizar, pra eu ter uma idéia melhor do que tá acontecendo?

Na verdade eu estou utilizando o NHibernate(Castle ActiveRecord).

Vamos especificar mais então. Cliente NxM Ocorrencias.

[code][HasAndBelongsToMany(typeof(Customer), Table = “CLIENTE_OCORRENCIA”, ColumnKey = “CD_OCORRENCIA”
, ColumnRef = “CD_CNPJ”, RelationType = RelationType.Set, Cascade = ManyRelationCascadeEnum.SaveUpdate)]
public virtual ICollection Customers
{
get { return _customers; }
set { _customers = value; }
}

    public virtual void AddOccurences(long[] cnpj)
    {
        Customer[] customers = Customer.FindBy(cnpj);

        foreach (Customer cust in customers)
        {
            _customers.Add(cust);
        }
    }[/code]

[HasAndBelongsToMany(typeof(Occurrence), Table = "CLIENTE_OCORRENCIA", ColumnKey = "CD_CNPJ", ColumnRef = "CD_OCORRENCIA", Lazy = true, Inverse = true, RelationType = RelationType.Set, Cascade = ManyRelationCascadeEnum.SaveUpdate)] public virtual ICollection<Occurrence> Occurrences { get { return _occurrences; } set { _occurrences = value; } }

Dessa forma eu busco todos os clientes para terem aquela ocorrênca, pois isso é feito em lote, então se eu selecionar três clientes para a ocorrência 1, esses três clientes deve ter essa ocorrência.

Abaixo fica o log gerado pelo log4net:

[quote]2009-11-20 13:43:14,296 [8] DEBUG NHibernate.SQL - SELECT this_.CD_CNPJ as CD1_11_0_, this_.NM_CLIENTE as NM2_11_0_, this_.DS_ENDERECO as DS3_11_0_, this_.DS_CIDADE as DS4_11_0_, this_.DS_UF as DS5_11_0_, this_.DS_EMAIL as DS6_11_0_, this_.DS_FONE as DS7_11_0_, this_.DS_CONTATO as DS8_11_0_, this_.ID_STATUS as ID9_11_0_ FROM CLIENTE this_ WHERE this_.CD_CNPJ in (?p0, ?p1, ?p2, ?p3);?p0 = 68768769876876, ?p1 = 80809808090909, ?p2 = 80980809809808, ?p3 = 80980980989080
2009-11-20 13:43:14,468 [8] DEBUG NHibernate.SQL - UPDATE OCORRENCIA SET DS_OCORRENCIA = ?p0, ID_STATUS = ?p1 WHERE CD_OCORRENCIA = ?p2;?p0 = ‘TESTE 5’, ?p1 = True, ?p2 = 5
2009-11-20 13:43:14,500 [8] DEBUG NHibernate.SQL - DELETE FROM CLIENTE_OCORRENCIA WHERE CD_OCORRENCIA = ?p0;?p0 = 5
2009-11-20 13:43:14,531 [8] DEBUG NHibernate.SQL - INSERT INTO CLIENTE_OCORRENCIA (CD_OCORRENCIA, CD_CNPJ) VALUES (?p0, ?p1);?p0 = 5, ?p1 = 68768769876876
2009-11-20 13:43:14,531 [8] DEBUG NHibernate.SQL - INSERT INTO CLIENTE_OCORRENCIA (CD_OCORRENCIA, CD_CNPJ) VALUES (?p0, ?p1);?p0 = 5, ?p1 = 80809808090909
2009-11-20 13:43:14,531 [8] DEBUG NHibernate.SQL - INSERT INTO CLIENTE_OCORRENCIA (CD_OCORRENCIA, CD_CNPJ) VALUES (?p0, ?p1);?p0 = 5, ?p1 = 80980809809808
2009-11-20 13:43:14,531 [8] DEBUG NHibernate.SQL - INSERT INTO CLIENTE_OCORRENCIA (CD_OCORRENCIA, CD_CNPJ) VALUES (?p0, ?p1);?p0 = 5, ?p1 = 80980980989080
[/quote]

Bom… eu não sei como NHibernate funciona, mas acho que você deveria usar o Property pra acessar a lista, não acessar a lista diretamente:

 public virtual void AddOccurences(long[] cnpj)  
         {  
             Customer[] customers = Customer.FindBy(cnpj);  
   
             foreach (Customer cust in customers)  
             {  
                 Customers.Add(cust);  
             }  
         }  

[]'s

Atualmente eu uso os dois, Hibernate e NHibernate em projetos distintos.

Mais usando Property como vc falou, não funcionou também. Ta teoria o NHibernate tem tudo que o Hibernate tem.

Resolvido, depois de muito tempo perdido, e muita decepção, resolvi fazer ao contrario.

Em vez de adicionar clientes a ocorrências, resolvi adicionar ocorrencia a clientes, e dai FUNCIONOU!!!.

Agora só não entendi o motivo, mais esta funcionando.

qdo vc faz um relacionamento bidirecional tem um lado forte e um lado fraco…
só funciona adicionar os elementos do lado forte…

Essa idéia de lado forte e lado fraco pra mim ainda não está exclarecido.

Vejamos, numa relação 1xN, o lado forte seria quem tem a fk, certo?

-No caso eu teria uma classe @OneToMany(que seria o lado forte) e a outra classe @ManyToOne(lado fraco).

Numa relação NxM, quando saber quem é o lado forte? Seria a relação que NÃO tem o mappedBy, certo?

  • Então eu teria uma classe @ManyToMany(com os demais atributos) ou no NHibernate(assim como é no hibernate quando mapeado em XML, Inverse=true) e outra classe @ManyToMany(mappedBy=“outra_classe”).

Esta certo?

sim… algo parecido com isso…

Esclareceu minha duvida.
Valeu lucascs, essa não foi a primeira vez que vc me ajudou com minhas dificuldades, ajudando na resolução do meu problema.

Muito obrigado mesmo.
Valeu