Pergunta

Supondo que os seguintes mapeamentos sejam fornecidos:

<class name="A" table="a_table">
  <id name="id"/>
  <many-to-one name="entityB" column="fk_B" not-null="false" unique="true"/>
</class>

<class name="B" table="b_table">
  <id name="id"/>
</class>

Classe Java:

public class A {
   private long id;
   private B entityB;
   // getters and setters skipped
}

É possível mudar o mapeamento de hibernato para que A chave estrangeira ainda é aplicada e criada por Hibernate na startup, mas aula A pareceria o seguinte:

public class A {
   private long id;
   private long idOfB;
   // getters and setters skipped
}

Eu entendo que se eu converter <many-to-one... dentro de <property... Isso funcionaria, mas a chave estrangeira não seria aplicada pelo banco de dados.

Eu preciso fazer isso porque objeto B pode (ou não) ser inicializado separadamente, o que às vezes causaorg.hibernate.LazyInitializationException: could not initialize proxy - no Session exceções a ocorrer quando a.getB() é chamado. Eu preferiria tê -lo como um long idOfB e carregar um objeto inteiro sempre que for necessário; Isso também tornaria o carregamento do objeto A mais rápido.

Eu acredito que minha pergunta é muito semelhante a Este, no entanto, a solução oferecida (para usar carregamento preguiçoso) não é apropriado no meu caso, mesmo que eu ligue a.getB().getId(), Eu pegaria LazyInitializationException Considerando que se eu ligar a.getIdOfB() Eu não faria.

Muito obrigado antecipadamente.

Foi útil?

Solução

Como dito

Eu entendo que se eu converter Mas a chave estrangeira não seria aplicada pelo banco de dados.

Então, meu conselho é: use ambos

public class EntityA {

    private Integer idOfB;

    private EntityB entityB;

    // getter's and setter's

}

E

<class name="A" table="a_table">
    <id name="id"/>
    <property name="idOfB" column="fk_B" not-null="false" unique="true"/>
    <many-to-one name="entityB" update="false" insert="false" column="fk_B"/>
</class>

Observe quando duas propriedades compartilham a mesma coluna, Você tem que colocar configurações sobre isso em apenas uma propriedade. Caso contrário, o Hibernate reclamará alguns erros. Ele explica por que eu defino update = "false" e insert = "false" na propriedade EntityB.

Saudações,

Outras dicas

Você sempre pode criar a chave estrangeira DDL manualmente no seu arquivo hibernado hbm.xml:

<hibernate-mapping>
    ...
    <database-object>
        <create>[CREATE FK]</create>
        <drop>[DROP FK]</drop>
    </database-object> 
</hibernate-mapping>

Você também pode procurar isso se diferentes dialetos precisarem ser suportados.

Verificação de saída 5.7. Objetos de banco de dados auxiliares

Outra abordagem que você pode adotar é definir o FK com seu mapeamento B, em vez do mapeamento A. Eu adicionei o código JPA, você teria que traduzir isso no seu arquivo de mapeamento de hibernato se você não estiver usando anotações.

@Entity
public class B
{
    private long id;
    private List<A> aList;

    @Id
    @Column( name = "ID" )
    public long getId()
    {
        return id;
    }

    @OneToMany
    @JoinColumn( name = "B_ID" )
    public List<A> getAList()
    {
        return aList;
    }
    public void setId( long id )
    {
        this.id = id;
    }
    public void setAList( List<A> aList )
    {
        this.aList = aList;
    }        
}

A.Java não seria assim:

@Entity
public class A
{
    private long id;
    private long idOfB;

    @Id
    @Column( name = "ID" )
    public long getId()
    {
        return id;
    }
    @Column( name = "B_ID" )
    public long getIdOfB()
    {
        return idOfB;
    }
    public void setId( long id )
    {
        this.id = id;
    }
    public void setIdOfB( long idOfB )
    {
        this.idOfB = idOfB;
    }   
}

Eu recomendo que você associe objetos a objetos para obter vantagens completas do Hibernate. Eu acho que o problema é a exceção que você recebe. Isso ocorre porque a sessão de hibernato já está fechada quando você tenta obter o objeto preguiçoso. Existem várias postagens neste blog que mostram respostas para esse problema, por exemplo, este:Texto do link.

Caso você esteja usando a primavera, você pode usar o OpenEntityManagerInViewFilter para que a sessão se mantenha aberta até que a exibição seja renderizada.

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