2012-11-27 5 views
19

Presento la domanda con un esempio.Spring Data JPA - Perché le modifiche a un'entità restituita vengono automaticamente mantenute?

affermare che abbiamo un repository, come il qui sotto:

public interface ExampleObjectRepository extends CrudRepository<ExampleObject, Long> { 

} 

Estendendo l'interfaccia JpaRepository, il repository ExampleObject eredita il seguente metodo:

T findOne(ID id); 

Ora, ho osservato che, se ricevo un riferimento a un ExampleObject dopo una chiamata a questo metodo, qualsiasi modifica apportata a questo metodo viene salvata automaticamente nel database, ad esempio:

ExampleObject pointInCase = exampleObjectRepository.findOne(1L); 
pointInCase.setName("Something else"); 

Lettura intorno all'oggetto, ho capito questo questo signf che l'istanza ExampleObject è not detached.

Questo va contro le mie aspettative. Mi sarei aspettato che avrei bisogno di usare il metodo save ereditato da CrudRepository al fine di salvare le modifiche:

T save(T entity); 

qualcuno dovrebbe essere così gentile da confermare che gli oggetti restituiti da una sorgente dati JPA Repository rimangono attaccati come standard e spiega come utilizzare l'API per contrassegnare un metodo nel repository in modo tale che restituisca solo riferimenti distaccati?

Immagino che la modifica dello stato dell'entità possa anche cambiare la sua definizione quando viene utilizzata con il metodo save(T entity), quindi mi piacerebbe anche capire come viene gestita l'identità per gli aggiornamenti.

risposta

14

Questo è un principio fondamentale dell'APP. Lavorate con entità allegate (gestite) e ogni modifica apportata su queste entità gestite viene automaticamente resa persistente.

Se non si desidera che le modifiche siano persistenti, non apportare modifiche o eseguire il rollback della transazione.

Lavorare su entità distaccate sarebbe un incubo, perché impedirebbe il pigro caricamento di tutte le associazioni. Puoi sempre chiamare EntityManager.detach() sulle tue entità, ma davvero non lo farei. Basta provare a capire come funziona e ad affrontarlo. Ci sono molti più vantaggi che svantaggi. Uno di questi è che non devi neanche pensare di salvare tutte le modifiche che una logica di business complessa potrebbe fare, dato che è tutto fatto per te da JPA, in modo trasparente.

+0

Grazie per i vostri commenti - sono sicuramente coerenti con le altre opinioni in tutto l'ufficio!Tuttavia, nel caso in cui diverse manipolazioni POJO vengano eseguite come parte di una transazione, questo comportamento interromperebbe la natura transazionale del metodo? – 8bitjunkie

+1

Perché dovrebbe? Avvia una transazione, apporta un numero qualsiasi di modifiche a qualsiasi numero e tipo di entità che desideri, quindi effettua il commit della transazione. O tutte le modifiche vengono confermate o tutte le modifiche sono ripristinate. L'aspetto transazionale di un metodo si applica anche a ogni metodo interno che chiama: il contesto della transazione viene propagato. –

+0

quindi ... il metodo di chiamata 'save' non è necessario se non lo si scollega? O dovrei chiamare qualche altro metodo solo per assicurarmi che JPA chiuda la transazione invece del rollback? – kiedysktos

5

È possibile fare in modo che il repository restituisca le entità distaccate se la Transazione è applicata al repository. Cioè la transazione inizia con l'ingresso nel repository e si chiude quando il codice esce dal repository.

Se si lavora in questo modo è necessario assicurarsi che tutti i dati necessari vengano caricati in una volta sola, altrimenti si ottengono eccezioni di inizializzazione pigre. Ma in molte circostanze lo considero desiderabile perché ti dà un po 'di controllo quando e quali dati vengono caricati, che altrimenti scivolano facilmente tra le dita quando si usa JPA.

Per le modifiche, utilizzo un diverso ambito di Transaction che avvolge l'intero processo di caricamento, modifica (e implicitamente persistente).

Problemi correlati