Como definir uma Cascade Inversa Excluir sobre um mapeamento de muitos para um em Hibernate
Pergunta
Eu tenho duas classes A e B. Muitos B's podem ter associação com um único A, daí um relacionamento de muitos para um de B a A. Mapeei o relacionamento como:
<class name="A" table="tbl_A">
<property name="propA" column="colA"/>
</class>
<class name="B" table="tbl_B">
<property name="propB" column="colB"/>
<many-to-one name="a" class="A" column="col1" cascade="delete"/>
</class>
A não tem nada mapeado para B. Tendo isso em mente, pretendemos excluir B quando está associado A é excluído. Isso poderia ter sido possível se eu pudesse definir um inverso = "verdadeiro" na associação muitos para um em B, mas o hibernato não permite isso.
Alguém pode ajudar com isso? Não queremos escrever nada em um para isso.
Solução
Hibernar apenas cascata ao longo das associações definidas. Se A não sabe nada sobre BS, nada que você faz com um afetará a BS.
A sugestão de Pascal é, portanto, a maneira mais fácil de fazer o que você deseja:
<class name="A" table="tbl_A">
...
<set name="myBs" inverse="true" cascade="all,delete-orphan">
<key column="col1"/>
<one-to-many class="B"/>
</set>
</class>
<class name="B" table="tbl_B">
...
<many-to-one name="a" class="A" column="col1" not-null="true"/>
</class>
Observe essa configuração cascade="delete"
sobre B
Como você o possui no seu código original, não fará o que você deseja - ele diz a Hibernate para "excluir a se B for excluído", o que provavelmente resultará em violação de restrição (se houver algum outro BS vinculado a isso).
Se você absolutamente não pode adicionar uma coleção de BS a um (embora eu não consiga realmente pensar nas circunstâncias em que esse seria o caso), sua única outra alternativa é definir a exclusão de Cascade de A a B no nível da chave estrangeira; Seu BS será excluído quando você for excluído.
Esta é uma solução bastante feia, no entanto, porque você precisa ter muito cuidado com a forma como exclua um em hibernado:
- A sessão deve ser liberada antes da exclusão de A (ter atualizações pendentes para B podem resultar em um erro ou a e alguns Bs sendo inseridos nos bastidores)
- Todos os BS vinculados ao seu A (e como você não está mantendo o relacionamento de um lado que significa tudo BS) deve ser despejado de todas as sessões ativas e do 2º cache de nível.
Outras dicas
Eu acho que você precisa cascade="all,delete-orphan"
de A a B com um one-to-many
Associação.