2012-08-09 20 views
83

Beh, la domanda dice praticamente tutto. Usando JPARepository come posso aggiornare un'entità?Come aggiornare un'entità utilizzando spring-data-jpa?

JPARepository ha solo un metodo risparmi, che non mi dice se è effettivamente creato o aggiornato. Ad esempio, inserisco un semplice oggetto per l'utente del database, che ha tre campi: nome e cognome e età:

@Entity 
public class User { 

    private String firstname; 
    private String lastname; 
     //Setters and getters for age omitted, but they are the same as with firstname and lastname. 
     private int age; 

    @Column 
    public String getFirstname() { 
    return firstname; 
    } 
    public void setFirstname(String firstname) { 
    this.firstname = firstname; 
    } 

    @Column 
    public String getLastname() { 
    return lastname; 
    } 
    public void setLastname(String lastname) { 
    this.lastname = lastname; 
    } 

    private long userId; 

    @Id 
    @GeneratedValue(strategy=GenerationType.AUTO) 
    public long getUserId(){ 
    return this.userId; 
    } 

    public void setUserId(long userId){ 
    this.userId = userId; 
    } 
} 

Poi ho semplicemente "Save", che a questo punto è un inserto in realtà:

User user1 = new User(); 
user1.setFirstname("john"); user1.setLastname("dew"); 
user1.setAge(16); 

userService.saveUser(user1);// This call is actually using the JPARepository: userRepository.save(user); 

Ok tutto va bene. Ora voglio aggiornare questo utente, diciamo cambia la sua età. Bene, potrei usare una Query per QueryDSL o NamedQuery, qualunque sia. Ma, considerando che voglio solo usare spring-data-jpa e il JPARepository, come faccio a dire che invece di un inserto voglio fare un aggiornamento?

In particolare, come faccio a dire a spring-data-jpa che gli utenti che hanno lo stesso nome utente e lo stesso nome sono in realtà EQUAL e che è necessario aggiornare l'entità. L'override degli uguoli non ha funzionato.

Grazie!

+1

Sei sicuro l'ID viene riscritto quando si salva un oggetto esistente nel database ?? Mai avuto questo sul mio progetto tbh –

+0

@ByronVoorbach hai ragione hai appena provato questo. aggiorna anche la domanda, thx – Eugene

+1

Ciao amico, puoi guardare questo link http://stackoverflow.com/questions/24420572/update-or-saveorupdate-in-crudrespository-is-there-any-options-available puoi essere un approccio come saveOrUpdate() – ibrahimKiraz

risposta

107

L'identità delle entità è definita dalle loro chiavi primarie. Poiché firstname e lastname non sono parti della chiave primaria, non è possibile indicare a JPA il trattamento di User s con gli stessi se lastname s se uguale a userId s.

Quindi, se si desidera aggiornare un User identificato dal suo firstname e lastname, è necessario trovare che User da una query, e quindi modificare campi appropriati dell'oggetto tuo trovato. Queste modifiche verranno automaticamente scaricate nel database al termine della transazione, in modo che non sia necessario fare nulla per salvare queste modifiche in modo esplicito.

EDIT:

forse sarebbe meglio approfondire la semantica complessivi di JPA. Ci sono due approcci principali per la progettazione di API di persistenza:

  • inserto approccio/update. Quando è necessario modificare il database, è necessario chiamare esplicitamente i metodi dell'API di persistenza: si chiama insert per inserire un oggetto oppure update per salvare il nuovo stato dell'oggetto nel database.

  • Approccio unità di lavoro. In questo caso hai una serie di oggetti gestiti da dalla libreria di persistenza. Tutte le modifiche apportate a questi oggetti verranno automaticamente scaricate nel database al termine dell'unità di lavoro (ad esempio alla fine della transazione corrente, nel caso tipico). Quando è necessario inserire un nuovo record nel database, si rende l'oggetto corrispondente gestito. Gli oggetti gestiti sono identificati dalle loro chiavi primarie, in modo che se si crea un oggetto con la chiave primaria predefinita gestito, esso sarà associato al record del database dello stesso id e lo stato di questo oggetto verrà propagato a tale record automaticamente.

JPA segue l'approccio successivo. save() in Spring Data JPA è supportato da merge() in JPA semplice, quindi rende l'entità gestita come descritto sopra. Significa che chiamare save() su un oggetto con ID predefinito aggiornerà il record del database corrispondente piuttosto che inserirne uno nuovo, e spiega anche perché save() non è chiamato create().

+0

beh penso che lo so. Mi riferivo strettamente a spring-data-jpa. Ho due problemi con questa risposta ora: 1) i valori aziendali non dovrebbero far parte della chiave primaria - è una cosa nota, giusto? Quindi avere il nome e il cognome come chiave primaria non va bene. E 2) Perché questo metodo non è chiamato creare, ma salvare invece in spring-data-jpa? – Eugene

+0

@Eugene: aggiornato. – axtavt

+0

"save() in Spring Data JPA è supportato da merge() in plain JPA" hai effettivamente guardato il codice? L'ho appena fatto e sia il backup sia persistere o fondere. Continuerà o si aggiornerà in base alla presenza dell'ID (chiave primaria). Questo, penso, dovrebbe essere documentato nel metodo di salvataggio. Quindi salvare è in realtà unire o persistere. – Eugene

52

Poiché la risposta di @axtavt concentra non JPAspring-data-jpa

Per aggiornare un'entità interrogando salvando non è efficiente poiché richiede due query ed eventualmente l'interrogazione può essere molto costoso in quanto può unirsi altre tabelle e caricare eventuali raccolte che hanno fetchType=FetchType.EAGER

Spring-data-jpa supporta l'operazione di aggiornamento.
È necessario definire il metodo nell'interfaccia del repository e annotarlo con @Query e @Modifying.

@Modifying 
@Query("update User u set u.firstname = ?1, u.lastname = ?2 where u.id = ?3") 
void setUserInfoById(String firstname, String lastname, Integer userId); 

@Query è per la definizione query personalizzata e @Modifying è per dire spring-data-jpa che questa query è un'operazione di aggiornamento e richiede executeUpdate() non executeQuery().

+0

hey non funziona! – bks4line

+2

Assicurati di eseguirlo nella transazione – hussachai

+1

Hey! Grazie sto usando i bean di dati primaverili. Quindi si prenderà automaticamente cura del mio aggiornamento. S salva (S entità); si occupa automaticamente dell'aggiornamento. non ho dovuto usare il tuo metodo! Grazie comunque! – bks4line

4

Utilizzo di spring-data-jpa save(), Avevo lo stesso problema di @DtechNet. Voglio dire che ogni save() stava creando un nuovo oggetto invece di un aggiornamento. Per risolvere questo problema ho dovuto aggiungere la "versione" archiviata all'entità e alla tabella correlata.

1

Ecco come ho risolto il problema:

User inbound = ... 
User existing = userRepository.findByFirstname(inbound.getFirstname()); 
if(existing != null) inbound.setId(existing.getId()); 
userRepository.save(inbound); 
Problemi correlati