Interessante, hibernate deleta/insere registro sem necessidade!

1 resposta
robsonmrsp

Olá amigos!

Estava fazendo alguns testes com mapeamento ManyToMany no hibernate e me deparei com uma situacao no mínimo curiosa. Explico aos poucos:

Meu exemplo consite de duas tabelas FUNCIONARIO e EVENTO, e uma tabela de relacionamento EVEN_FUNC (relacionamento MxN). o mapeamento das classes Fucnionario e Evento sao mostrados a seguir.

Classe Funcionario:

@Entity

@Table(name="funcionario")

public class Funcionario implements Serializable {

 

       private static final long serialVersionUID = 1L;

 

       @Id

       @Column(name="fun_codigo",length=5, nullable=false, precision=0, scale=5)

       private Integer codigo;

 

       @Column(name="fun_nome",length=256)

       private String nome;

 

       @ManyToMany(cascade=CascadeType.ALL)

       @JoinTable(name="even_func",

                    joinColumns=@JoinColumn(name="ef_funcionario", referencedColumnName="fun_codigo"),

                    inverseJoinColumns=@JoinColumn(name="ef_evento", referencedColumnName="eve_codigo")

       )     

       private List<Evento> eventos;

...//gets, sets e hashcode...

classe Evento:

@Entity

@Table(name="evento")

public class Evento implements Serializable{

 

       private static final long serialVersionUID = 1L;

 

       @Id

       @Column(name="eve_codigo",length=5, nullable=false, precision=0, scale=5)

       private Integer codigo;

 

       @Column(name="eve_nome", length=256, nullable=false)

       private String nome;

 

       @Column(name="eve_descricao", length=4000, nullable=false)

       private String descricao;

 

       @ManyToMany(mappedBy="eventos", cascade=CascadeType.ALL)   

       @JoinTable(name="even_func",           

                    joinColumns=@JoinColumn(name="ef_evento",referencedColumnName="eve_codigo"),                 

                    inverseJoinColumns=@JoinColumn(name="ef_funcionario", referencedColumnName="fun_codigo")

       )     

       private List<Funcionario> funcionarios ;

…//idem

O mapeamento acima foi feito seguindo as dicas dos livros Pro EJB 3 Java Persistence API , e Java Persistence with Hibernate , assim como a lógica abaixo para criar o registro na tabela de associação(ou link table, como queiram). Abaixo mostro como estou salvando os registros na tabela de associação:

public static void main(String[] args) {

 

             Session session = HibernateUtil.getSessionFactory().openSession();

             session.beginTransaction();

 

             Evento evento = (Evento)session.get(Evento.class, 4);

             Funcionario funcionario = (Funcionario)session.get(Funcionario.class, 2);

 

             funcionario.getEventos().add(evento);

             evento.getFuncionarios().add(funcionario);

 

             session.getTransaction().commit();

       }

O que achei extranho foi que, ao ver o SQL executado pelo hibernate, ví que ele deteta TODOS os registros para o Funcionario 2 e em seguida os insere novamente(como podemos obserar na continuação).

////////////////////////////////////////////////////////////////////////////////////////////////////////

Log do Hibernate:

Hibernate:

    select

        evento0_.eve_codigo as eve1_0_0_,

        evento0_.eve_descricao as eve2_0_0_,

        evento0_.eve_nome as eve3_0_0_

    from

        evento evento0_

    where

        evento0_.eve_codigo=?

Hibernate:

    select

        funcionari0_.fun_codigo as fun1_1_0_,

        funcionari0_.fun_nome as fun2_1_0_

    from

        funcionario funcionari0_

    where

        funcionari0_.fun_codigo=?

Hibernate:

    select

        eventos0_.ef_funcionario as ef1_1_,

        eventos0_.ef_evento as ef2_1_,

        evento1_.eve_codigo as eve1_0_0_,

        evento1_.eve_descricao as eve2_0_0_,

        evento1_.eve_nome as eve3_0_0_

    from

        even_func eventos0_

    left outer join

        evento evento1_

            on eventos0_.ef_evento=evento1_.eve_codigo

    where

        eventos0_.ef_funcionario=?

Hibernate:

    delete

    from

        even_func

    where

        ef_funcionario=?

Hibernate:

    insert

    into

        even_func

        (ef_funcionario, ef_evento)

    values

        (?, ?)

Hibernate:

    insert

    into

        even_func

        (ef_funcionario, ef_evento)

    values

        (?, ?)

Hibernate:

    insert

    into

        even_func

        (ef_funcionario, ef_evento)

    values

        (?, ?)

Hibernate:

    insert

    into

        even_func

        (ef_funcionario, ef_evento)

    values

        (?, ?)

Bem, vem agora a pergunta, ou as perguntas!

  1. Existe algum erro no mapeamento? Qual?

  2. se nao há erro, o que fazer para que o hibernate nao precise realizar essas deleções “desnecessárias”? Acredito que isso seja caro para o banco!

Caso queiram fazer seus próprios testes lhes envio os fontes quase completos , assim como o DDL de criacao das tabelas.

Favor, comentar!

1 Resposta

C

Robson, isso e normal mesmo…
Antes tinha que fazer isso na mão, guardar os registros numa lista, limpar os relacionamentos da tabela e depois inseri-los novamente…
Deve ser algum gambiarra que o hibernate faz…eu também fico meio preocupado, porque se tiver milhões de registros vai demorar para ele fazer tudo…

Criado 1 de junho de 2010
Ultima resposta 16 de jul. de 2010
Respostas 1
Participantes 2