Delete em relação many to many

Olá pessoal

O problema é o seguinte:

Tenho duas tabelas do tipo

Usuario:
id_usuario
nome_usuario

Grupo:
id_grupo
nome_grupo

Um usuário pode fazer parte de vários grupos e um grupo pode ter vários usuários, ou seja ManyToMany

Portanto tenho uma tabela intermediária
Usuario_Grupo
id_usuario_grupo
id_usuario
id_grupo

Até aí está funcionando. Tenho as entidades mapeadas e inserindo normalmente. Se necessito deletar alguem da entidade Usuario ele deleta da entidade UsuarioGrupo e se eu preciso deletar um grupo ele deleta também do UsuarioGrupo.

O que ocorre é o seguinte. Eu quero deletar objetos da entidade UsuarioGrupo. Isto eu consigo mas gostaria de fazer em lote como o SQL faz. No SQL (Mysql) eu faria assim:

DELETE FROM usuario_grupo WHERE id_usuario = 45;

Ocorre que a entidade mapeada não tem id_usuario como inteiro e sim como um atributo do tipo Usuario

Tentei fazer assim em JPA

DELETE FROM UsuarioGrupo ug WHERE ug.usuario.idUsuario = 45

Normalmente se necessido fazer isso no select não tem problema pois a entidade UsuarioGrupo guarda a referencia a entidade Usuario e não o id_usuario. Internamente o hibernate faz isso.

O problema é que o JPA não deleta se usar inner join ( ug.usuario.idUsuario).

tentei enganar fazendo algo como

DELETE FROM UsuarioGrupo ug WHERE ug.idUsuarioGrupo IN (SELECT ug.idUsuarioGrupo FROM UsuarioGrupo ug WHERE ug.usuario.idUsuario = 45 )

Mas isso parece não funcionar nem no SQL.

Não estou querendo fazer uma consulta, jogar uma lista e ir iterando e deletando objeto por objeto.

Alguém tem uma luz?


faz isso e ve se funciona =P

faz isso e ve se funciona =P

[quote=darklordkamui] @ManyToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})

faz isso e ve se funciona =P

[/quote]

Cara, estou longe do código agora para ver mas não me parece este o problema.

O problema é que a entidade UsuarioGrupo não guarda campos do tipo Integer.As entidades estão mais ou menos assim:


class Usuario Extends Serialize {

@ID
...
private Integer idUsuario;

@OneToMany
List<UsuarioGrupo> listUsuarioGrupo;

}


class UsuarioGrupo Extends Serialize {

@ID
...
private Integer idUsuario;

@ManyToOne
Usuario usuario;

}

Sei que está faltando bastante coisa ai mas dá para entender.

Digamos que eu queira acessar na tabela usuario_grupo o campo id_usuario no java eu tenho que chamar o Objeto UsuarioGrupo. Algo assim:

Integer idUsuario = usuarioGrupo.usuario.getIdUsuario();

Veja que eu tenho o objeto usuarioGrupo mas para acessar o id_usuario eu tenho que ir na entidade associada Usuario e pegar o idUsuario dela.

Para SELECTs, Inserts vai bem. o Problema é o delete que não permite join

O SELECT que quero fazer é

DELETE FROM usuario_grupo WHERE id_usuario = 45;

Eu posso fazer assim:

Query query = session.createQuery("SELECT ug FROM UsuarioGrupo WHERE ug.usuario.idUsuario = 45");
List<UsuarioGrupo> listUsuarioGrupo = query.getResultList();
for(UsuarioGrupo usuariogrupo: listUsuarioGrupo) {
        //Deleto cada usuarioGrupo por vez pois eu tenho o objeto
}

Veja que o problema não é impedimento de deletar. O problema é que não consigo fazer isso em uma chamada só no banco.

bom pelo que vi se vc quiser deletar o usuario blz… ele deleta normalmente… mais ao vc deletar o grupo é necessario que ele faça a deleção em cascata… entao seu problema ta no @OneToMany

entao vc precisa fala pro @OneToMany deletar os relacionamentos que o grupo possui…

que foi o que postei mais modifica aonde ta o OneToMany e faz um delete simples no grupo… que ele ira deletar normalmente… lembrando que isso é um validação do Hibernate 3.5+ se nao vc vai ter que implementar na Mão igual ta fazendo atualmente

um exemplo de como eu faço mapeamento…

@OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH}, mappedBy = "pai") @Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.DELETE, org.hibernate.annotations.CascadeType.MERGE, org.hibernate.annotations.CascadeType.PERSIST, org.hibernate.annotations.CascadeType.DELETE_ORPHAN}) private List<Filho> filhos = new ArrayList<Filho>();

Vamos lá novamente

São 3 tabelas e 3 entidades

Tabela1: usuario
Tabela2: grupo
Tabela 3(Junção) usuario_grupo

algo assim:

usuario-------------usuario_grupo-------------grupo
--------1------------m-------------m------------1

na tabela usuario_grupo eu tenho 3 colunas
Int id (Auto_increment)
Int id_usuario
Int id_grupo

mas na entidade UsuarioGrupo eu tenho

Integer Id;
Usuario usuario;
Grupo grupo;

Veja que pela entidade eu não tenho o id_usuario nem o id_grupo diretamente. Eu tenho que acessar a entidade relacionada para pegar o id
usuarioGrupo.usuario.idUsuario

Entretanto não consigo fazer “DELETE FROM UsuarioGrupo Where idUsuario = 42” pois não tem idUsuario. o que tem é usuario.idUsuario

Eu não quero deleção em cascata. Não quero deletar os objetos de Usuario nem de Grupo. Apenas o Relacionamento (UsuarioGrupo) entre eles.

O problema aqui é que estás a repetir o alias ug.

Algo assim deveria funcionar:

DELETE FROM UsuarioGrupo ug WHERE ug.idUsuarioGrupo IN (SELECT ug2.idUsuarioGrupo FROM UsuarioGrupo ug2 WHERE ug2.usuario.idUsuario = 45 )

Outra opção é mapeares na entidade UsuarioGrupo os ids de usuario e grupo para além dos próprios objetos. Estes campos teriam insertable e updatable a false.
Aí já poderias fazer

DELETE FROM UsuarioGrupo ug WHERE ug.idUsuario = 45

eu tive que botar o @JoinTable … o hibernate parece não saber quando é uma relação @ManyToMany … ai ele não sabe de onde deletar

no meu caso ficou assim …

@ManyToMany(cascade = { CascadeType.REFRESH, CascadeType.PERSIST }, fetch = FetchType.LAZY, targetEntity = SysDepartment.class) @JoinTable(name = "SYSTB_Department_users", joinColumns = {@JoinColumn(name="users_id", referencedColumnName = "id")}, inverseJoinColumns = {@JoinColumn(name="departments_id", referencedColumnName = "id")} ) @Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE) public Set<SysDepartment> getDepartments() { if(departments == null) { departments = new LinkedHashSet<SysDepartment>(); } return departments; }

O erro estava no JPQL

Ficou assim:

Query query = this.getEntityManager().createQuery("DELETE FROM UsuarioGrupo WHERE usuario.idUsuario =  :idUsuario");

Primeiro erro: DELETE não tem alias "UsuarioGrupo ug"
Segundo erro: Não se usa ug.usuario.idUsuario e sim usuario.idUsuario.

Obrigado pela ajuda.

Alguem sabe como marco o tópico como resolvido?