Hibernate, JPA - Problemas com relacionamento ManyToMany

Perae, eu não precisaria especificar assim não?
Tipo:
O nome das chaves primárias das tabelas pai.
Que no caso seriam ID_PERFIL e ID PERMISSAO:

PERFIL


ID_PERFIL Nome
1 Administrador

PERMISSAO


ID_PERMISSAO Nome
1 Perm1
2 Perm2
3 Perm3

O nome das chaves estrangeiras que estão na tabela filho.
Que no caso também seriam ID_PERFIL e ID PERMISSAO:

PERFIL_PERMISSAO


ID_PERFIL ID_PERMISSAO
1 1
1 2
1 3

Do jeito que estava já funcionava a listagem de Perfis e das Permissões, só na hora de incluir um novo Perfil que dá o problema.

Fiquei confuso. Desculpe se não fui claro.

Você fez a alteração que eu falei acima?

Sim, coloquei as annotations em cima dos atributos, mas não faz diferença.

Já na parte do relacionamento está assim:

    joinColumns = { @JoinColumn(name = "ID_PERFIL")},    
    inverseJoinColumns={@JoinColumn(name="ID_PERMISSAO")})  

É nisso que estou confuso, do jeito que você disse ficaria assim:
joinColumns = { @JoinColumn(name = “ID_PERFIL”)}, inverseJoinColumns={@JoinColumn(name=“ID_PERFIL”)})

Mas e onde entraria o ID_PERMISSAO?

Velho para que vc quer numerar a permissão?? Veja o relacionamento que fiz abaixo, aqui acontece o seguinte o relacionamento pega o id do usuario joga pra tabela do nessa tabela existe uma role pra esse usuario ponto final.

package financeiro.usuario;

import java.io.Serializable;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.*;

import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
@Table(name= "usuario")
public class Usuario implements Serializable{

	private static final long serialVersionUID = -7390392097656238443L;
	
	@Id
	@GeneratedValue
	private Integer codigo;
	private String nome;
	private String email;
	@org.hibernate.annotations.NaturalId
	private String login;
	private String senha;
	private Date nascimento;
	private String celular;
	private String idioma;
	private boolean ativo;
	
	//relação pai e filho
	//necessario para informar o tipo de dado da hashset.
	@ElementCollection(targetClass = String.class)
	@JoinTable(
			name="usuario_permissao",
			uniqueConstraints = {@UniqueConstraint(columnNames = {"usuario", "permissao"})},//constroi um indice unico entre as colunas usuario e permissao
			joinColumns = @JoinColumn(name = "usuario"))//diz a qual coluna da tabela filho a tabela pai vai se ligar
	@Column(name = "permissao", length=50)
	private Set<String> permissao = new HashSet<String>();
	
