Cometi um pequeno erro ao tentar definir um mapeamento entre duas entidades, o que acabou tornando o atributo DELETE_ORPHAN sem efeito. Trata-se de um mapeamento entre uma entidade denominada Documento e outra Signatario. Um Documento possui uma coleção de Signatários.
A classe Signatario tem como chave primária o identificador do usuário (idusuario) e o identificador do documento (iddocumento). A tabela, no Oracle, possui os campos iddocumento e idusuario, ambos como chave primária. Tenho, então, três classes: Usuario, Documento e Signatario. Para mapear o ID da classe Signatario foi necessário recorrer às composite-id do Hibernate.
@Entity @Table(name="SIGNATARIO") public class Signatario { @EmbbededId private SignatarioPK pk; }
A classe SignatarioPK ficou assim:
@Embeddable @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) public class SignatarioPK implements Serializable { private Usuario usuario; private Documento documento; @ManyToOne(fetch=FetchType.EAGER) @Cascade(value={org.hibernate.annotations.CascadeType.DELETE_ORPHAN}) @JoinColumn(name="IDDOCUMENTO") public Documento getDocumento() { return documento; } public void setDocumento(Documento documento) { this.documento = documento; } @ManyToOne(fetch=FetchType.EAGER) @JoinColumn(name="IDUSUARIO") public Usuario getUsuario() { return usuario; } public void setUsuario(Usuario usuario) { this.usuario = usuario; } }
Quando eu crio um documento, crio também os signatários e coloco na coleção. Configurei o Hibernate para incluir os signatários automaticamente no banco de dados, já fazendo o relacionamento entre as duas tabelas. O problema é que ao remover um objeto da coleção e solicitar ao Hibernate para salvar o objeto Documento, ele define o campo iddocumento, da tabela Signatarios, como NULL.
Na classe Documento, a coleção está mapeada da seguinte forma:
@OneToMany @Cascade(value={org.hibernate.annotations.CascadeType.ALL, org.hibernate.annotations.CascadeType.DELETE_ORPHAN}) @JoinColumn(name = "IDDOCUMENTO") public Collection getSignatarios() { return signatarios; }
O erro ocorre, pois o mapeamento acima referencia uma JoinColumn específica. Mas o objeto filho (Signatarios) é formado por duas chaves primárias. Portanto, para que o Hibernate remova seus “órfãos”, este mapeamento deve ser assim:
@OneToMany(mappedBy="pk.documento") @Cascade(value={org.hibernate.annotations.CascadeType.DELETE_ORPHAN, org.hibernate.annotations.CascadeType.ALL}) public Collection getSignatarios() { return signatarios; }
Feito isto, o mapeamento funciona da forma como eu queria.