2014-11-07 11 views
12

Sto usando lo spring boot e lo hibernate su jpa. Sto usando l'interfaccia JpaRepository per implementare i miei repository. Come con i seguenti UserRepositorySpring JpaRepository - Stacca e collega l'entità

public interface UserRepository extends JpaRepository<User, Long> { 
} 

che voglio raggiungere seguente

  1. carico un'entità utente.
  2. Modificare lo stato dell'oggetto entità ad es. user.setName ("foo")
  3. Effettua una chiamata al servizio web di sistema esterno. Salva il risultato della chiamata in DB
  4. Solo in caso di risposta positiva di questa chiamata al servizio web, salvare il nuovo stato dell'utente nel repository.

Tutti i passaggi sopra descritti non si verificano in una transazione, ovvero la chiamata di servizio esterna è fuori servizio.

Quando si salva il risultato del servizio web in DB tramite il repository, vengono salvate anche le modifiche in Entità utente. Secondo la mia comprensione, ciò è dovuto al flusso del contesto di persistenza di underlaying al punto 3. Dopo alcuni google, penso di poter raggiungere il mio scopo, se riesco a staccare la mia entità utente al punto uno e ricollegarlo al punto 4. Per favore confermare se la mia comprensione è corretta e come posso ottenere questo? Non c'è un metodo nell'interfaccia JpaRepository per staccare un'entità.

seguito è riportato il codice per illustrare

public void updateUser(int id, String name, int changeReqId){ 
    User mUser = userRepository.findOne(id); //1 
    mUser.setName(name); //2 

    ChangeRequest cr = changeRequestRepository.findOne(changeReqId); 
    ChangeResponse rs = userWebService.updateDetails(mUser); //3 

    if(rs.isAccepted()){ 
     userRepository.saveAndFlush(mUser); //4 
    } 

    cr.setResponseCode(rs.getCode()); 
    changeRequestRepository.saveAndFlush(cr); //this call also saves the changes at step 2 
} 

Grazie

+1

È necessario inserire il codice corrente per i passaggi da 1 a 4 (per chiarire) –

+0

Sarebbe possibile effettuare chiamate nel seguente ordine: 1,3,4,2? – BlueLettuce16

risposta

28

Se si utilizza JPA 2.0, è possibile utilizzare EntityManager#detach() per separare una singola entità dal contesto di persistenza. Inoltre, Hibernate ha uno Session#evict() che serve allo stesso scopo.

Dal JpaRepository non fornisce questa funzionalità per sé, è possibile add a custom implementation ad esso, qualcosa di simile

public interface UserRepositoryCustom { 
    ... 
    void detachUser(User u); 
    ... 
} 

public interface UserRepository extends JpaRepository<User, Long>, UserRepositoryCustom { 
    ... 
} 

@Repository 
public class UserRepositoryCustomImpl implements UserRepositoryCustom { 
    ... 
    @PersistenceContext 
    private EntityManager entityManager; 

    @Override 
    public void detachUser(User u) { 
     entityManager.detach(u); 
    } 
    ... 
} 

Non ho provato questo codice, ma si dovrebbe essere in grado di farlo funzionare. Potresti anche provare a mettere in attesa il EntityManager nella tua classe di servizio (dove updateUser() è) con @PersistenceContext ed evitare il trambusto di aggiungere un'implementazione personalizzata al repository.

+0

Grazie, questo approccio ha funzionato nella mia app Spring Boot. (Ci siamo presi la libertà di aggiungere '@ Repository' all'implementazione nel tuo codice di esempio, altrimenti il ​​repository personalizzato non può essere autowired.) – Jonik

+3

Non funziona per me con la primavera 4. –

+0

Lo stesso approccio può essere usato per CrudRepository? – DBS

3

entityManager.clear() disconnetterà tutti gli oggetti JPA, in modo che potrebbe non essere una soluzione adeguata in tutti i casi, se si dispone di altri oggetti che si fanno piano per rimanere connesso.

chiaro

/** 
* Clear the persistence context, causing all managed 
* entities to become detached. Changes made to entities that 
* have not been flushed to the database will not be 
* persisted. 
*/ 
public void clear(); 

entityManager.detach(entity); Rimuovere l'entità proposta dal contesto di persistenza

staccare

/** 
* Remove the given entity from the persistence context, causing 
* a managed entity to become detached. Unflushed changes made 
* to the entity if any (including removal of the entity), 
* will not be synchronized to the database. Entities which 
* previously referenced the detached entity will continue to 
* reference it. 
* @param entity entity instance 
* @throws IllegalArgumentException if the instance is not an 
*   entity 
* @since Java Persistence 2.0 
*/ 
public void detach(Object entity); 
Problemi correlati