ある種のデータベースに永続化されているある種のデータ構造があるとします。簡単にするために、このデータ構造を呼びましょうPerson
。これで、他のアプリケーションがを作成、読み取り、更新、および削除できるようにするCRUD APIを設計する必要がありますPerson
。簡単にするために、このAPIが何らかのWebサービスを介してアクセスされると仮定します。
CRUDのC、R、Dパーツのデザインはシンプルです。私はC#のような関数表記を使用します-実装はSOAP、REST / JSON、またはその他の可能性があります。
class Person {
string Name;
DateTime? DateOfBirth;
...
}
Identifier CreatePerson(Person);
Person GetPerson(Identifier);
void DeletePerson(Identifier);
アップデートはどうですか?自然なことは
void UpdatePerson(Identifier, Person);
しかし、どのフィールドを更新するかをどのように指定しますPerson
か?
私が思いつくことができる解決策:
常に完全な Personを渡すように要求することができます。つまり、クライアントは次のようにして生年月日を更新します。
p = GetPerson(id); p.DateOfBirth = ...; UpdatePerson(id, p);
ただし、そのためには、GetとUpdateの間にトランザクションの整合性またはロックが必要になります。そうしないと、他のクライアントによって並行して行われた他の変更を上書きする可能性があります。これにより、APIがさらに複雑になります。さらに、次の疑似コード(JSONをサポートするクライアント言語を想定)であるため、エラーが発生しやすくなります。
UpdatePerson(id, { "DateOfBirth": "2015-01-01" });
-これは正しいように見えます-DateOfBirthを変更するだけでなく、他のすべてのフィールドをnullにリセットします。
であるすべてのフィールドを無視できます
null
。しかし、それを変更しないことDateOfBirth
と、意図的にnullに変更することの違いをどのように作成しますか?署名をに変更します
void UpdatePerson(Identifier, Person, ListOfFieldNamesToUpdate)
。署名をに変更します
void UpdatePerson(Identifier, ListOfFieldValuePairs)
。送信プロトコルのいくつかの機能を使用します。たとえば、PersonのJSON表現に含まれていないすべてのフィールドを無視できます。ただし、通常は、JSONを自分で解析し、ライブラリの組み込み機能(WCFなど)を使用できないようにする必要があります。
ソリューションはどれも私には本当にエレガントに思えません。確かに、これは一般的な問題なので、誰もが使用するベストプラクティスソリューションは何ですか?
Person
まだ永続化されていない新しく作成されたインスタンスの場合、識別子が永続化メカニズムの一部として決定された場合は、nullのままにします。答えは、JPAはバージョン番号を使用します。バージョン23を読み取る場合、アイテムを更新すると、DBのバージョンが24の場合、書き込みは失敗します。