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:
[code]@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;
}
}
[/code]
[code]@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;
}
}
[/code]
O problema ocorre ao tentar remover um registro de Contato, segue o método no EJB:
[code] 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);
}[/code]
É 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…