web-dev-qa-db-ja.com

Spring Data JPA:モデルをエレガントに更新する方法は?

  1. 私のモデルは次のようなものです。

    @Entity
    @Table(name = "user")
    public class User {
    
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Long id;
    
        @Column(name="email")
        private String email;
    
        @Column(name = "weblink")
        private String webLink;
    
        //getter & setter
    }
    
  2. httpリクエストを介してフォームまたはモバイルデータを収集し、springmvcはこれらのデータをモデルのようなユーザーに提供します。

    たとえば、次のようなリクエストがあります。

    http://localhost:8080/update?id=1919&[email protected]

  3. contollerでは、リクエストURLとそのパラメータは自動的にUserオブジェクトに変換されます。

    @RequestMapping(method = RequestMethod.GET, value = "/update0")
    public User update(@ModelAttribute("User") User user){
    
        System.out.println(user.getId());
        System.out.println(user.getEmail());
        System.out.println(user.getWebLink());
    
        return userRepository.save(test);
    }
    
  4. mysqlにidが1919のレコードがあり、列(id、email、weblik)にすべて値がある場合。

    ご覧のとおり、Webまたはモバイルから渡されたユーザーオブジェクトには2つのプロパティがあります。

    http://localhost:8080/update?id=1919&[email protected]

    idとemailには値があり、weblinkにはありません。

    したがって、saveメソッドを実行すると、列の電子メールが[email protected]に更新され、weblikフィールドもNULLに更新されますが、更新したくありませんこのフィールドは、電子メールフィールドを更新したいだけです。

  5. 問題を解決する方法は2つありますが、すべてがエレガントというわけではありません。

    5.1最初にユーザーオブジェクトをロードして更新する

    User userExist = userRepository.findOne(user.getId());
    userExist.setEmail(user.getEmail());
    
    //or using 
    //BeanUtil.copyProprty(formDto,modle)
    
    userRepository.save();
    

    5.2 @DynamicUpdateを使用しますが、機能しません。

    ユーザーモデルを更新し、余分な作業を行わない他の方法はありますか?.

    前もって感謝します。

10
diligent

最も簡単な方法は、適切に設定されたコントローラーメソッドです。

@RequestMapping(value = "/users/{user}", method = RequestMethod.PATCH)
public … updateUser(@ModelAttribute User user) { … }

リファレンスドキュメント によると、このメソッドが呼び出されると、次の手順が実行されます。

  1. Userのインスタンスを取得する必要があります。これには基本的に、URIテンプレートから抽出されたパスセグメントをConverterに変換するためにStringからUserまでのUserをSpringMVCに登録する必要があります。あなたが例えば リファレンスドキュメント で説明されているように、Spring Dataを使用してWebサポートを有効にします。これはそのまま使用できます。
  2. 既存のインスタンスが取得された後、リクエストデータは既存のオブジェクトにバインドされます。
  3. バインドされたオブジェクトはメソッドに渡されます。

追加のヒント

  • 更新のHTTPメソッドとしてGETを使用しないでください。 GETは安全な操作(副作用なし)として定義されていますが、更新はそうではありません。 PATCHは、既存のリソースを部分的に更新できるように定義されているため、ここでは正しい方法です。
  • フォームデータをPUTおよびPATCHリクエストに送信するには、説明されているようにHttpPutFormContentFilterをアプリケーションに登録する必要があります ここ 。私はそれをデフォルトで登録するために Spring Bootの問題 を提出しました。
13
Oliver Drotbohm

最初に、_@Oliver Gierke_によるPatchソリューションは本当に素晴らしいと言う必要があります。

そして私の以前のプロジェクトでは、私の解決策は次のとおりです:
1。 JpaRepositoryを実装する抽象クラスを作成し、save()関数を実装します。
2。保存機能で、DBからエンティティを取得します。存在しません。保存してください。それ以外の場合は、リフレクションを使用して、更新されたエンティティからすべてのNOT NULLフィールドを取得し、DBからエンティティに設定します。 (あなたと同じですが、すべての保存機能でそれを行いました)

0
Mavlarn