Como faço para usar JPQL às entradas de exclusão a partir de uma tabela de associação?

StackOverflow https://stackoverflow.com/questions/1071940

  •  21-08-2019
  •  | 
  •  

Pergunta

Eu tenho um objeto APP, que tem um relacionamento muitos-para-muitos como esta:

@Entity
public class Role {
    //...

    @ManyToMany(fetch=FetchType.EAGER)
    @JoinTable(
    name="RolePrivilege",
    joinColumns=
        @JoinColumn(name="role", referencedColumnName="ID"),
    inverseJoinColumns=
        @JoinColumn(name="privilege", referencedColumnName="ID")
    )
    private Set<Privilege> privs;
}

Não é um objeto JPA para RolePrivilege, então eu não tenho certeza de como escrever uma consulta JPQL às entradas Excluir no campo privs de um objeto de papel. Por exemplo, eu tentei isso, mas ele não funciona. Ele reclama que Role.privs não está mapeada.

DELETE FROM Role.privs p WHERE p.id=:privId

Eu não tenho certeza o que mais tentar. Eu poderia, claro, apenas escrever uma consulta nativa que exclui da tabela de junção RolePrivilege. Mas, eu estou preocupado que isso iria interagir mal com objetos em cache localmente que não seria atualizado pela consulta nativa.

Será que é mesmo possível escrever JPQL para remover entradas a partir de uma tabela de associação como esta? Se não posso apenas carregar todos os objetos Papel e remover entradas da coleção privs de cada um e, em seguida, persistem cada função. Mas parece bobagem para fazer isso, se uma consulta JPQL simples vai fazer tudo de uma vez.

Foi útil?

Solução

A atualização JPQL e instruções DELETE precisa para se referir a um nome de entidade, não um nome de tabela, então eu acho que você está sem sorte com a abordagem que você sugeriu.

Dependendo do seu provedor de JPA, você pode excluir as entradas do JoinTable usando uma instrução SQL cru simples (deve ser 100% portátil) e, em seguida, programaticamente interagir com o seu provedor de cache API para expulsar os dados. Por exemplo, no Hibernate você pode chamar evict () para expirar todas as coleções "Role.privs" a partir do cache de nível 2:

sessionFactory.evictCollection("Role.privs", roleId); //evict a particular collection of privs
sessionFactory.evictCollection("Role.privs"); //evict all privs collections

Infelizmente eu não trabalho com o suficiente JPA APIs para saber ao certo o que exatamente é suportado.

Outras dicas

Eu também estava procurando uma abordagem JPQL excluir uma relação muitos-para-muitos (contidos em uma tabela juntar). Obviamente, não há nenhum conceito de mesas em um ORM, por isso não podemos usar operações DELETE ... Mas eu gostaria que houvesse um operador especial para estes casos. Algo como vincular e desvincular. Talvez um recurso futuro?

De qualquer forma, o que eu tenho feito para alcançar essa necessidade tem sido trabalhar com as coleções implementadas nos beans de entidade, aqueles que mapeiam os muitos-para-muitos relações.

Por exemplo, se eu tenho um estudante de classe que tem uma relação muitos-para-muitos com cursos:

@ManyToMany
private Collection <Courses> collCourses;

I construção na entidade um getter e setter para essa coleção. Então, por exemplo, de um EJB, eu recuperar a coleção usando o getter, adicionar ou remover o curso desejado e, finalmente, usar o setter para atribuir a nova coleção. E ele é feito. Ele funciona perfeitamente.

No entanto a minha principal preocupação é o desempenho. ORM é suposto para manter um cache enorme de todos os objetos (se não me engano), mas mesmo usá-lo a trabalhar mais rápido, eu me pergunto se recuperar todos e cada elemento de uma coleção é realmente eficaz ...

Porque para mim é o mais ineficiente como recuperar os registros de uma tabela e pós-filtro-los usando puro Java em vez de uma linguagem de consulta que trabalha direta ou undirectly com o motor DB interno (SQL, JPQL ...).

Java é uma linguagem orientada a objetos e todo o ponto de ORM é ocultar detalhes de juntar tabelas e tal de você. Consequentemente, mesmo contemplando a eliminação de uma tabela de associação sem considerar as conseqüências seria estranho.

Não, você não pode fazê-lo com JPQL, que é para entidades.

Recuperar as entidades em cada extremidade e limpar suas coleções. Isto irá remover as tabelas entradas participar. orientada a objetos.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top