Sono abbastanza sicuro che finalizzare sia ancora una brutta notizia su JVMS successiva: c'è un'alternativa?

StackOverflow https://stackoverflow.com/questions/5359367

  •  27-10-2019
  •  | 
  •  

Domanda

Vorrei implementare un sistema in stile ORM in grado di salvare gli aggiornamenti a Pojos quando non sono più raggiungibili dal chiamante.

Pensavo che le classi di riferimento potessero farlo, ma sembrano solo accusare il riferimento dopo che l'oggetto è stato cancellato (speravo che fosse quando sono stati in grado di essere raccolti), quindi una volta che hanno accusato il metodo .get () tornerà sempre nullo.

Potrei usare un finalizer, ma l'ultima volta che ho controllato quelli erano discutibili (non garantiti per funzionare prontamente o correre affatto)-credo che una combinazione di finalizzatori e runshutdownhook () funzionerebbe, ma questo si sta entrando in un territorio abbastanza paludoso.

C'è un altro percorso che non sto pensando oltre all'obbligo "Basta avere la chiamata chiamante .Save () quando ha finito"?

È stato utile?

Soluzione

Stai solo cercando di evitare di dover chiamare save() Su ogni pojo che modifichi?

Questo può essere fatto in modo affidabile usando un oggetto di sessione di persistenza, come questo:

  1. Apri un nuovo oggetto di sessione.
  2. Carica gli oggetti tramite l'oggetto sessione. L'oggetto sessione mantiene i riferimenti a tutti gli oggetti che carica.
  3. Apportare eventuali modifiche agli oggetti caricati. Non è necessario chiamare un metodo di salvataggio su oggetti aggiornati.
  4. Chiudi l'oggetto sessione. La sessione salva tutti i suoi oggetti. Potrebbe anche essere abbastanza elegante da conservare una copia dei dati carichi puliti, confrontare tutti i suoi oggetti con i dati puliti e salvare solo quelli che sono stati modificati.

E se non si desidera passare gli oggetti di sessione tramite il codice, puoi fare un passo avanti con il modello di lavoro, associando un oggetto di sessione al thread corrente:

  1. Avvia un'unità di lavoro. Questo crea un oggetto di sessione dietro le quinte e lo associa al thread corrente.
  2. Caricare oggetti. Ogni volta che viene caricato un oggetto, l'ORM lo associa automaticamente a un oggetto di sessione in base al thread corrente.
  3. Apportare eventuali modifiche agli oggetti caricati. Non è necessario chiamare un metodo di salvataggio su oggetti aggiornati.
  4. Completa l'unità di lavoro. Questo chiude l'oggetto sessione, salvando tutti gli oggetti.

Ciò risolve diversi problemi con una soluzione basata sulla raggiungibilità:

  • Non ti affidi a raccolte di immondizia non deterministiche, che potrebbero avere un lungo periodo tra le corse o non funzionare affatto.
  • Tutti gli oggetti modificati in un'operazione vengono salvati insieme. Se si fa affidamento sulla raggiungibilità, diversi oggetti modificati nella stessa operazione possono diventare irraggiungibili in momenti diversi, il che significa che le modifiche possono essere salvate nel database in bit e pezzi.
  • Il rollback è molto più semplice: basta dare all'oggetto sessione un metodo rollback (). Con una soluzione di raggiungibilità, dovresti ricordare di chiamare il rollback () su ogni pojo modificato se un'operazione fallisce, il che è davvero la stessa del tuo problema originale.

Forse vedi http://nhibernate.info/doc/patternsandpracts/nhibernata-and-the-unit-of-work-pattern.html o ricercare l'unità del modello di lavoro ed emulare alcune di queste idee.

Altri suggerimenti

Usa il modello Observer Costruisci un ClearCanceManager e alcuni Distruggibles. Idestroyable è un'interfaccia, che viene utilizzata per gli osservatori che contiene il metodo public void Destroy () Il clearanceManager è oggetto di ObserverPattern. Forse usa Singleton qui per assicurarti di avere un solo oggetto ClearCeManager nella tua applicazione.

Utilizzare un set internaly all'interno del ClearCeNanager (non un elenco per garantire che gli oggetti possano essere aggiunti solo una volta)

Supportare un metodo AddDestroyable (Idestroyable Destoryble) (e forse uno rimosso).

Durante il runtime le lezioni per le quali hai bisogno di un po 'di emulazione distruttore, possono registrarle se stessi al ClearenceManager. ClearenceManager.getInstance (). AddDestroyable (this);

Il ClearCeManager ha un metodo Doclearance (), che dovrebbe essere chiamato alla fine del metodo principale. Iterato ha lanciato il set privato e chiama Destroy () su ogni oggetto Idestroyable.

In questo modo puoi emulare i distruttori, senza usarli, perché usando i distruttori stai perdendo il controllo sull'esistenza dell'oggetto necessario Myabe. Non si sa quando la sovrascrittura finalizza, quando viene chiamata.

Forse, se non vuoi chiamare Doclearance () nel tuo metodo principale che puoi usare qui, ma solo qui, un vero distruttore finalizzato (). Poiché ci sono riferimenti nel ClearenceManager agli oggetti necessari, non saranno distrutti per primi. Ma forse MHH, se ci sono riferimenti incrociati ... meglio non usare finalizza, usa doclearance () e divertiti :)

Penso che tu stia abbaiando l'albero sbagliato qui.

Tutti i meccanismi di finalizzatore e di riferimento di Java basati sulla raggiungibilità dipendono dal collettore della spazzatura per determinare se i rispettivi oggetti sono raggiungibili. Quindi, se usi uno qualsiasi dei meccanismi di riferimento per una sorta di finalizzazione, ti imbatti negli stessi problemi che fanno finalize una cattiva idea.

È tecnicamente possibile implementare i propri meccanismi per realizzare la raggiungibilità; Ad esempio implementando il proprio conteggio di riferimento specifico dell'applicazione. Tuttavia, è probabile che sia costoso, fragile e rende il tuo codice orribile. (Il conteggio dei riferimenti in Java è probabilmente più disordinato e più fragile rispetto a C ++, perché non è possibile sovraccaricare gli operatori di assegnazione di riferimento per garantire che i conteggi di riferimento siano regolati in modo trasparente. Quindi ogni assegnazione di riferimento deve essere avvolta in una chiamata del metodo.) Direi che fare la tua analisi di raggiungibilità è un cattiva idea.

Quindi, per essere pratico devi:

  • ripensare il tuo design in modo da non fare cose in base alla raggiungibilità o
  • vivere con le conseguenze dell'uso di finalize.

La prima opzione è chiaramente la migliore, IMO.

Forse puoi sottoclasse Fantomreference e archiviare i dati necessari per le azioni finali.

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