From 31d74f52b85c3178e9bb852aa581b354ffafa093 Mon Sep 17 00:00:00 2001 From: nameless-mc Date: Wed, 12 Nov 2025 16:04:15 +0900 Subject: [PATCH 1/6] feat!: add upsert mode to update records --- .../java/com/kintone/client/RecordClient.java | 5 +++-- .../api/record/UpdateRecordsRequest.java | 6 ++++++ .../api/record/UpdateRecordsResponseBody.java | 6 +++--- .../model/record/RecordOperationType.java | 10 ++++++++++ .../model/record/RecordUpdateResult.java | 20 +++++++++++++++++++ .../com/kintone/client/RecordClientTest.java | 18 ++++++++++++----- 6 files changed, 55 insertions(+), 10 deletions(-) create mode 100644 src/main/java/com/kintone/client/model/record/RecordOperationType.java create mode 100644 src/main/java/com/kintone/client/model/record/RecordUpdateResult.java diff --git a/src/main/java/com/kintone/client/RecordClient.java b/src/main/java/com/kintone/client/RecordClient.java index d568d9c2..92aa2beb 100644 --- a/src/main/java/com/kintone/client/RecordClient.java +++ b/src/main/java/com/kintone/client/RecordClient.java @@ -38,6 +38,7 @@ import com.kintone.client.model.record.RecordComment; import com.kintone.client.model.record.RecordForUpdate; import com.kintone.client.model.record.RecordRevision; +import com.kintone.client.model.record.RecordUpdateResult; import com.kintone.client.model.record.StatusAction; import com.kintone.client.model.record.UpdateKey; import java.util.List; @@ -516,9 +517,9 @@ public UpdateRecordAssigneesResponseBody updateRecordAssignees( * * @param app the App ID * @param records a list of objects that include id/updateKey, revision and record objects - * @return a list of record revisions. See {@link RecordRevision} + * @return a list of record update results. See {@link RecordUpdateResult} */ - public List updateRecords(long app, List records) { + public List updateRecords(long app, List records) { UpdateRecordsRequest req = new UpdateRecordsRequest(); req.setApp(app); req.setRecords(records); diff --git a/src/main/java/com/kintone/client/api/record/UpdateRecordsRequest.java b/src/main/java/com/kintone/client/api/record/UpdateRecordsRequest.java index dc3dafc2..2bd77e41 100644 --- a/src/main/java/com/kintone/client/api/record/UpdateRecordsRequest.java +++ b/src/main/java/com/kintone/client/api/record/UpdateRecordsRequest.java @@ -14,4 +14,10 @@ public class UpdateRecordsRequest implements KintoneRequest { /** A list of objects that include id/updateKey, revision and record objects (required). */ private List records; + + /** + * If set to true, the UPSERT mode will be enabled. In UPSERT mode, if the specified record + * exists, it will be updated. If it does not exist, a new record will be created (optional). + */ + private Boolean upsert; } diff --git a/src/main/java/com/kintone/client/api/record/UpdateRecordsResponseBody.java b/src/main/java/com/kintone/client/api/record/UpdateRecordsResponseBody.java index 2efc0b87..364335cc 100644 --- a/src/main/java/com/kintone/client/api/record/UpdateRecordsResponseBody.java +++ b/src/main/java/com/kintone/client/api/record/UpdateRecordsResponseBody.java @@ -1,7 +1,7 @@ package com.kintone.client.api.record; import com.kintone.client.api.KintoneResponseBody; -import com.kintone.client.model.record.RecordRevision; +import com.kintone.client.model.record.RecordUpdateResult; import java.util.List; import lombok.Value; @@ -9,6 +9,6 @@ @Value public class UpdateRecordsResponseBody implements KintoneResponseBody { - /** A list of objects that include the record IDs and updated revisions. */ - private final List records; + /** A list of objects that include the record IDs, updated revisions, and operations. */ + private final List records; } diff --git a/src/main/java/com/kintone/client/model/record/RecordOperationType.java b/src/main/java/com/kintone/client/model/record/RecordOperationType.java new file mode 100644 index 00000000..a86ea25d --- /dev/null +++ b/src/main/java/com/kintone/client/model/record/RecordOperationType.java @@ -0,0 +1,10 @@ +package com.kintone.client.model.record; + +/** The type of operation performed on a record when using UPSERT mode in Update Records API. */ +public enum RecordOperationType { + /** An existing record was updated. */ + UPDATE, + + /** A new record was created. */ + INSERT +} diff --git a/src/main/java/com/kintone/client/model/record/RecordUpdateResult.java b/src/main/java/com/kintone/client/model/record/RecordUpdateResult.java new file mode 100644 index 00000000..f63a1564 --- /dev/null +++ b/src/main/java/com/kintone/client/model/record/RecordUpdateResult.java @@ -0,0 +1,20 @@ +package com.kintone.client.model.record; + +import lombok.Value; + +/** A value that contains the record ID, revision, and operation, returned by Update Records API. */ +@Value +public class RecordUpdateResult { + + /** The Record ID */ + private final long id; + + /** The revision number of the record after updating or creating the record. */ + private final long revision; + + /** + * The operation that was performed. UPDATE (existing record was updated) or INSERT (new record + * was created). Null when not using UPSERT mode. + */ + private final RecordOperationType operation; +} diff --git a/src/test/java/com/kintone/client/RecordClientTest.java b/src/test/java/com/kintone/client/RecordClientTest.java index 94fc8ec1..dcb62e2a 100644 --- a/src/test/java/com/kintone/client/RecordClientTest.java +++ b/src/test/java/com/kintone/client/RecordClientTest.java @@ -39,7 +39,8 @@ import com.kintone.client.model.record.Record; import com.kintone.client.model.record.RecordComment; import com.kintone.client.model.record.RecordForUpdate; -import com.kintone.client.model.record.RecordRevision; +import com.kintone.client.model.record.RecordOperationType; +import com.kintone.client.model.record.RecordUpdateResult; import com.kintone.client.model.record.StatusAction; import com.kintone.client.model.record.UpdateKey; import java.util.Arrays; @@ -525,12 +526,19 @@ public void updateRecordAssignees_UpdateRecordAssigneesRequest() { public void updateRecords_long_List() { RecordForUpdate up1 = new RecordForUpdate(1L, new Record()); RecordForUpdate up2 = new RecordForUpdate(new UpdateKey("text", "test"), new Record()); - RecordRevision rev1 = new RecordRevision(1, 2); - RecordRevision rev2 = new RecordRevision(100, 2); - mockClient.setResponseBody(new UpdateRecordsResponseBody(Arrays.asList(rev1, rev2))); + RecordUpdateResult result1 = new RecordUpdateResult(1, 2, RecordOperationType.UPDATE); + RecordUpdateResult result2 = new RecordUpdateResult(100, 2, RecordOperationType.INSERT); + mockClient.setResponseBody(new UpdateRecordsResponseBody(Arrays.asList(result1, result2))); List records = Arrays.asList(up1, up2); - assertThat(sut.updateRecords(1, records)).containsExactly(rev1, rev2); + List result = sut.updateRecords(1, records); + assertThat(result).hasSize(2); + assertThat(result.get(0).getId()).isEqualTo(1); + assertThat(result.get(0).getRevision()).isEqualTo(2); + assertThat(result.get(0).getOperation()).isEqualTo(RecordOperationType.UPDATE); + assertThat(result.get(1).getId()).isEqualTo(100); + assertThat(result.get(1).getRevision()).isEqualTo(2); + assertThat(result.get(1).getOperation()).isEqualTo(RecordOperationType.INSERT); assertThat(mockClient.getLastApi()).isEqualTo(KintoneApi.UPDATE_RECORDS); assertThat(mockClient.getLastBody()).isInstanceOf(UpdateRecordsRequest.class); UpdateRecordsRequest expected = new UpdateRecordsRequest().setApp(1L).setRecords(records); From bf78fb2db505bdd004b3815289ef582181328427 Mon Sep 17 00:00:00 2001 From: nameless-mc Date: Tue, 18 Nov 2025 14:47:26 +0900 Subject: [PATCH 2/6] feat: add upsertRecords interface --- .../java/com/kintone/client/RecordClient.java | 18 +++++++++++++ .../com/kintone/client/RecordClientTest.java | 27 ++++++++++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/kintone/client/RecordClient.java b/src/main/java/com/kintone/client/RecordClient.java index 92aa2beb..d2636642 100644 --- a/src/main/java/com/kintone/client/RecordClient.java +++ b/src/main/java/com/kintone/client/RecordClient.java @@ -523,6 +523,7 @@ public List updateRecords(long app, List re UpdateRecordsRequest req = new UpdateRecordsRequest(); req.setApp(app); req.setRecords(records); + req.setUpsert(false); return updateRecords(req).getRecords(); } @@ -536,6 +537,23 @@ public UpdateRecordsResponseBody updateRecords(UpdateRecordsRequest request) { return client.call(KintoneApi.UPDATE_RECORDS, request, handlers); } + /** + * Inserts or updates details of multiple records in an App, by specifying their record numbers, + * or their unique keys. If the record exists, it will be updated. If it does not exist, a new + * record will be created. + * + * @param app the App ID + * @param records a list of objects that include id/updateKey, revision and record objects + * @return a list of record update results. See {@link RecordUpdateResult} + */ + public List upsertRecords(long app, List records) { + UpdateRecordsRequest req = new UpdateRecordsRequest(); + req.setApp(app); + req.setRecords(records); + req.setUpsert(true); + return updateRecords(req).getRecords(); + } + /** * Updates the Status of a record of an App, that was set with the Process Management feature. * diff --git a/src/test/java/com/kintone/client/RecordClientTest.java b/src/test/java/com/kintone/client/RecordClientTest.java index dcb62e2a..7c268cf9 100644 --- a/src/test/java/com/kintone/client/RecordClientTest.java +++ b/src/test/java/com/kintone/client/RecordClientTest.java @@ -541,7 +541,8 @@ public void updateRecords_long_List() { assertThat(result.get(1).getOperation()).isEqualTo(RecordOperationType.INSERT); assertThat(mockClient.getLastApi()).isEqualTo(KintoneApi.UPDATE_RECORDS); assertThat(mockClient.getLastBody()).isInstanceOf(UpdateRecordsRequest.class); - UpdateRecordsRequest expected = new UpdateRecordsRequest().setApp(1L).setRecords(records); + UpdateRecordsRequest expected = + new UpdateRecordsRequest().setApp(1L).setRecords(records).setUpsert(false); assertThat(mockClient.getLastBody()).usingRecursiveComparison().isEqualTo(expected); } @@ -556,6 +557,30 @@ public void updateRecords_UpdateRecordsRequest() { assertThat(mockClient.getLastBody()).isEqualTo(req); } + @Test + public void upsertRecords_long_List() { + RecordForUpdate up1 = new RecordForUpdate(1L, new Record()); + RecordForUpdate up2 = new RecordForUpdate(new UpdateKey("text", "test"), new Record()); + RecordUpdateResult result1 = new RecordUpdateResult(1, 2, RecordOperationType.UPDATE); + RecordUpdateResult result2 = new RecordUpdateResult(100, 2, RecordOperationType.INSERT); + mockClient.setResponseBody(new UpdateRecordsResponseBody(Arrays.asList(result1, result2))); + + List records = Arrays.asList(up1, up2); + List result = sut.upsertRecords(1, records); + assertThat(result).hasSize(2); + assertThat(result.get(0).getId()).isEqualTo(1); + assertThat(result.get(0).getRevision()).isEqualTo(2); + assertThat(result.get(0).getOperation()).isEqualTo(RecordOperationType.UPDATE); + assertThat(result.get(1).getId()).isEqualTo(100); + assertThat(result.get(1).getRevision()).isEqualTo(2); + assertThat(result.get(1).getOperation()).isEqualTo(RecordOperationType.INSERT); + assertThat(mockClient.getLastApi()).isEqualTo(KintoneApi.UPDATE_RECORDS); + assertThat(mockClient.getLastBody()).isInstanceOf(UpdateRecordsRequest.class); + UpdateRecordsRequest expected = + new UpdateRecordsRequest().setApp(1L).setRecords(records).setUpsert(true); + assertThat(mockClient.getLastBody()).usingRecursiveComparison().isEqualTo(expected); + } + @Test public void updateRecordStatus_long_long_String() { mockClient.setResponseBody(new UpdateRecordStatusResponseBody(10L)); From 293aa734edb83ab7b2d09bb2b289923178b8f96a Mon Sep 17 00:00:00 2001 From: nameless-mc Date: Tue, 18 Nov 2025 14:49:34 +0900 Subject: [PATCH 3/6] docs: update comments --- .../java/com/kintone/client/model/record/RecordRevision.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/com/kintone/client/model/record/RecordRevision.java b/src/main/java/com/kintone/client/model/record/RecordRevision.java index b0cae6b9..92b562bd 100644 --- a/src/main/java/com/kintone/client/model/record/RecordRevision.java +++ b/src/main/java/com/kintone/client/model/record/RecordRevision.java @@ -2,10 +2,7 @@ import lombok.Value; -/** - * A value that contains the record ID and the revision, returned by Update Records API and Update - * Record Statuses API. - */ +/** A value that contains the record ID and the revision, returned by Update Record Statuses API. */ @Value public class RecordRevision { From 7ab29a3d8c8e341bc4105d50d9d8d83819025f90 Mon Sep 17 00:00:00 2001 From: nameless-mc Date: Thu, 27 Nov 2025 15:31:06 +0900 Subject: [PATCH 4/6] feat: separate update and upsert --- .../java/com/kintone/client/KintoneApi.java | 2 + .../java/com/kintone/client/RecordClient.java | 28 +++++++---- .../api/record/UpdateRecordsRequest.java | 6 --- .../api/record/UpdateRecordsResponseBody.java | 6 +-- .../api/record/UpsertRecordsRequest.java | 23 +++++++++ .../api/record/UpsertRecordsResponseBody.java | 14 ++++++ .../client/model/record/RecordRevision.java | 5 +- .../model/record/RecordUpdateResult.java | 2 +- .../com/kintone/client/RecordClientTest.java | 49 ++++++++++--------- 9 files changed, 93 insertions(+), 42 deletions(-) create mode 100644 src/main/java/com/kintone/client/api/record/UpsertRecordsRequest.java create mode 100644 src/main/java/com/kintone/client/api/record/UpsertRecordsResponseBody.java diff --git a/src/main/java/com/kintone/client/KintoneApi.java b/src/main/java/com/kintone/client/KintoneApi.java index 3298dacb..8fe494b8 100644 --- a/src/main/java/com/kintone/client/KintoneApi.java +++ b/src/main/java/com/kintone/client/KintoneApi.java @@ -85,6 +85,7 @@ import com.kintone.client.api.record.UpdateRecordStatusResponseBody; import com.kintone.client.api.record.UpdateRecordStatusesResponseBody; import com.kintone.client.api.record.UpdateRecordsResponseBody; +import com.kintone.client.api.record.UpsertRecordsResponseBody; import com.kintone.client.api.schema.GetApiListResponseBody; import com.kintone.client.api.space.AddGuestsResponseBody; import com.kintone.client.api.space.AddSpaceFromTemplateResponseBody; @@ -112,6 +113,7 @@ public enum KintoneApi { GET_RECORDS(GET, "records", GetRecordsResponseBody.class), ADD_RECORDS(POST, "records", AddRecordsResponseBody.class), UPDATE_RECORDS(PUT, "records", UpdateRecordsResponseBody.class), + UPSERT_RECORDS(PUT, "records", UpsertRecordsResponseBody.class), DELETE_RECORDS(DELETE, "records", DeleteRecordsResponseBody.class), CREATE_CURSOR(POST, "records/cursor", CreateCursorResponseBody.class), GET_RECORDS_BY_CURSOR(GET, "records/cursor", GetRecordsByCursorResponseBody.class), diff --git a/src/main/java/com/kintone/client/RecordClient.java b/src/main/java/com/kintone/client/RecordClient.java index d2636642..8bebad7e 100644 --- a/src/main/java/com/kintone/client/RecordClient.java +++ b/src/main/java/com/kintone/client/RecordClient.java @@ -32,13 +32,15 @@ import com.kintone.client.api.record.UpdateRecordStatusesResponseBody; import com.kintone.client.api.record.UpdateRecordsRequest; import com.kintone.client.api.record.UpdateRecordsResponseBody; +import com.kintone.client.api.record.UpsertRecordsRequest; +import com.kintone.client.api.record.UpsertRecordsResponseBody; import com.kintone.client.model.Order; import com.kintone.client.model.record.PostedRecordComment; import com.kintone.client.model.record.Record; import com.kintone.client.model.record.RecordComment; import com.kintone.client.model.record.RecordForUpdate; import com.kintone.client.model.record.RecordRevision; -import com.kintone.client.model.record.RecordUpdateResult; +import com.kintone.client.model.record.RecordUpsertResult; import com.kintone.client.model.record.StatusAction; import com.kintone.client.model.record.UpdateKey; import java.util.List; @@ -517,13 +519,12 @@ public UpdateRecordAssigneesResponseBody updateRecordAssignees( * * @param app the App ID * @param records a list of objects that include id/updateKey, revision and record objects - * @return a list of record update results. See {@link RecordUpdateResult} + * @return a list of record revisions. See {@link RecordRevision} */ - public List updateRecords(long app, List records) { + public List updateRecords(long app, List records) { UpdateRecordsRequest req = new UpdateRecordsRequest(); req.setApp(app); req.setRecords(records); - req.setUpsert(false); return updateRecords(req).getRecords(); } @@ -544,14 +545,23 @@ public UpdateRecordsResponseBody updateRecords(UpdateRecordsRequest request) { * * @param app the App ID * @param records a list of objects that include id/updateKey, revision and record objects - * @return a list of record update results. See {@link RecordUpdateResult} + * @return a list of record update results. See {@link RecordUpsertResult} */ - public List upsertRecords(long app, List records) { - UpdateRecordsRequest req = new UpdateRecordsRequest(); + public List upsertRecords(long app, List records) { + UpsertRecordsRequest req = new UpsertRecordsRequest(); req.setApp(app); req.setRecords(records); - req.setUpsert(true); - return updateRecords(req).getRecords(); + return upsertRecords(req).getRecords(); + } + + /** + * Inserts or updates details of multiple records in an App. + * + * @param request the request parameters. See {@link UpsertRecordsRequest} + * @return the response data. See {@link UpsertRecordsResponseBody} + */ + public UpsertRecordsResponseBody upsertRecords(UpsertRecordsRequest request) { + return client.call(KintoneApi.UPSERT_RECORDS, request, handlers); } /** diff --git a/src/main/java/com/kintone/client/api/record/UpdateRecordsRequest.java b/src/main/java/com/kintone/client/api/record/UpdateRecordsRequest.java index 2bd77e41..dc3dafc2 100644 --- a/src/main/java/com/kintone/client/api/record/UpdateRecordsRequest.java +++ b/src/main/java/com/kintone/client/api/record/UpdateRecordsRequest.java @@ -14,10 +14,4 @@ public class UpdateRecordsRequest implements KintoneRequest { /** A list of objects that include id/updateKey, revision and record objects (required). */ private List records; - - /** - * If set to true, the UPSERT mode will be enabled. In UPSERT mode, if the specified record - * exists, it will be updated. If it does not exist, a new record will be created (optional). - */ - private Boolean upsert; } diff --git a/src/main/java/com/kintone/client/api/record/UpdateRecordsResponseBody.java b/src/main/java/com/kintone/client/api/record/UpdateRecordsResponseBody.java index 364335cc..2efc0b87 100644 --- a/src/main/java/com/kintone/client/api/record/UpdateRecordsResponseBody.java +++ b/src/main/java/com/kintone/client/api/record/UpdateRecordsResponseBody.java @@ -1,7 +1,7 @@ package com.kintone.client.api.record; import com.kintone.client.api.KintoneResponseBody; -import com.kintone.client.model.record.RecordUpdateResult; +import com.kintone.client.model.record.RecordRevision; import java.util.List; import lombok.Value; @@ -9,6 +9,6 @@ @Value public class UpdateRecordsResponseBody implements KintoneResponseBody { - /** A list of objects that include the record IDs, updated revisions, and operations. */ - private final List records; + /** A list of objects that include the record IDs and updated revisions. */ + private final List records; } diff --git a/src/main/java/com/kintone/client/api/record/UpsertRecordsRequest.java b/src/main/java/com/kintone/client/api/record/UpsertRecordsRequest.java new file mode 100644 index 00000000..6b8968a3 --- /dev/null +++ b/src/main/java/com/kintone/client/api/record/UpsertRecordsRequest.java @@ -0,0 +1,23 @@ +package com.kintone.client.api.record; + +import com.kintone.client.api.KintoneRequest; +import com.kintone.client.model.record.RecordForUpdate; +import java.util.List; +import lombok.Data; + +/** A request object for Upsert Records API. */ +@Data +public class UpsertRecordsRequest implements KintoneRequest { + + /** The App ID (required). */ + private Long app; + + /** A list of objects that include id/updateKey, revision and record objects (required). */ + private List records; + + /** + * If set to true, the UPSERT mode will be enabled. In UPSERT mode, if the specified record + * exists, it will be updated. If it does not exist, a new record will be created (optional). + */ + private final Boolean upsert = true; +} diff --git a/src/main/java/com/kintone/client/api/record/UpsertRecordsResponseBody.java b/src/main/java/com/kintone/client/api/record/UpsertRecordsResponseBody.java new file mode 100644 index 00000000..8a1ac313 --- /dev/null +++ b/src/main/java/com/kintone/client/api/record/UpsertRecordsResponseBody.java @@ -0,0 +1,14 @@ +package com.kintone.client.api.record; + +import com.kintone.client.api.KintoneResponseBody; +import com.kintone.client.model.record.RecordUpsertResult; +import java.util.List; +import lombok.Value; + +/** A response object for Upsert Records API. */ +@Value +public class UpsertRecordsResponseBody implements KintoneResponseBody { + + /** A list of objects that include the record IDs, updated revisions, and operations. */ + private final List records; +} diff --git a/src/main/java/com/kintone/client/model/record/RecordRevision.java b/src/main/java/com/kintone/client/model/record/RecordRevision.java index 92b562bd..b0cae6b9 100644 --- a/src/main/java/com/kintone/client/model/record/RecordRevision.java +++ b/src/main/java/com/kintone/client/model/record/RecordRevision.java @@ -2,7 +2,10 @@ import lombok.Value; -/** A value that contains the record ID and the revision, returned by Update Record Statuses API. */ +/** + * A value that contains the record ID and the revision, returned by Update Records API and Update + * Record Statuses API. + */ @Value public class RecordRevision { diff --git a/src/main/java/com/kintone/client/model/record/RecordUpdateResult.java b/src/main/java/com/kintone/client/model/record/RecordUpdateResult.java index f63a1564..fb4ca510 100644 --- a/src/main/java/com/kintone/client/model/record/RecordUpdateResult.java +++ b/src/main/java/com/kintone/client/model/record/RecordUpdateResult.java @@ -4,7 +4,7 @@ /** A value that contains the record ID, revision, and operation, returned by Update Records API. */ @Value -public class RecordUpdateResult { +public class RecordUpsertResult { /** The Record ID */ private final long id; diff --git a/src/test/java/com/kintone/client/RecordClientTest.java b/src/test/java/com/kintone/client/RecordClientTest.java index 7c268cf9..d46b6f9e 100644 --- a/src/test/java/com/kintone/client/RecordClientTest.java +++ b/src/test/java/com/kintone/client/RecordClientTest.java @@ -35,12 +35,15 @@ import com.kintone.client.api.record.UpdateRecordStatusesResponseBody; import com.kintone.client.api.record.UpdateRecordsRequest; import com.kintone.client.api.record.UpdateRecordsResponseBody; +import com.kintone.client.api.record.UpsertRecordsRequest; +import com.kintone.client.api.record.UpsertRecordsResponseBody; import com.kintone.client.model.Order; import com.kintone.client.model.record.Record; import com.kintone.client.model.record.RecordComment; import com.kintone.client.model.record.RecordForUpdate; import com.kintone.client.model.record.RecordOperationType; -import com.kintone.client.model.record.RecordUpdateResult; +import com.kintone.client.model.record.RecordRevision; +import com.kintone.client.model.record.RecordUpsertResult; import com.kintone.client.model.record.StatusAction; import com.kintone.client.model.record.UpdateKey; import java.util.Arrays; @@ -526,23 +529,15 @@ public void updateRecordAssignees_UpdateRecordAssigneesRequest() { public void updateRecords_long_List() { RecordForUpdate up1 = new RecordForUpdate(1L, new Record()); RecordForUpdate up2 = new RecordForUpdate(new UpdateKey("text", "test"), new Record()); - RecordUpdateResult result1 = new RecordUpdateResult(1, 2, RecordOperationType.UPDATE); - RecordUpdateResult result2 = new RecordUpdateResult(100, 2, RecordOperationType.INSERT); - mockClient.setResponseBody(new UpdateRecordsResponseBody(Arrays.asList(result1, result2))); + RecordRevision rev1 = new RecordRevision(1, 2); + RecordRevision rev2 = new RecordRevision(100, 2); + mockClient.setResponseBody(new UpdateRecordsResponseBody(Arrays.asList(rev1, rev2))); List records = Arrays.asList(up1, up2); - List result = sut.updateRecords(1, records); - assertThat(result).hasSize(2); - assertThat(result.get(0).getId()).isEqualTo(1); - assertThat(result.get(0).getRevision()).isEqualTo(2); - assertThat(result.get(0).getOperation()).isEqualTo(RecordOperationType.UPDATE); - assertThat(result.get(1).getId()).isEqualTo(100); - assertThat(result.get(1).getRevision()).isEqualTo(2); - assertThat(result.get(1).getOperation()).isEqualTo(RecordOperationType.INSERT); + assertThat(sut.updateRecords(1, records)).containsExactly(rev1, rev2); assertThat(mockClient.getLastApi()).isEqualTo(KintoneApi.UPDATE_RECORDS); assertThat(mockClient.getLastBody()).isInstanceOf(UpdateRecordsRequest.class); - UpdateRecordsRequest expected = - new UpdateRecordsRequest().setApp(1L).setRecords(records).setUpsert(false); + UpdateRecordsRequest expected = new UpdateRecordsRequest().setApp(1L).setRecords(records); assertThat(mockClient.getLastBody()).usingRecursiveComparison().isEqualTo(expected); } @@ -561,12 +556,12 @@ public void updateRecords_UpdateRecordsRequest() { public void upsertRecords_long_List() { RecordForUpdate up1 = new RecordForUpdate(1L, new Record()); RecordForUpdate up2 = new RecordForUpdate(new UpdateKey("text", "test"), new Record()); - RecordUpdateResult result1 = new RecordUpdateResult(1, 2, RecordOperationType.UPDATE); - RecordUpdateResult result2 = new RecordUpdateResult(100, 2, RecordOperationType.INSERT); - mockClient.setResponseBody(new UpdateRecordsResponseBody(Arrays.asList(result1, result2))); + RecordUpsertResult result1 = new RecordUpsertResult(1, 2, RecordOperationType.UPDATE); + RecordUpsertResult result2 = new RecordUpsertResult(100, 2, RecordOperationType.INSERT); + mockClient.setResponseBody(new UpsertRecordsResponseBody(Arrays.asList(result1, result2))); List records = Arrays.asList(up1, up2); - List result = sut.upsertRecords(1, records); + List result = sut.upsertRecords(1, records); assertThat(result).hasSize(2); assertThat(result.get(0).getId()).isEqualTo(1); assertThat(result.get(0).getRevision()).isEqualTo(2); @@ -574,13 +569,23 @@ public void upsertRecords_long_List() { assertThat(result.get(1).getId()).isEqualTo(100); assertThat(result.get(1).getRevision()).isEqualTo(2); assertThat(result.get(1).getOperation()).isEqualTo(RecordOperationType.INSERT); - assertThat(mockClient.getLastApi()).isEqualTo(KintoneApi.UPDATE_RECORDS); - assertThat(mockClient.getLastBody()).isInstanceOf(UpdateRecordsRequest.class); - UpdateRecordsRequest expected = - new UpdateRecordsRequest().setApp(1L).setRecords(records).setUpsert(true); + assertThat(mockClient.getLastApi()).isEqualTo(KintoneApi.UPSERT_RECORDS); + assertThat(mockClient.getLastBody()).isInstanceOf(UpsertRecordsRequest.class); + UpsertRecordsRequest expected = new UpsertRecordsRequest().setApp(1L).setRecords(records); assertThat(mockClient.getLastBody()).usingRecursiveComparison().isEqualTo(expected); } + @Test + public void upsertRecords_UpsertRecordsRequest() { + UpsertRecordsRequest req = new UpsertRecordsRequest(); + UpsertRecordsResponseBody resp = new UpsertRecordsResponseBody(Collections.emptyList()); + mockClient.setResponseBody(resp); + + assertThat(sut.upsertRecords(req)).isEqualTo(resp); + assertThat(mockClient.getLastApi()).isEqualTo(KintoneApi.UPSERT_RECORDS); + assertThat(mockClient.getLastBody()).isEqualTo(req); + } + @Test public void updateRecordStatus_long_long_String() { mockClient.setResponseBody(new UpdateRecordStatusResponseBody(10L)); From 5cb96079cef73e1a5813b6be26a0e5b3281a18b7 Mon Sep 17 00:00:00 2001 From: nameless-mc Date: Thu, 27 Nov 2025 15:36:19 +0900 Subject: [PATCH 5/6] refactor: format --- .../com/kintone/client/api/record/UpsertRecordsRequest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/kintone/client/api/record/UpsertRecordsRequest.java b/src/main/java/com/kintone/client/api/record/UpsertRecordsRequest.java index 6b8968a3..0a42691f 100644 --- a/src/main/java/com/kintone/client/api/record/UpsertRecordsRequest.java +++ b/src/main/java/com/kintone/client/api/record/UpsertRecordsRequest.java @@ -15,7 +15,7 @@ public class UpsertRecordsRequest implements KintoneRequest { /** A list of objects that include id/updateKey, revision and record objects (required). */ private List records; - /** + /** * If set to true, the UPSERT mode will be enabled. In UPSERT mode, if the specified record * exists, it will be updated. If it does not exist, a new record will be created (optional). */ From 35d2d25dfc5c6c232b4e73c7e99280a3eb970ed5 Mon Sep 17 00:00:00 2001 From: nameless-mc Date: Thu, 27 Nov 2025 16:31:48 +0900 Subject: [PATCH 6/6] refactor: rename file --- .../record/{RecordUpdateResult.java => RecordUpsertResult.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/main/java/com/kintone/client/model/record/{RecordUpdateResult.java => RecordUpsertResult.java} (93%) diff --git a/src/main/java/com/kintone/client/model/record/RecordUpdateResult.java b/src/main/java/com/kintone/client/model/record/RecordUpsertResult.java similarity index 93% rename from src/main/java/com/kintone/client/model/record/RecordUpdateResult.java rename to src/main/java/com/kintone/client/model/record/RecordUpsertResult.java index fb4ca510..fd848ff4 100644 --- a/src/main/java/com/kintone/client/model/record/RecordUpdateResult.java +++ b/src/main/java/com/kintone/client/model/record/RecordUpsertResult.java @@ -2,7 +2,7 @@ import lombok.Value; -/** A value that contains the record ID, revision, and operation, returned by Update Records API. */ +/** A value that contains the record ID, revision, and operation, returned by Upsert Records API. */ @Value public class RecordUpsertResult {