Ist es möglich, mit Spring MVC mit JPA nur eine Teilmenge der Attribute einer Entität zu aktualisieren?

Ich arbeite mit Spring Roo und verwende Spring MVC und JPA für die Persistenz mit einer MySQL-Datenbank. Ich bin sehr neu in Spring MVC und Java im Allgemeinen, habe aber mit CakePHP und Rails gearbeitet.

Ich habe einUser Entität, die neben einem Passwort auch persönliche Daten enthält. So etwas wie dieses (mit Ausnahme vieler Roo-generierter Funktionen in zusätzlichen .aj-Dateien):

public class User {

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

    @Column(name = "PASSWORD", length = 32)
    private String password;

    @Column(name = "FIRST_NAME", length = 25)
    private String firstName;

    @Column(name = "LAST_NAME", length = 25)
    private String lastName;

    @Column(name = "ADDRESS", length = 255)
    private String address;

    // The appropriate getters and setters
    ...
}

Dann habe ich eine Bearbeitungsaktion in meinemUser Controller, den ich anhand des automatisch generierten Gerüsts von Roo nach folgenden Konventionen erstellt habe:

@RequestMapping(value="/edit", method = RequestMethod.GET)
public String editForm(Model uiModel) {
    String username = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    uiModel.addAttribute("user", User.findUserByUsername(username).getSingleResult());
    return "account/edit";
}

Und eine JSPX-Ansicht zum Rendern des Formulars, ebenfalls gemäß den Konventionen von Roo:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<div xmlns:field="urn:jsptagdir:/WEB-INF/tags/form/fields" xmlns:form="urn:jsptagdir:/WEB-INF/tags/form" xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0">
    <jsp:directive.page contentType="text/html;charset=UTF-8"/>
    <jsp:output omit-xml-declaration="yes"/>
    <form:update id="" label="Personal Details" modelAttribute="user" path="/account" versionField="none">
        <field:input id="" field="firstName" label="First Name" />
        <field:input id="" field="lastName" label="Last Name" />
        <field:textarea id="" field="address" label="Street Address" />
    </form:update>
</div>

ich machenicht Damit das Formular das Kennwort aktualisiert, müssen nur die bereitgestellten Felder (Vorname, Nachname und Adresse) ausgefüllt werden.

Die Update-Aktion, ebenfalls nach der Roo-Konvention:

@RequestMapping(method = RequestMethod.PUT, produces = "text/html")
public String edit(@Valid User user, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest) {
    if (bindingResult.hasErrors()) {
        uiModel.addAttribute("user", user);
        return "account/edit";
    }
    uiModel.asMap().clear();
    user.merge();
    return "redirect:/account";
}

Das Benutzerobjekt wird perfekt aktualisiert. Das Problem besteht jedoch darin, dass das Kennwortfeld mit Null überschrieben wird, da es nicht als Eingabe im Formular bereitgestellt wird und daher im Benutzerobjekt, das an den Anforderungshandler zum Senden des Formulars übergeben wird, auf Null gesetzt wird. Das Problem tritt beim von Roo generierten Gerüst nicht auf, da sie Formulareingaben für alle Spalten bereitstellen. Ich könnte es also als verstecktes Feld hinzufügen, aber das klingt nicht nach einer guten Idee. Und ich habe das Gefühl, dass es einen viel besseren Weg gibt, es zu tun ...

TL; DR Wie kann ich nur die in einem Formular bereitgestellten Entitätsattribute aktualisieren, ohne die anderen Attribute zu überschreiben?

Mit anderen Worten, wie kann ich Spring / JPA die SQL generieren lassen?

UPDATE user SET firstname=?, lastname=?, address=?

anstatt

UPDATE user SET firstname=?, lastname=?, address=?, password=?

Codebeispiele wären fantastisch, da mir das alles neu ist :)

Vielen Dank!

AKTUALISIEREN: Ich konnte es mit dem Vorschlag von yglodt zum Laufen bringen und meinem Benutzermodell die folgende Methode hinzufügen:

@Transactional
public void mergeWithExistingAndUpdate() {
    final User existingUser = User.findUser(this.getId());

    existingUser.setFirstName(this.getFirstName());
    existingUser.setLastName(this.getLastName());
    existingUser.setAddress(this.getAddress());

    existingUser.flush();
}

und Aufrufen von meiner Controller-Aktion anstelle von user.merge ():

user.mergeWithExistingAndUpdate();

Antworten auf die Frage(3)

Ihre Antwort auf die Frage