Domanda

Ho un problema con caricamento pigro in ibernazione quando si tratta di eredità. Ho un ente che fa riferimento a una seconda entità che è una sottoclasse. Voglio il riferimento per caricare pigramente, ma questo causa errori nei miei .equals) Metodi (.

Nel codice qui sotto, se si chiama equals () su un'istanza di A, il controllo ha esito negativo nelle C.equals () quando la verifica se l'oggetto o è un esempio di C. Si fallisce perché l'altro oggetto è in realtà un proxy Sospensione creato da javassist, che si estende B, non C.

capisco che Hibernate non può creare un proxy di tipo C senza andare al database e rompendo così il lazy loading. C'è un modo per rendere la funzione getB () in classe A restituire l'istanza concreta B al posto del proxy (pigramente)? Ho provato con la specifica @LazyToOne Hibernate (LazyToOneOption.NO_PROXY) annotazioni sul metodo getB () senza alcun risultato.

@Entity @Table(name="a")
public class A {
    private B b;

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="b")
    public B getB() {
        return this.b;
    }

    public boolean equals(final Object o) {
        if (o == null) {
            return false;
        }

        if (!(o instanceof A)) {
            return false;
        }
        final A other = (A) o;
        return this.getB().equals(o.getB());
    }
}

@Entity @Table(name="b")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
    name="type",
    discriminatorType=DiscriminatorType.STRING
)
public abstract class B {
   private long id;

   public boolean equals(final Object obj) {
       if (this == obj) {
           return true;
       }
       if (obj == null) {
           return false;
       }
       if (!(obj instanceof B)) {
           return false;
       }
       final B b = (B) o;
       return this.getId().equals(b.getId());
    }
}

@Entity @DiscriminatorValue("c")
public class C extends B {
   private String s;

   public boolean equals(Object obj) {
       if (this == obj) {
           return true;
       }
       if (!super.equals(obj)) {
           return false;
       }
       if (obj == null) {
           return false;
       }
       if (!super.equals(obj)) {
           return false;
       }
       if (!(obj instanceof C)) {
           return false;
       }
       final C other = (C) o;
       if (this.getS() == null) {
           if (other.getS() != null) {
               return false;
           }
       } else if (!this.getS().equals(other.getS())) {
           return false;
       }
       return true;
    }
}

@Entity @DiscriminatorValue("d")
public class D extends B {
    // Other implementation of B
}
È stato utile?

Soluzione

Si scopre che ero sul monitoraggio destra cercando di usare l'annotazione @LazyToOne (LazyToOneOption.NO_PROXY). Non stava lavorando per me, fuori dalla scatola, perché non avevo ancora eseguire lo strumento bytecode enhancer Hibernate su di esso. Le istruzioni per questo possono essere trovati qui:

19.1.7. Utilizzando proprietà pigro recupero

Altri suggerimenti

Si potrebbe desiderare di provare a cambiare la proprietà fetch su get () per FetchType.EAGER. Spero che questo aiuti.

Indipendentemente dal fatto che gli oggetti sono entità e / o pigri-caricato, è praticamente impossibile rispettare il contratto tra pari e di avere una specializzazione di eguali in una sottoclasse che utilizza instanceof. In effetti, si dovrebbe quindi essere in una situazione in cui si avrebbe b1.equals(c1) == true, ma c1.equals(b1) == false.

Quindi, penso che la superclasse (B) dovrebbe definire eguali, e renderla definitiva, perché tutte le sottoclassi dovrebbero utilizzare il metodo della classe base equals.

Detto questo, il vostro metodo equals in B non è giusto:

if (!super.equals(obj)) {
   return false;
}

Ciò significa che l'attuazione oggetto di eguali deve restituire true per avere due istanze B uguali. Il che significa che due istanze B sono uguali solo se sono lo stesso oggetto.

if (!(obj instanceof C)) {
    return false;
}

Perché il controllo di classe B che l'altra istanza è un'istanza di C. Si deve verificare se l'altra istanza è un'istanza di B.

Dal momento che, alla fine, due B sono uguali se hanno lo stesso ID, e dal momento che gli ID devono essere univoci per tutto l'albero di ereditarietà, sei al sicuro se si effettua questo metodo equals finale.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top