	public Integer getCodigo() {
		return codigo;
	}
	public void setCodigo(Integer codigo) {
		this.codigo = codigo;
	}
	public String getNome() {
		return nome;
	}
	public void setNome(String nome) {
		this.nome = nome;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getLogin() {
		return login;
	}
	public void setLogin(String login) {
		this.login = login;
	}
	public String getSenha() {
		return senha;
	}
	public void setSenha(String senha) {
		this.senha = senha;
	}
	public Date getNascimento() {
		return nascimento;
	}
	public void setNascimento(Date nascimento) {
		this.nascimento = nascimento;
	}
	public String getCelular() {
		return celular;
	}
	public void setCelular(String celular) {
		this.celular = celular;
	}
	public String getIdioma() {
		return idioma;
	}
	public void setIdioma(String idioma) {
		this.idioma = idioma;
	}
	public boolean isAtivo() {
		return ativo;
	}
	public void setAtivo(boolean ativo) {
		this.ativo = ativo;
	}
	public Set<String> getPermissao() {
		return permissao;
	}
	public void setPermissao(Set<String> permissao) {
		this.permissao = permissao;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + (ativo ? 1231 : 1237);
		result = prime * result + ((celular == null) ? 0 : celular.hashCode());
		result = prime * result + ((codigo == null) ? 0 : codigo.hashCode());
		result = prime * result + ((email == null) ? 0 : email.hashCode());
		result = prime * result + ((idioma == null) ? 0 : idioma.hashCode());
		result = prime * result + ((login == null) ? 0 : login.hashCode());
		result = prime * result
				+ ((nascimento == null) ? 0 : nascimento.hashCode());
		result = prime * result + ((nome == null) ? 0 : nome.hashCode());
		result = prime * result
				+ ((permissao == null) ? 0 : permissao.hashCode());
		result = prime * result + ((senha == null) ? 0 : senha.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Usuario other = (Usuario) obj;
		if (ativo != other.ativo)
			return false;
		if (celular == null) {
			if (other.celular != null)
				return false;
		} else if (!celular.equals(other.celular))
			return false;
		if (codigo == null) {
			if (other.codigo != null)
				return false;
		} else if (!codigo.equals(other.codigo))
			return false;
		if (email == null) {
			if (other.email != null)
				return false;
		} else if (!email.equals(other.email))
			return false;
		if (idioma == null) {
			if (other.idioma != null)
				return false;
		} else if (!idioma.equals(other.idioma))
			return false;
		if (login == null) {
			if (other.login != null)
				return false;
		} else if (!login.equals(other.login))
			return false;
		if (nascimento == null) {
			if (other.nascimento != null)
				return false;
		} else if (!nascimento.equals(other.nascimento))
			return false;
		if (nome == null) {
			if (other.nome != null)
				return false;
		} else if (!nome.equals(other.nome))
			return false;
		if (permissao == null) {
			if (other.permissao != null)
				return false;
		} else if (!permissao.equals(other.permissao))
			return false;
		if (senha == null) {
			if (other.senha != null)
				return false;
		} else if (!senha.equals(other.senha))
			return false;
		return true;
	}
	
}

Observe que só precisa de um relacionamento, coloque do jeito que falei e me mostre o erro novamente.

Desculpe, não entendi do jeito que você disse.
E para não ficar te perguntando sobre isso, fiquei fazendo uns testes. E então descobri que o relacionamento que estou fazendo está funcionando perfeitamente.

Chegamos a um avanço, o que fiz foi o seguinte:

No método salvar, inseri manualmente o ID do PERFIL e o ID de uma PERMISSAO. E veja só, funcionou! =D

	public String salvar(){	
             //Inserindo manualmente:
			perfil.setId(6);
			Permissao permissao = new Permissao();
			permissao.setId(1);
			List <Permissao> perms = new ArrayList<Permissao>(); 
			perms.add(permissao);
			perfil.setPermissoes(perms);
              //.
	        if (this.perfil.getId() == 0){  
	            JSFMensageiro.info("Perfil incluido com sucesso!");  
	        }  
	        else{  
	            JSFMensageiro.info("Perfil alterado com sucesso.");    
	        }  

			new PerfilHIB().salvar(this.perfil);
			this.perfil = new Perfil();
			perfis = new PerfilHIB().listar();
			return "success";
	}

Então o problema é que os ids estão chegando vazios.
Tu poderia checar o meu formulário de inserção/Alteração de Perfil? Não consegui encontrar nada de errado nele. (Foi postado mais no início)
Será que pode ser algum problema também com o Converter?

Valeu cara!

Velho você lembra daquela linha no formulário que eu falei que vc teria que colocar para alimentar o id do perfil??

	<h:inputHidden value="#{UsuarioBean.usuario.codigo}"/>

Esse código parece inútil a primeira vista mais depois você vai ver que ele está ativando a propriedade pelo set e então o método set usara a propriedade e então a annotation entrara em ação gerando um valor.

[quote=Mathe] Velho você lembra daquela linha no formulário que eu falei que vc teria que colocar para alimentar o id do perfil??

	<h:inputHidden value="#{UsuarioBean.usuario.codigo}"/>

Esse código parece inútil a primeira vista mais depois você vai ver que ele está ativando a propriedade pelo set e então o método set usara a propriedade e então a annotation entrara em ação gerando um valor.[/quote]

Agora dá o seguinte erro:

org.hibernate.PropertyAccessException: could not get a field value by reflection getter of entityBean.Permissao.id
..........

Caused by: java.lang.IllegalArgumentException: Can not set int field entityBean.Permissao.id to java.lang.String

Está dizendo que não existe o getId da Permissao, correto? Mas ele está lá. =/

Agora só esta dando o seguinte erro quando a gente pega o valor, da pagina jsf no caso ele esta indo como string mas a propriedade e int. Mas agora esta tudo quase certo só falta a gente conseguir ajeitar essa inserção

Como está a propriedade id e seus getters e setters? No banco de dados como está a coluna int? está para receber numeros inteiros ou caracteres?

No banco o ID é do tipo int.

Na classe Permissao, já testei o ID como int e Integer. Acontece o mesmo.

Analisa o caminho que o ID está fazendo desde que vc cilca em salvar até chegar no banco e ve se em alguma parte desse caminho o id está sendo colocado em uma propriedade string

Observei com o debug e nada.

To pensando que pode ser algo relacionado com o converter. Apesar de já ter utilizado desta maneira, dá uma olhada aí:

public class PermissaoConverter implements Converter {
	public Object getAsObject(FacesContext context, UIComponent component, String value) throws ConverterException {
		if (value == null)
			return null;
		return new PermissaoHIB().consultar(Integer.parseInt(value));
	}

	public String getAsString(FacesContext context, UIComponent component, Object object) throws ConverterException {
		if (object == null)
			return null;
		Permissao permissao = (Permissao) object;
		return Integer.toString(permissao.getId());
	}
}

Tenso…

Relacionado ao converter não pode ser por que o converter trata o objeto inteiro e não só a propriedade, além do no erro esta especificando que a entrada de um argumento errado está vindo do id, faz assim ó pega o id que está entrando no objeto com o código <h:inputHidden que eu te mandei lembra?? Então esse código esta alimentando o id do objeto antes de salvar esse objeto recupere o id e faça a conversão de String para Integer.

Veja só o que descobri.
O formulário está mandando uma lista de permissões vazias. '.'
Para fazer alguns testes, no método salvar fiz assim:
perfil.getPermissoes().size (E retorna o número de permissões que escolhi no formulário)
E depois fiz um foreach pra correr a lista inteira e imprimir o que tinha, mas não imprime nada.

Muito curioso. :?

LOL velho achei o problema está aqui ó, itemValue="#{permissao.id}" tira isso só da sua view cara, agora ficou claro por que está dando erro de tentativa de conversão inesperada hahaha.

Pior que não, tirei e dá o mesmo erro. Tentei também assim itemValue="#{permissao}" e não deu.

Acrescentando…
O estranho é que sempre aparece isso:

Tem algum componente na sua página xhtml com o id permissoes?

Não, a única parte que tem uma lista de permissões é no select:

				<p:selectManyCheckbox value="#{perfilMB.perfil.permissoes}" layout="pageDirection">
					<f:selectItems value="#{permissaoMB.permissoes}" var="permissao"   itemLabel="#{permissao.nome}"/>
				</p:selectManyCheckbox>

Me diz uma coisa mesmo depois de vc ter tirado o itemValue="#{permissao.id} ele continuou dando o erro :

org.hibernate.PropertyAccessException: could not get a field value by reflection getter of entityBean.Permissao.id  
..........  
  
Caused by: java.lang.IllegalArgumentException: Can not set int field entityBean.Permissao.id to java.lang.String  

Sim, exatamente o mesmo. =/