Pergunta

Eu tenho tentado para se familiarizar com o atributo inverso do Hibernate, e parece ser apenas uma daquelas coisas que é conceitualmente difícil.

A essência que eu tenho é que quando você tem uma entidade pai (por exemplo Parent), que tem uma coleção de objetos filho usando um one-to-many mapeamento, estabelecendo inverso = true no mapeamento informa ao Hibernate que 'o outro lado (a criança) tem a responsabilidade de atualizar-se para manter a referência de chave estrangeira em sua mesa'.

Fazendo isto parece ter 2 benefícios quando se trata de acrescentar Crianças para a coleção em seu código, e depois salvar o Pai (com cascata tudo pronto): salvar um hit desnecessária na banco de dados (porque sem conjunto inversa, Hibernate pensa que tem dois lugares para atualizar a relação FK), e de acordo com os documentos oficiais :

Se a coluna de um associação é declarado NOT NULL, NHibernate pode causar violações de restrição quando se cria ou atualiza a associação. Prevenir esse problema, você deve usar um associação bidirecional com o muitos final valorizado (o conjunto ou saco) marcado como inverse = "true".

Isso tudo parece fazer sentido até agora. O que eu não entendo é o seguinte:? Em que não quiser usar inverso = true em um relacionamento um-para-muitos

Foi útil?

Solução

Como Matthieu diz, o único caso em que você não gostaria de conjunto inverso = true é o lugar onde isso não faz sentido para a criança a ser responsável por atualizar-se, como no caso em que a criança não tem conhecimento de seu pai.

Vamos tentar um mundo real, e não em todos exemplo artificial:

<class name="SpyMaster" table="SpyMaster" lazy="true">
  <id name="Id">
    <generator class="identity"/>
  </id>
  <property name="Name"/>
  <set name="Spies" table="Spy" cascade="save-update">
    <key column="SpyMasterId"/>
    <one-to-many class="Spy"/>
  </set>
</class>

<class name="Spy" table="Spy" lazy="true">
  <id name="Id">
    <generator class="identity"/>
  </id>
  <property name="Name"/>
</class>

spymasters pode ter espiões, mas espiões nunca sabe quem é seu espião é, porque nós não incluímos o relacionamento muitos-para-um na classe de espionagem. Também (convenientemente) um espião pode virar desonestos e por isso não precisa ser associado com um espião. Podemos criar entidades da seguinte forma:

var sm = new SpyMaster
{
    Name = "Head of Operation Treadstone"
};
sm.Spies.Add(new Spy
{
    Name = "Bourne",
    //SpyMaster = sm // Can't do this
});
session.Save(sm);

Em tal caso, você deve definir a coluna FK para ser anulável porque o ato de sm de poupança poderia inserir na tabela do Spymaster ea tabela de Spy, e só depois que ele, em seguida, atualizar a tabela Spy para definir o FK. Neste caso, se fôssemos conjunto inverso = true, o FK nunca iria ficar atualizado.

Outras dicas

Apesar da resposta de alta votado aceito, eu tenho uma outra resposta para isso.

Considere um diagrama de classe com essas relações:

Parent => list of Items
Item => Parent

Ninguém nunca disse, que o item => relação Parent é redundante ao Pai => relação Items. Um item pode fazer referência a qualquer pai.

Mas em seu aplicativo, você sabe que as relações são redundantes . Você sabe que as relações não precisam ser armazenados separadamente no banco de dados. Então você decide armazená-lo em uma única chave estrangeira , apontando a partir do item para o pai. Esta informação mínima é suficiente para construir a lista e parte de trás de referência.

Tudo que você precisa fazer para mapear isso com NH é:

  • usar a mesma chave estrangeira para ambas as relações
  • dizer NH que um (a lista) é redundante para o outro e pode ser ignorado quando armazenar o objeto. (Isso é o que NH realmente faz com inverse="true")

Estes são os pensamentos que são relevantes para o inverso. Nada mais. Não é uma escolha, não é apenas uma forma de mapeamento correto.


O Espião Problema : É uma discussão completamente diferente se quiser apoiar uma referência do item para o pai. Isso é com o seu modelo de negócio, NH não tomar quaisquer decisões neste. Se uma das relações está faltando, há, naturalmente, nenhuma redundância e sem uso de inverso.

Desvio: Se você usar inverse = "true" em uma lista que não tem nenhuma redundância na memória, ele simplesmente não ficam armazenados. Se você não especificar o inverso = "true" se ele deve estar lá, NH podem armazenar a informação redundante duas vezes.

Se você quer ter uma associação unidirecional ou seja, que as crianças não podem navegar para o pai. Se assim for, você coluna FK deve ser NULLABLE porque as crianças serão salvas antes do pai.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top