Domanda

Esiste un modo per utilizzare gli oggetti Flyweight con il mapping di persistenza in letargo? Il mio modello di dati contiene molti oggetti che saranno gli stessi. Invece di avere un'istanza separata per ciascuno di quegli stessi oggetti, mi piacerebbe usare il modello Flyweight Design Pattern e fare riferimento sempre allo stesso oggetto fisico. Come raggiungere questo obiettivo in letargo?

Btw. tutte le JVM ottimizzano l'utilizzo delle stringhe in modo tale che quando la stessa stringa viene utilizzata più volte, sarà sempre la stessa istanza fisica?

È stato utile?

Soluzione

Dipende.

Per valori in sola lettura puoi facilmente implementare un modello flyweight creando un UserType personalizzato che restituirà ogni volta oggetti da un pool anziché nuove istanze.

Per le entità Hibernate è per impostazione predefinita sana e vuole essere coerente tra le transazioni e quindi non condividerà le entità tra le sessioni per evitare le condizioni di gara dei dati - e non penso che sia quello che vuoi.

Ma nel caso sia (e questo è totalmente sconsigliato senza sapere davvero cosa stai facendo) puoi implementare Interceptor.getEntity () che è destinato alla memorizzazione nella cache di secondo livello. In questo metodo puoi restituire un'entità (anche alcune condivise da altre sessioni) e avrai effettivamente un modello flyweight per le tue entità.

MA sconsiglio vivamente questo per la coerenza dei tuoi dati - molto meglio avere valori di peso volatile immutabili a cui fanno riferimento le entità piuttosto che provare a pesare le entità reali.

Altri suggerimenti

Sì, è possibile implementare il modello Flyweight con Hibernate.

Il modello flyweight è un modo per ridurre al minimo l'utilizzo della memoria per istanza . La strategia è quella di condividere quanto più stato possibile tra le istanze dei pesi mosca. Nel tuo caso lo stato condivisibile è tutto tranne l'identificatore di oggetto ibernato e qualche stato aggiuntivo per mantenere l'identità dell'oggetto .

Ogni istanza di peso mosca necessita della propria identità oggetto . Lo stato aggiuntivo è il modo di implementare l'identità per distinguere tra oggetti che condividono lo stato comune.

public boolean equals(Object obj){
  Fly other; [..]//check type
  //null checks ommitted
  return other.myState.equals(myState) && other.commonState.equals(commonState); 
}

Se l'identità dell'oggetto è condivisa tra istanze ibernate interpreterebbe tutte le istanze fisiche (riferimenti) come la stessa istanza. Hibernate utilizza il metodo equals per verificare l'identità dell'oggetto e l'implementazione uguale dovrebbe restituire (! A.equals (a) == true) che è illegale. Uguale deve essere riflessivo. Se infrangi questo contratto, tutte le biblioteche che dipendono dal contratto verranno infrante (collezioni, letargo, ecc.).

Non è possibile implementare il metodo uguale utilizzando l'identificatore di oggetto ibernazione per distinguere tra oggetti. Ciò renderebbe l'identità dell'oggetto dipendente dallo stato di persistenza (persistente o transitorio).

Un modo per modellare lo stato comune in ibernazione è un'associazione uno-a-molti tra oggetti a stati condivisi e oggetti flyweight. (Forse qualcuno ha un'idea su come mappare i dati senza unire due tabelle?)

Stringa: solo stringhe interiorizzate saranno condivise. Questa non è la soluzione migliore per la maggior parte del tempo. È appropriato per i simboli (nome della classe, nome del metodo, ecc.). Le stringhe interiorizzate non verranno mai raccolte per garbage e devi avere un'istanza String che dovrà essere comunque garbage collection new String (" .. "). Intern () . Non salverà le allocazioni. C'è solo il piccolo vantaggio che la stringa di base non sopravviverà a una generazione gc o potrebbe essere allocata nello stack (con analisi di escape in hot spot abilitata e applicabile).

  

tutte le JVM ottimizzano l'utilizzo delle stringhe in modo tale che quando la stessa stringa viene utilizzata più volte, sarà sempre la stessa istanza fisica?

Ne dubito moltissimo. Nello stesso file di classe, quando definito come:

String s1 = "Yes";
String s2 = "Yes";

probabilmente avrai s1 == s1.

Ma se ti piace:

String x = loadTextFromFile(); // file contains es
StringBuilder b = new StringBuilder();
s2 = b.append("Y").append(x).toString(); // s2 = "Yes"

Non credo che il runtime controllerà e confronterà tutte le stringhe caricate il valore di ritorno del loro costruttore.

Quindi, confronta sempre gli oggetti con equals (). È comunque un buon consiglio dato che ogni bene uguale inizia con:

if (this == o) {
    return true;
}

Se i tuoi oggetti implementano l'uguaglianza per identità, Hibernate avrà solo la singola istanza associata a quella chiave primaria. Non credo sia esattamente la stessa idea di Flyweight, ma il punto è che non avrai molte istanze dello stesso oggetto Hibernate.

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