2013-01-03 5 views
15

La mia domanda è questa: C'è mai un ruolo per JPA merge in un'applicazione Web stateless?JPA si fonde in un'applicazione web RESTful con DTO e blocco ottimistico?

C'è un sacco di discussioni su SO sul funzionamento merge in JPA. C'è anche un great article on the subject che contrappone l'unione JPA tramite un processo Do-It-Yourself più manuale (dove trovi l'entità tramite il gestore di entità e apporti le modifiche).

La mia applicazione dispone di un modello di dominio ricco (ala-driven design) che utilizza l'annotazione @Version per utilizzare il blocco ottimistico. Abbiamo anche creato DTO per l'invio su cavo come parte dei nostri servizi web RESTful. La creazione di questo livello DTO ci consente anche di inviare al client tutto ciò di cui ha bisogno e nulla lo fa.

Finora, ho capito che questa è un'architettura abbastanza tipica. La mia domanda riguarda i metodi di servizio che necessitano di AGGIORNARE gli oggetti esistenti (ad es. HTTP PUT). In questo caso abbiamo questi due approcci 1) JPA Merge e 2) DIY.

Quello che non capisco è come l'unione JPA possa essere considerata un'opzione per la gestione degli aggiornamenti. Ecco il mio pensiero e mi chiedo se c'è qualcosa che non capisco:

1) Per creare correttamente un'entità JPA separata da un DTO filo, il numero di versione deve essere impostato correttamente ... else un OptimisticLockException viene lanciato Ma la specifica JPA dice:

Un'entità può accedere allo stato del suo campo versione o proprietà o esportare un metodo per l'utilizzo con l'applicazione per accedere alla versione, ma non deve modificare il valore di versione [30] . Solo il provider di persistenza è autorizzato a impostare o aggiornare il valore dell'attributo di versione nell'oggetto .

2) Unisci non gestisce le relazioni bidirezionali ... i campi di puntamento all'indietro sempre finiscono come null.

3) Se dal DTO mancano campi o dati (a causa di un aggiornamento parziale), l'unione JPA eliminerà tali relazioni o cancellerà tali campi. Hibernate può gestire gli aggiornamenti parziali, ma non l'unione JPA. Fai da te in grado di gestire gli aggiornamenti parziali.

4) La prima cosa che farà il metodo di unione è interrogare il database per l'ID entità, quindi non ci sono benefici sulle prestazioni rispetto a DIY.

5) In un aggiornamento DYI, si carica il soggetto e apportare le modifiche secondo la DTO - non ci sono chiamate a merge o persist per questo perché il contesto dell'APP implementa il modello di unità di lavoro fuori della scatola.

Ho diritto?

Edit:

6) Unire il comportamento per quanto riguarda le relazioni caricati pigri possono differ amongst providers.

risposta

13

L'utilizzo di Unisci richiede di inviare e ricevere una rappresentazione completa dell'entità o di mantenere lo stato lato server. Per operazioni di tipo CRUD-y banali, è facile e conveniente. L'ho usato in abbondanza in applicazioni web stateless in cui non vi è alcun rischio significativo per la sicurezza che consente al cliente di vedere l'intera entità.

Tuttavia, se hai già ridotto le operazioni al solo passaggio delle informazioni immediatamente rilevanti, devi anche scrivere manualmente i servizi corrispondenti.

Ricorda che quando esegui il tuo aggiornamento "fai da te" devi ancora passare un numero di versione sul DTO e confrontarlo manualmente con quello che esce dal database. Altrimenti non si ottiene il blocco ottimistico che si estende al 'tempo di pensare dell'utente' che si avrebbe se si stesse utilizzando l'approccio più semplice con l'unione.

  1. Non è possibile modificare la versione su un'entità creata dal fornitore, ma quando hai fatto la propria istanza della classe di entità con la parola chiave new è bene e dovrebbe impostare la versione su di esso.

  2. Fa in modo che la rappresentazione persistente corrisponda alla rappresentazione in memoria fornita, ciò può includere rendere le cose nulle. Ricorda quando un oggetto viene unito quell'oggetto dovrebbe essere scartato e sostituito con quello restituito da unire. Non si suppone che unisca un oggetto e quindi continui a utilizzarlo. Il suo stato non è definito dalla specifica.

  3. Vero.

  4. Molto probabilmente, purché la soluzione DIY utilizzi anche l'ID entità e non una query arbitraria. (Ci sono altri vantaggi nell'usare il metodo "trova" su una query.)

  5. Vero.

4

Vorrei aggiungere:

7) di unione si traduce per inserire o aggiornare a seconda della esistenza del record su DB, quindi non si tratta correttamente con update-vs-eliminare la concorrenza ottimistica. Cioè, se un altro utente elimina contemporaneamente il record e lo aggiorna, deve (1) lanciare un'eccezione di concorrenza ... ma non lo fa, semplicemente inserisce il record come nuovo.

(1) Almeno, nella maggior parte dei casi, a mio parere, dovrebbe. Posso immaginare alcuni casi in cui vorrei che questo caso d'uso attivasse un nuovo inserto, ma sono lontani dal solito. Almeno, vorrei che lo sviluppatore ci pensasse due volte, non solo accettare "merge() == updateWithConcurrencyControl()", perché non lo è.