前書き
エンティティ(オブジェクト)のインスタンスに対する一般的なWebサービスの基本的なセット操作の構造は、CRUD(C reate、R ead、U pdate、およびD elete)です。HTTPメソッドPOST、GET、PUT、およびDELETEは、RESTのこれらの操作に対応しています。しかし、多くの場合、開発者はHTTPPATCHメソッドに対応するオブジェクトを部分的に変更する必要があります。その意味は、サーバー側で、リクエストで渡されたオブジェクトのフィールドのみを変更することです。これにはさまざまな理由があります。
本質的に多数のフィールド。
高負荷の下で同じオブジェクトが同時に変更される可能性が高く、その結果、変更されたフィールドだけが上書きされるわけではありません。
ストレージ内の複数またはすべてのオブジェクトのフィールドを変更することが不可能またはより複雑になる(一括更新)。
これらの理由、および場合によっては他の理由により、開発者はオブジェクトを部分的に変更するための操作のスタックを実装するようになります。
部分更新の問題を解決するために最も頻繁に使用されるオプションについて考えてみましょう。
通常のコントローラーとDTOを使用する
最も一般的なPATCHメソッドの実装の1つ。コントローラでは、着信オブジェクトが通常のDTOに逆シリアル化され、さらにアプリケーション層のスタックに沿って、null値を持つDTO内のすべてのフィールドを処理できないと見なされます。
この方法の利点には、実装の「親しみやすさ」が含まれます。
- null
( null
).
DTO . , . ObjectMapper
(/ POJO, @JsonInclude(Include.NON_NULL) ) , MapStruct, .
Map<String, Object> POJO
Map<String, Object>
. JSON . , , ( IDE).
null
.
: , , , , runtime( ).
JSON Patch JSON Merge Patch
JSON Patch JSON Merge Patch . Java EE , : JsonPatch JsonMergePatch. , json-patch. Michael Scharhag REST: Partial updates with PATCH.
: , , , , , , .
, DTO , , , , etc.
Partial Update library
: DTO Map<String, Object>
" ".
ChangeLogger ChangeLoggerProducer.
ChangeLoggerProducer
"" POJO, ChangeLogger
, Map<String, Object>
.
POJO:
public class UserModel {
private String login;
private String firstName;
private String lastName;
private String birthDate;
private String email;
private String phoneNumber;
}
@ChangeLogger
public class UserDto extends UserModel {
}
"":
ChangeLoggerProducer<UserDto> producer = new ChangeLoggerProducer<>(UserDto.class);
UserDto user = producer.produceEntity();
user.setLogin("userlogin");
user.setPhoneNumber("+123(45)678-90-12");
Map<String, Object> changeLog = ((ChangeLogger) user).changelog();
/*
changeLog in JSON notation will contains:
{
"login": "userlogin",
"phoneNumber": "+123(45)678-90-12"
}
*/
"" : Set<String>
, Map<String, Object> changelog()
, , , . , , ChangeLogger
, Map<String, Object> changelog()
.
/ "" ChangeLoggerAnnotationIntrospector
. Annotation Introspector ObjectMapper
. "" , @ChangeLogger
Map<String, Object> changelog()
. ObjectMapper
ChangeLoggerAnnotationIntrospector
.
:
ObjectMapper mapper = new ObjectMapper.setAnnotationIntrospector(new ChangeLoggerAnnotationIntrospector());
ChangeLoggerProducer<UserDto> producer = new ChangeLoggerProducer<>(UserDto.class);
UserDto user = producer.produceEntity();
user.setLogin("userlogin");
user.setPhoneNumber("+123(45)678-90-12");
String result = mapper.writeValueAsString(user);
/*
result should be equal
"{\"login\": \"userlogin\",\"phoneNumber\": \"+123(45)678-90-12\"}"
*/
:
ObjectMapper mapper = new ObjectMapper.setAnnotationIntrospector(new ChangeLoggerAnnotationIntrospector());
String source = "{\"login\": \"userlogin\",\"phoneNumber\": \"+123(45)678-90-12\"}";
UserDto user = mapper.readValue(source, UserDto.class);
Map<String, Object> changeLog = ((ChangeLogger) user).changelog();
/*
changeLog in JSON notation will contains:
{
"login": "userlogin",
"phoneNumber": "+123(45)678-90-12"
}
*/
ObjectMapper
ChangeLoggerAnnotationIntrospector
JSON . DTO, Model, Entity "". Partial Update Example.
Partial Update library , . , runtime.
:
" ", DTO, Model, Entity;
Spring, / "" DTO ( ),
ChangeLoggerAnnotationIntrospector
ObjectMapper
;
SQL/HQL bulk update ;
.
この記事の形式では、マッパーを作成するためのインフラストラクチャを詳しく調べたり、一般的なアプリケーションスタックでのライブラリの使用法を示したりすることはできません。将来的には、部分更新の例をより詳細に分析し、ライブラリの内部実装の説明にさらに注意を払うことができます。