Problema em relacionamento @OneToMany

0 respostas
samba-jazz

Olá, estou passando por um estranho problema com um relacionamento bidirecional @OneToMany e @ManyToOne entre as classes Contato e FaleConosco.

Seguem as classes com os relacionamentos:

@SuppressWarnings("serial")
@Entity
@Table(name = "prt_contato")
@SequenceGenerator(name = "seqPrtContato", sequenceName = "seq_prt_contato", allocationSize = 1)
public class Contato implements Serializable {

	@Id
	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seqPrtContato")
	@Column(nullable = false)
	private Integer idContato;

	@Column(nullable = false, length = 50)
	private String nome;

	@Column(nullable = false, length = 100)
	private String emailDestinatario;

	@Column(nullable = false)
	private Idioma idioma;
	
	@OneToMany(mappedBy = "contato")
	private List<FaleConosco> faleConoscos = new ArrayList<FaleConosco>();

	@Version
	private Integer optlock;

	public Integer getIdContato() {
		return idContato;
	}

	public void setIdContato(Integer idContato) {
		this.idContato = idContato;
	}

	public String getNome() {
		return nome;
	}

	public void setNome(String nome) {
		this.nome = nome;
	}

	public String getEmailDestinatario() {
		return emailDestinatario;
	}

	public void setEmailDestinatario(String emailDestinatario) {
		this.emailDestinatario = emailDestinatario;
	}

	public Idioma getIdioma() {
		return idioma;
	}

	public void setIdioma(Idioma idioma) {
		this.idioma = idioma;
	}

	public Integer getOptlock() {
		return optlock;
	}

	public void setOptlock(Integer optlock) {
		this.optlock = optlock;
	}

	public List<FaleConosco> getFaleConoscos() {
		return faleConoscos;
	}

	public void setFaleConoscos(List<FaleConosco> faleConoscos) {
		this.faleConoscos = faleConoscos;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((emailDestinatario == null) ? 0 : emailDestinatario.hashCode());
		result = prime * result + ((idioma == null) ? 0 : idioma.hashCode());
		result = prime * result + ((nome == null) ? 0 : nome.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (!(obj instanceof Contato)) {
			return false;
		}
		Contato other = (Contato) obj;
		if (emailDestinatario == null) {
			if (other.emailDestinatario != null) {
				return false;
			}
		} else if (!emailDestinatario.equals(other.emailDestinatario)) {
			return false;
		}
		if (idioma != other.idioma) {
			return false;
		}
		if (nome == null) {
			if (other.nome != null) {
				return false;
			}
		} else if (!nome.equals(other.nome)) {
			return false;
		}
		return true;
	}
}
@SuppressWarnings("serial")
@Entity
@Table(name = "prt_faleconosco")
@SequenceGenerator(name = "seqPrtFaleConosco", sequenceName = "seq_prt_faleconosco", allocationSize = 1)
public class FaleConosco implements Serializable {

	@Id
	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seqPrtFaleConosco")
	@Column(nullable = false)
	private Integer idFaleConosco;

	@Column(nullable = false, length = 50)
	private String nome;

	@Column(nullable = false, length = 50)
	private String email;

	@Column(nullable = false, length = 5)
	private String dddTelefone;

	@Column(nullable = false, length = 8)
	private String numeroTelefone;

	@Column(nullable = false, length = 1000)
	private String mensagem;

	@Column(nullable = false)
	@Temporal(TemporalType.TIMESTAMP)
	private Date dataHora;

	@Column(nullable = false, length = 50)
	private String assunto;

	@ManyToOne(optional = false)
	@JoinColumn(name = "idcontato")
	private Contato contato;

	@Version
	private Integer optlock;

	public Integer getIdFaleConosco() {
		return idFaleConosco;
	}

	public void setIdFaleConosco(Integer idFaleConosco) {
		this.idFaleConosco = idFaleConosco;
	}

	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 getDddTelefone() {
		return dddTelefone;
	}

	public void setDddTelefone(String dddTelefone) {
		this.dddTelefone = dddTelefone;
	}

	public String getNumeroTelefone() {
		return numeroTelefone;
	}

	public void setNumeroTelefone(String numeroTelefone) {
		this.numeroTelefone = numeroTelefone;
	}

	public String getMensagem() {
		return mensagem;
	}

	public void setMensagem(String mensagem) {
		this.mensagem = mensagem;
	}

	public Date getDataHora() {
		return dataHora;
	}

	public void setDataHora(Date dataHora) {
		this.dataHora = dataHora;
	}

	public String getAssunto() {
		return assunto;
	}

	public void setAssunto(String assunto) {
		this.assunto = assunto;
	}

	public Contato getContato() {
		return contato;
	}

	public void setContato(Contato contato) {
		this.contato = contato;
	}

	public Integer getOptlock() {
		return optlock;
	}

	public void setOptlock(Integer optlock) {
		this.optlock = optlock;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((dataHora == null) ? 0 : dataHora.hashCode());
		result = prime * result + ((idFaleConosco == null) ? 0 : idFaleConosco.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (!(obj instanceof FaleConosco)) {
			return false;
		}
		FaleConosco other = (FaleConosco) obj;
		if (dataHora == null) {
			if (other.dataHora != null) {
				return false;
			}
		} else if (!dataHora.equals(other.dataHora)) {
			return false;
		}
		if (idFaleConosco == null) {
			if (other.idFaleConosco != null) {
				return false;
			}
		} else if (!idFaleConosco.equals(other.idFaleConosco)) {
			return false;
		}
		return true;
	}
}

O problema ocorre ao tentar remover um registro de Contato, segue o método no EJB:

public void remove(Integer id) {
		Contato contato = em.find(Contato.class, id);

		if (contato == null) {
			throw new BusinessException("Registro inexistente", "erroRegistroInexistente");
		}

		if (!contato.getFaleConoscos().isEmpty()) {
			throw new BusinessException("Existem registros de fale conosco vinculados ao contato",
					"erroContatoComFaleConosco");
		}

		em.remove(contato);
	}

É feita uma verificação, se houverem registros de FaleConosco vinculados ao Contato, então é lançada exceção não permitindo a remoção, até aí tudo bem.

Foi cadastrado um registro de contato e um de fale conosco vinculado a esse contato, só que quando a linha "contato.getFaleConoscos().isEmpty()" é executada, ela retorna true, como se não tivessem registros vinculados ao contato, o que na verdade está errado, existe registro vinculado.

Após a execução dessa verificação, é executado o "em.remove(contato)", aí outro problema ocorre, o método fica travado e não dá mais retorno, chega até a colocar no log a execução do seguinte sql:

DELETE FROM prt_contato WHERE ((IDCONTATO = ?) AND (OPTLOCK = ?))
	bind => [13, 1]

e fica preso aí...

Dúvidas:

1 - Por que quando é executada "contato.getFaleConoscos().isEmpty()" a lista está vindo vazia, sendo que existem registros associados ao contato?

2 - Por que a execução fica travada? (parece que ocorre algo como a abertura de uma transação e a mesma ficando aberta sem efetuar commit)

Sugestões?

É usado JPA 1.0 com implementação do toplink rodando num glassfish 2.1.

PS: Existe outro relacionamento semelhante aqui entre outras classes e funciona perfeitamente, no caso do "remove" é feita a mesma verificação e funciona....

Criado 22 de setembro de 2010
Respostas 0
Participantes 1