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!
-
Existe algum erro no mapeamento? Qual?
-
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!