テーマ
本体の標準機能ではありません
このページは本体を改修する場合の設計メモです。1.5.8.1 では、コメントの追加・編集・削除はどれもレコード全体の更新として処理され、コメントだけを操作する API やサーバースクリプトのメソッドはありません。
ソースへのリンクは Implem/Implem.Pleasanter の 1.5.8.1(コミット fdcbb3f8)固定です。
fdcbb3f8
コメントは Issues・Results・Wikis の Comments 列に JSON 配列で入っています。1 件は CommentId・CreatedTime・UpdatedTime・Creator・Updator・Body を持ちます(Comment.cs#L12-L23)。新しいコメントは配列の先頭に入り、CommentId はそのレコード内の最大値 + 1 です(Comments.cs#L190-L208)。
Issues
Results
Wikis
Comments
CommentId
CreatedTime
UpdatedTime
Creator
Updator
Body
[ { "CommentId": 2, "CreatedTime": "2026-03-01T10:00:00", "Creator": 1, "Body": "新しいコメント" }, { "CommentId": 1, "CreatedTime": "2026-02-28T09:00:00", "UpdatedTime": "2026-03-01T11:00:00", "Creator": 1, "Updator": 2, "Body": "編集したコメント" } ]
Prepend
Update
Create
"[]"
model.Comments = "本文"
Comment{番号}
DeleteComment
Get
model.Comments
画面で編集できるのは自分が書いたコメントだけです(Creator == context.UserId。Comment.cs#L104-L107)。
Creator == context.UserId
サーバースクリプトで items.Update(id, model) に apiModel を渡すときは、Comments を null にしてから JSON にするため、取得したモデルを渡しても既存のコメントが二重に追加されることはありません(ServerScriptModelApiModel.cs#L435-L479)。
items.Update(id, model)
null
コメントの操作がレコードの更新と同じ処理を通るため、次のことが起こります。
コメント専用の入口を足し、Comments 列だけを更新します。
図を読み込み中…
IssueModel
ResultModel
WikiModel
/api/items/{id}/AddComment
UpdateComment
GetComments
items.AddComment(id, body)
items.UpdateComment(id, commentId, body)
items.DeleteComment(id, commentId)
items.GetComments(id)
$p.apiAddComment
$p.apiExec
{ "ApiVersion": 1.1, "ApiKey": "your-api-key", "CommentId": 3, "Body": "編集後の本文" }
addcomment
コメントは 1 列の JSON 配列なので、「読んで、配列を変えて、書き戻す」処理になります。2 人がほぼ同時にコメントを追加すると、後から書いた方が先の追加を含まない配列で上書きし、先のコメントが消えます。UpdatedTime による競合チェックをやめると、この問題は画面の更新競合としても検出されなくなります。
対策は 2 つあります。
ReferenceId
ReferenceType
まずは JSON 配列のまま「読み直してマージ」で作り、ページングや大量コメントの性能が問題になったら専用テーブルを検討する、という順が現実的です。
モデル・ユーティリティ・コントローラの多くは CodeDefiner のテンプレートから生成されるコードです。追加するメソッドは、生成し直しで消えない場所(テンプレート側か、生成対象外のファイル)に置く必要があります(CodeDefiner)。
コメントだけを追加・編集・削除する
本体の標準機能ではありません
このページは本体を改修する場合の設計メモです。1.5.8.1 では、コメントの追加・編集・削除はどれもレコード全体の更新として処理され、コメントだけを操作する API やサーバースクリプトのメソッドはありません。
前提にした現行の実装(1.5.8.1)
ソースへのリンクは Implem/Implem.Pleasanter の 1.5.8.1(コミット
fdcbb3f8)固定です。データの持ち方
コメントは
Issues・Results・WikisのComments列に JSON 配列で入っています。1 件はCommentId・CreatedTime・UpdatedTime・Creator・Updator・Bodyを持ちます(Comment.cs#L12-L23)。新しいコメントは配列の先頭に入り、CommentIdはそのレコード内の最大値 + 1 です(Comments.cs#L190-L208)。操作ごとの経路
Commentsの値をPrependUpdate(またはCreate)のCommentsに本文を渡すと 1 件追加("[]"は無視。Comments.cs#L281-L293)model.Comments = "本文"で 1 件追加(ServerScriptUtilities.cs#L950)Comment{番号}を更新と一緒に送る(ResultModel.cs#L2656-L2663)DeleteCommentだが、中身はフォームを読んでレコードを更新する(ResultModel.cs#L2622-L2629)Getのレスポンスにレコードの一部として含まれるmodel.Comments画面で編集できるのは自分が書いたコメントだけです(
Creator == context.UserId。Comment.cs#L104-L107)。サーバースクリプトで
items.Update(id, model)に apiModel を渡すときは、Commentsをnullにしてから JSON にするため、取得したモデルを渡しても既存のコメントが二重に追加されることはありません(ServerScriptModelApiModel.cs#L435-L479)。困ること
コメントの操作がレコードの更新と同じ処理を通るため、次のことが起こります。
UpdatedTimeが変わり、他のユーザーの編集と更新日時の競合チェックでぶつかる設計案
コメント専用の入口を足し、
Comments列だけを更新します。図を読み込み中…
IssueModel・ResultModel・WikiModel)に、Comments列だけを更新する SQL を作るメソッド(履歴を作らない、UpdatedTimeを変えない)/api/items/{id}/AddComment(Body)、UpdateComment(CommentId、Body)、DeleteComment(CommentId)、GetCommentsitems.AddComment(id, body)、items.UpdateComment(id, commentId, body)、items.DeleteComment(id, commentId)、items.GetComments(id)$p.apiAddCommentなどのラッパー($p.apiExecで上の API を呼ぶ)権限
通知・履歴・ログ
addcommentなど)同時書き込みの問題
コメントは 1 列の JSON 配列なので、「読んで、配列を変えて、書き戻す」処理になります。2 人がほぼ同時にコメントを追加すると、後から書いた方が先の追加を含まない配列で上書きし、先のコメントが消えます。
UpdatedTimeによる競合チェックをやめると、この問題は画面の更新競合としても検出されなくなります。図を読み込み中…
対策は 2 つあります。
Comments列を行ロック付きで読み直し、その時点の配列に追加・変更を適用して書く。CommentIdもこのとき採番するCommentsテーブル(CommentIdを自動採番、ReferenceId・ReferenceType・Creator・Body・日時)に 1 行ずつ持つまずは JSON 配列のまま「読み直してマージ」で作り、ページングや大量コメントの性能が問題になったら専用テーブルを検討する、という順が現実的です。
改修時の注意
モデル・ユーティリティ・コントローラの多くは CodeDefiner のテンプレートから生成されるコードです。追加するメソッドは、生成し直しで消えない場所(テンプレート側か、生成対象外のファイル)に置く必要があります(CodeDefiner)。
関連ページ