2013-04-05 12 views
9

Sono nuovo per l'intera faccenda del JPA quindi ho più domande sul modo migliore di gestire l'unione e la persistenza JPA.Il modo migliore per gestire l'unione JPA?

  1. Ho un oggetto utente che dovrebbe essere aggiornato (alcuni valori come la data e il nome). Devo prima unire l'oggetto passato o è più sicuro trovare il nuovo oggetto?

    Attualmente il mio codice per l'aggiornamento di un utente si presenta così:

    public void updateUserName(User user, String name) { 
        // maybe first merge it? 
        user.setName(name); 
        user.setChangeDate(new Date()); 
        em.merge(user); 
    } 
    

    Come posso essere sicuro che l'utente non è stato manipolato prima che il metodo di aggiornamento si chiama? È più sicuro fare qualcosa del genere:

    public void updateUserName(int userId, String name) { 
        User user = em.getReference(User.class, userId); 
        user.setName(name); 
        user.setChangeDate(new Date()); 
        em.merge(user); 
    } 
    

    Forse altre soluzioni? Ho visto più video e ho visto molti esempi, ma erano tutti diversi e nessuno ha spiegato quale fosse la migliore pratica.

  2. Qual è l'approccio migliore per aggiungere bambini alle relazioni? Ad esempio il mio oggetto utente ha una connessione a più gruppi. Dovrei chiamare il gestore JPA per gli utenti e aggiungere il nuovo gruppo all'elenco di gruppi di utenti o dovrei creare il gruppo in un gestore di gruppi con persistente e aggiungerlo manualmente al mio oggetto utente?

speranza che qualcuno qui ha un indizio;)

+0

Vedi http://stackoverflow.com/questions/1069992/jpa-entitymanager-why-use-persist-over-merge – GKislin

risposta

3

Domanda 1

  • Il metodo merge deve essere chiamato su un distaccato un'entità .
  • Il metodo merge restituirà l'oggetto unito collegato a all'entitàManager.

Che cosa significa?

Un'entità viene rimossa non appena l'entityManager utilizzato per il recupero viene chiuso. (Ad esempio la maggior parte delle volte perché lo si preleva in una transazione precedente).

Nel secondo esempio di codice: l'utente è collegato (perché lo si preleva semplicemente) e quindi l'unione è inutile. (BTW: non è getReference ma find)

Nel tuo primo esempio: non conosciamo lo stato dell'utente (entità distaccata o no?). Se è scollegato, ha senso chiamare merge, ma attenzione che merge non modifichi l'oggetto passato come argomento. Quindi, ecco la mia versione del primo campione:

/** 
* @param user : a detached entity 
* @return : the attached updated entity 
**/ 
public User updateUserName(User user, String name) { 
    user.setName(name); 
    user.setChangeDate(new Date()); 
    return em.merge(user); 
} 

Domanda 2

Forse qualche esempio di codice per spiegare cosa si intende per gestore APP può aiutarci a capire la vostra preoccupazione. Ad ogni modo, cercherò di aiutarti.

Se si dispone di un utente persistente e avete bisogno di creare un nuovo gruppo e associandola con l'utente persistente:

User user = em.find(User.class, userId); 
Group group = new Group(); 
... 
em.persist(group); 
user.addToGroups(group); 
group.addToUsers(user); //JPA won't update the other side of the relationship 
         //so you have to do it by hand OR being aware of that 

Se si dispone di un utente persistente e un gruppo persistente e avete bisogno di associarli :

User user = em.find(User.class, userId); 
Group group = em.find(Group.class, groupId); 
... 
user.addToGroups(group); 
group.addToUsers(user); 

considerazioni generali

La migliore le pratiche relative a tutto ciò dipendono davvero dalla gestione delle transazioni (e quindi del ciclo di vita di entityManager) rispetto al ciclo di vita degli oggetti.

La maggior parte delle volte: un entityManager è un oggetto vivente a tempo veramente breve. D'altra parte i tuoi oggetti di business possono vivere più a lungo e quindi dovrai chiamare merge (e stai attento al fatto che l'unione non modifica l'oggetto passato nell'argomento !!!).

È possibile decidere di recuperare e modificare i propri oggetti di business nella stessa transazione (ovvero con lo stesso entityManager): significa molto più accesso al database e questa strategia deve generalmente essere combinata con una cache di secondo livello per motivi di prestazioni. Ma in questo caso non dovrai chiamare fusione.

Spero che questo aiuto.

+0

Grazie per la risposta. Riguardo alla mia domanda 1, non è il modo più semplice per impostare i miei campi come data e nuovo nome nel mio metodo che chiama il gestore JPA e basta chiamare un metodo "updateUser (utente utente)" per unire semplicemente l'oggetto utente e salvare tutte le modifiche invece di creare metodi per diversi casi di utilizzo degli aggiornamenti? – ManuPanu

6
  1. Dipende da ciò che si desidera ottenere e da quante informazioni si hanno sull'origine dell'oggetto che si sta tentando di unire.

    In primo luogo, se si invoca em.merge(user) nella prima riga del metodo o alla fine non è importante. Se si utilizza JTA e CMT, l'entità verrà aggiornata al termine dell'invocazione del metodo. L'unica differenza è che se si richiama em.merge(user) prima di cambiare l'utente è necessario utilizzare l'istanza restituita al posto del tuo parametro, quindi o è:

    public void updateUserName(User user, String name) { 
        User managedUser = em.merge(user); 
        managedUser.setChangeDate(new Date()); 
        // no need of additional em.merge(-) here. 
        // JTA automatically commits the transaction for this business method. 
    } 
    

    o

    public void updateUserName(User user, String name) { 
        user.setChangeDate(new Date()); 
        em.merge(user); 
        // JTA automatically commits the transaction for this business method. 
    } 
    

    Ora sull'aggiornamento entità.
    Se si desidera solo aggiornare alcuni campi ben definiti nella propria entità, utilizzare il secondo approccio in quanto è più sicuro. Non puoi essere sicuro che un client del tuo metodo non abbia modificato altri campi della tua entità. Pertanto, em.merge(-) aggiornerà anche quelli che potrebbero non essere ciò che si desidera ottenere.

    D'altra parte - se si desidera accettare tutte le modifiche apportate dall'utente e basta sovrascrivere/aggiungere alcune proprietà come changeDate nel tuo esempio, il primo approccio è anche bene (merge intera entità passato al metodo di business.) E ' dipende davvero dal tuo caso d'uso.

  2. Suppongo che dipenda dalle impostazioni a cascata. Se si desidera mantenere/unire automaticamente tutto ogni volta che l'entità User viene modificata, è sicuro aggiungerla alla raccolta dell'Utente (qualcosa come User#addGroup(Group g) { groups.add(g)}. Se non si desidera il collegamento in cascata, è sempre possibile creare i propri metodi che si propagheranno dall'altra parte della relazione. Potrebbe essere qualcosa di simile: User#addGroup(Group g) che invoca automaticamente g.addUser(this);.

Problemi correlati