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:
oder
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?
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.
Einfaches JPA-Update ..
Customer customer = em.find(id, Customer.class); //Consider em as JPA EntityManager
customer.setName(customerDto.getName);
em.merge(customer);
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
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.
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.