Problema com persistência em relacionamento N : M

Olá pessoal,

Tenho um relacionamento de N : M entre duas entidades.

Sou novo na utilização do hibernate e segui as dicas deste site, que inclusive encontrei aqui no GUJ:

http://thiagoprocaci.blogspot.com/2009/04/mapeamento-objeto-relacional-com.html

Seguindo a mesma lógica descrita no blog, não estou conseguindo persistir a lista de serviços associada aos usuários. Qual a forma correta para persistir os dados do relacionamento? Está dando a seguinte mensagem para mim:

Criei as classes seguindo a mesma lógica que ele criou o relacionamento entre Professor e Turma. No meu caso é um relacionamento de Usuário com Serviço.
OBS: ignorei o resto dos atributos e métodos getters e setters.

[code]
public abstract class Usuario implements Serializable {

@OneToMany(fetch = FetchType.LAZY, mappedBy = "usuario")
private List<UsuarioServico> usuarioServico;

}[/code]

[code]
public class Servico implements Serializable {

@OneToMany(fetch = FetchType.LAZY, mappedBy = "servico")
private List<UsuarioServico> usuarioServico;

}[/code]

[code]
public class UsuarioServico implements Serializable {

@EmbeddedId
@AttributeOverrides( {
		@AttributeOverride(name = "idUsuario", column = @Column(name = "IDUSUARIO", nullable = false)),
		@AttributeOverride(name = "idServico", column = @Column(name = "IDSERVICO", nullable = false)) })
private Id idUsuarioServico;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "idUsuario", nullable = false, insertable = false, updatable = false)
private Usuario usuario;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "idServico", nullable = false, insertable = false, updatable = false)
private Servico servico;

@Embeddable
public static class Id implements Serializable {

	@Column(name = "idUsuario", nullable = false)
	private Long idUsuario;

	@Column(name = "idServico", nullable = false)
	private Long idServico;

	public Long getIdUsuario() {
		return this.idUsuario;
	}

	public void setIdUsuario(Long idturma) {
		this.idUsuario = idturma;
	}

	public Long getIdServico() {
		return this.idServico;
	}

	public void setIdServico(Long idprofessor) {
		this.idServico = idprofessor;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Id other = (Id) obj;
		if (idServico != other.idServico)
			return false;
		if (idUsuario != other.idUsuario)
			return false;
		return true;
	}
}

}[/code]

Agradeço antecipadamente quem puder me ajudar!

Valeu!

Olá!

Será que isso te ajuda?
http://www.guj.com.br/posts/list/201812.java#1019289
http://www.guj.com.br/posts/list/134922.java
http://www.guj.com.br/posts/list/139085.java

At.
Wallfox

Olá!

Wallfox, um dos links q vc me passou apresenta uma solução aparentemente igual a minha e uma outra solução usando @IdClass. A do IdClass eu não consegui fazer funcionar, devo ter feito alguma coisa errada. Mas fiquei curioso que a solução q eu tinha encontrado no blog é a mesma citada em um dos posts q vc passou.

Será q o problema não está em como eu estou tentando salvar o objeto? Como eu devo fazer? O q eu salvo primeiro? Eu salvo os objetos separadamente? Como é? Eu já tentei de duas formas:

Adicionar os objetos UsuarioServico no List do Usuário e tentando salvar somente o objeto Usuário. Dae dá o erro dizendo que o id é null. Daí eu tentei salvar o usuário sem o list preenchido, dae crio os objetos UsuarioServico passando o usuário já adicionado no banco para tentar salvar o objeto UsuarioServico, mas tb dá o erro dizendo que o id tá nulo. Eu acho q nos dois casos ele esteja reclamando do mesmo id estando nulo e acredito que seja o id da tabela UsuarioServico.
OBS: os serviços já estão cadastrados no banco

Agradeço a ajuda!

Valeu…

Olá,

Talvez primeiro tenhamos que acertar o conceito. Você possui uma classe Usuário e outra Serviço, neste caso um Usuário pode ter vários Serviços e um Serviço pode conter vários Usuários, se você fizer um mapeamento ManytoMany talvez resolva, pois a tabela ServiçoUsuário será criada automaticamente, sem a necessidade de criar a classe ServiçoUsuário. Qual o problema que poderá ocorrer? Você poderá adicionar um UsuarioServiço que já tenha no BD.
Outra solução seria criar a Classe Usuário, Classe Serviço, uma classe UsuárioServiçoPK que contenha a anotação @Embeddable e o relacionamento ManyToOne como passei no link e então criar a Classe UsuárioServiço com a anotação @Id em private UsuarioServicoPK idUsuarioServico = new UsuarioServicoPK()

Tenta ai e depois me fale.
Wallfox

Wallfox,

O mapeamento @ManyToMany não me serve pois na relação eu preciso armazenar um atributo.

Depois de umas buscas no fórum eu achei a mesma solução q vc sugeriu agora e hoje pela manhã consegui fazer funcionar. Só q eu vi que do jeito q eu estava fazendo também é possível e eu estava tentando resolver dessa forma. Neste momento estou brigando com o código para funcionar do jeito q eu apresentei o código aqui no fórum. :slight_smile:

Ainda tem uma outra solução usando o @IdClass mas eu já me contentaria em fazer funcionar dessa maneira q eu apresentei inicialmente, mesmo pq em minhas buscas ouvi dizer que não há ganhos usando o @IdClass. Como eu estou aprendendo hibernate, estou buscando essa solução para ampliar os conhecimentos.

Valeu pela ajuda!

Problema resolvido!

Lá em UsuarioServico eu não sabia q eu precisava preencher os atributos na pk. Eu achava q só de atribuir os atributos usuario e serviço na classe UsuarioServico ele já jogaria os ids lá pra baixo. Bem, a solução ficou assim:

public class UsuarioServico implements Serializable {

	@EmbeddedId
	@AttributeOverrides( {
			@AttributeOverride(name = "idUsuario", column = @Column(name = "IDUSUARIO", nullable = false)),
			@AttributeOverride(name = "idServico", column = @Column(name = "IDSERVICO", nullable = false)) })
	private Id idUsuarioServico;

	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "idUsuario", nullable = false, insertable = false, updatable = false)
	private Usuario usuario;

	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "idServico", nullable = false, insertable = false, updatable = false)
	private Servico servico;

    //Solução do problema
	public UsuarioServico(Usuario usuario, Servico servico) {
		this.idUsuarioServico = new Id();
		
		this.idUsuarioServico.setIdUsuario(usuario.getIdUsuario());
		this.idUsuarioServico.setIdServico(servico.getIdServico());		
		
		this.usuario = usuario;
		this.servico = servico;
	}

	@Embeddable
	public static class Id implements Serializable {

		@Column(name = "idUsuario", nullable = false)
		private Long idUsuario;

		@Column(name = "idServico", nullable = false)
		private Long idServico;

		public Long getIdUsuario() {
			return this.idUsuario;
		}

		public void setIdUsuario(Long idturma) {
			this.idUsuario = idturma;
		}

		public Long getIdServico() {
			return this.idServico;
		}

		public void setIdServico(Long idprofessor) {
			this.idServico = idprofessor;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			Id other = (Id) obj;
			if (idServico != other.idServico)
				return false;
			if (idUsuario != other.idUsuario)
				return false;
			return true;
		}
	}

}

Valeu aí WallFox…