it-swarm.com.de

Wie lässt sich eine JPA-Entität in Spring Data schön aktualisieren?

Ich habe mir also verschiedene Tutorials zu JPA mit Spring Data angesehen und dies wurde bei vielen Gelegenheiten unterschiedlich gemacht, und ich bin mir nicht ganz sicher, was der richtige Ansatz ist.

Angenommen, es gibt die folgende Entität:

package stackoverflowTest.dao;

import javax.persistence.*;

@Entity
@Table(name = "customers")
public class Customer {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private long id;

@Column(name = "name")
private String name;

public Customer(String name) {
    this.name = name;
}

public Customer() {
}

public long getId() {
    return id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}
}

Wir haben auch ein DTO, das in der Service-Schicht abgerufen und an die Controller-/Client-Seite übergeben wird.

package stackoverflowTest.dto;

public class CustomerDto {

private long id;
private String name;

public CustomerDto(long id, String name) {
    this.id = id;
    this.name = name;
}

public long getId() {
    return id;
}

public void setId(long id) {
    this.id = id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}
}

Nehmen wir also an, der Kunde möchte seinen Namen im Webui ändern - dann wird es eine Controller-Aktion geben, bei der die aktualisierte DTO mit der alten ID und dem neuen Namen angezeigt wird.

Jetzt muss ich dieses aktualisierte DTO in der Datenbank speichern.

Leider gibt es derzeit keine Möglichkeit, einen vorhandenen Kunden zu aktualisieren (außer das Löschen des Eintrags in der Datenbank und das Erstellen eines neuen Kunden mit einer neuen automatisch generierten ID).

Da dies jedoch nicht machbar ist (insbesondere wenn man bedenkt, dass eine solche Entität möglicherweise Hunderte von Beziehungen haben könnte), gibt es zwei einfache Lösungen in meinem Kopf:

  1. legen Sie einen Setter für die ID in der Customer-Klasse fest - und lassen Sie so die ID festlegen und speichern Sie dann das Customer-Objekt über das entsprechende Repository.

oder

  1. fügen Sie das ID-Feld zum Konstruktor hinzu. Wenn Sie einen Kunden aktualisieren möchten, erstellen Sie immer ein neues Objekt mit der alten ID, jedoch die neuen Werte für die anderen Felder (in diesem Fall nur der Name).

Meine Frage ist also, ob es eine allgemeine Regel gibt, wie man das macht? Welche Nachteile haben die beiden Methoden, die ich erklärt habe?

8
Lukas Makor

Noch besser als die Antwort von @Tanjim Rahman können Sie mit Spring Data JPA die Methode T getOne(ID id) verwenden. 

Customer customerToUpdate = customerRepository.getOne(id);
customerToUpdate.setName(customerDto.getName);
customerRepository.save(customerToUpdate);

Ist besser, weil getOne(ID id)Sie nur ein Referenz (Proxy) -Objekt erhält und es nicht aus der DB abruft. In dieser Referenz können Sie festlegen, was Sie möchten, und unter save() wird nur eine SQL-UPDATE-Anweisung ausgeführt, wie Sie es erwarten. Im Vergleich zum Aufruf von find() wie in @Tanjim Rahmans Antwortfederdaten führt JPA eine SQL SELECT-Anweisung aus, um die Entität physisch aus der DB abzurufen, die Sie nicht benötigen, wenn Sie gerade aktualisieren.

34
Robert Niestroj

Einfaches JPA-Update .. 

Customer customer = em.find(id, Customer.class); //Consider em as JPA EntityManager
customer.setName(customerDto.getName);
em.merge(customer);
3
Esty

Wenn Sie nicht direkt mit Entitäten, sondern mit DTOs arbeiten müssen, sollten Sie die vorhandene Customer-Instanz abrufen und die aktualisierten Felder aus der DTO dieser zuordnen.

Customer entity = //load from DB
//map fields from DTO to entity
1
Alan Hay

Dies ist mehr eine Frage der Objektinitialisierung als eine jpa-Frage. Beide Methoden funktionieren, und Sie können beide gleichzeitig verwenden. Normalerweise ist der Datenelementwert vor der Instantiierung bereit, und Sie verwenden die Konstruktorparameter Nach der Instantiierung aktualisiert, sollten Sie einen Setter haben. 

1
Amer Qarabsa

In Spring Data definieren Sie einfach eine Aktualisierungsabfrage, wenn Sie die ID haben

  @Repository
  public interface CustomerRepository extends JpaRepository<Customer , Long> {

     @Query("update Customer c set c.name = :name WHERE c.id = :customerId")
     void setCustomerName(@Param("customerId") Long id);

  }

Einige Lösungen behaupten, Spring-Daten zu verwenden und JPA oldschool (sogar in einer Weise mit verlorenen Updates) zu verwenden.

0
gorefest