はじめに
前回までのブログでSalesforceのBig Objectの特徴や作成方法、Big Objectで使用できるSOQLについてご紹介いたしました。
今回はBig ObjectをApexクラスで扱う方法や注意点などをご紹介したいと思います。
Big Objectとは何?というところから知りたい方や、Big Objectの作成方法を確認したい方、
Big ObjectをSOQLで取得する方法を知りたい方は前回までのブログをご参照ください。
SalesforceにおけるBig Objectの特徴
SalesforceにおけるBig Objectの定義・作成
SalesforceにおけるBig ObjectのSOQLクエリについて
Big Objectのデータ取得
普通のオブジェクトと同じようにSOQLをApexコードに記載して取得可能です。
サンプルコード:SOQLによるBig Objectレコードの取得
Contact c = [SELECT Id FROM Contact WHERE Name = 'Barr Tim' LIMIT 1];
Id contactId = c.Id;
Purchase_History__b ph = [SELECT Id, Contact__c, Product_Code__c, Purchase_DateTime__c,
Payment_Date__c, Payment_Method__c, Quantity__c, Unit_Price__c
FROM Purchase_History__b
WHERE Contact__c = :contactId
AND Product_Code__c = '000001'
LIMIT 1];
System.debug('取得したBig Objectの情報:Product_Code__c = ' + ph.Product_Code__c + ':');
動的SOQLも使用できます。
サンプルコード:動的SOQLによるBig Objectレコードの取得
Contact c = [SELECT Id FROM Contact WHERE Name = 'Barr Tim' LIMIT 1];
String contactId = c.Id;
String productCode = '000001';
String query = 'SELECT Id, Contact__c, Product_Code__c, Purchase_DateTime__c, ';
query += 'Payment_Date__c, Payment_Method__c, Quantity__c, Unit_Price__c ';
query += 'FROM Purchase_History__b ';
query += 'WHERE Contact__c = :contactId AND Product_Code__c = :productCode ';
query += 'LIMIT 1';
Purchase_History__b ph = Database.query(query);
System.debug('取得したBig Objectの情報:Product_Code__c = ' + ph.Product_Code__c + ':');
Big Objectのデータ登録・更新
Big Objectのデータ登録や更新にはinsertImmediateを使用します。
サンプルコード:Big Objectのデータ登録
Contact c = [SELECT Id FROM Contact WHERE Name = 'Barr Tim' LIMIT 1];
Purchase_History__b ph = new Purchase_History__b();
ph.Contact__c = c.Id;
ph.Product_Code__c = '000002';
ph.Purchase_DateTime__c = Datetime.newInstance(2022, 4, 1);
Database.SaveResult sr = database.insertImmediate(ph);
insertImmediateはレコード単位でDatabase.SaveResultクラスを返却します。
そのためレコード単位でエラー検知が可能です。
インデックス項目に登録されているBig Objectレコードと同じ値を設定してinsertImmediateを行うと、設定したインデックス項目の値に対応するレコードを更新できます。
(insertImmediateは実質upsertの処理となります。)
サンプルコード:Big Objectのデータ更新
Contact c = [SELECT Id FROM Contact WHERE Name = 'Barr Tim' LIMIT 1];
Purchase_History__b ph = new Purchase_History__b();
ph.Contact__c = c.Id;
ph.Product_Code__c = '000002';
ph.Purchase_DateTime__c = Datetime.newInstance(2022, 4, 1);
ph.Payment_Date__c = Datetime.newInstance(2022, 4, 1);
ph.Payment_Method__c = 'クレジットカード決済';
ph.Quantity__c = 1;
ph.Unit_Price__c = 100000;
Database.SaveResult sr = database.insertImmediate(ph);
※insertやupdateのDML操作の場合と違って、以下のような記載ではinsertImmediateを行うことはできません。
サンプルコード:失敗するinsertImmediate
insertImmediate ph;
Big Objectのデータ削除
データを削除する際はdeleteImmediateを使用します。
サンプルコード:Big Objectのデータ削除
Contact c = [SELECT Id FROM Contact WHERE Name = 'Barr Tim' LIMIT 1];
Id contactId = c.Id;
Datetime dt = Datetime.newInstance(2022, 4, 1);
Purchase_History__b ph = [SELECT Contact__c, Product_Code__c, Purchase_DateTime__c
FROM Purchase_History__b
WHERE Contact__c = :contactId
AND Product_Code__c = '000002'
AND Purchase_DateTime__c = :dt
LIMIT 1];
Database.DeleteResult dr = database.deleteImmediate(ph);
削除するデータを指定する際インデックス項目以外の項目が設定されていると、
以下のようなエラーが発生するため注意が必要です。
deleteImmediateはレコード単位でDatabase.DeleteResultクラスを返却します。
insertImmediateと同様にdeleteImmediateもレコード単位のエラー検知が可能です。
またdeleteImmediateもinsertImmediateと同様以下のような記載で削除を行うことはできません。
サンプルコード:失敗するdeleteImmediate
deleteImmediate ph;
ApexクラスでBig Objectを使用する際の注意点
insertImmediateやdeleteImmediateでBig Objectのレコードを扱う際、ロールバック処理を使用できません。
insertImmediateやdeleteImmediateを行うとその時点でトランザクションが確定し、対象のレコードに対する操作が完了します。
そのためロールバック処理を行おうとするとエラーとなります。
(ちなみにImmediateは「即時」の意味を持っています。)
サンプルコード:insertImmediateの後にrollbackをするとエラーとなる
Savepoint sp = Database.setSavepoint();
Contact c = [SELECT Id FROM Contact WHERE Name = 'Barr Tim' LIMIT 1];
Purchase_History__b ph = new Purchase_History__b();
ph.Contact__c = c.Id;
ph.Product_Code__c = '000003';
ph.Purchase_DateTime__c = Datetime.newInstance(2022, 5, 1);
Database.SaveResult sr = Database.insertImmediate(ph);
Database.rollback(sp);
エラー発生前にトランザクションが確定しているので、insertImmediateしたレコードは登録されています。
同じトランザクションでinsertとBig ObjectのinsertImmediateを同時に行うことはできません。
サンプルコード:insertと同じトランザクションでinsertImmediateはできない
Account acc = new Account();
acc.Name = 'テスト取引先_001';
Contact c = [SELECT Id FROM Contact WHERE Name = 'Barr Tim' LIMIT 1];
Id contactId = c.Id;
Purchase_History__b ph = new Purchase_History__b();
ph.Contact__c = c.Id;
ph.Product_Code__c = '000004';
ph.Purchase_DateTime__c = Datetime.newInstance(2022, 5, 1);
ph.Payment_Date__c = Datetime.newInstance(2022, 5, 1);
ph.Payment_Method__c = 'クレジット決済';
ph.Quantity__c = 20;
ph.Unit_Price__c = 100;
insert acc;
Database.SaveResult sr = database.insertImmediate(ph);
以下のinsertImmediateは成功します。
サンプルコード:insertImmediateが終わってからinsertは可能
Account acc = new Account();
acc.Name = 'テスト取引先_001';
Contact c = [SELECT Id FROM Contact WHERE Name = 'Barr Tim' LIMIT 1];
Id contactId = c.Id;
Purchase_History__b ph = new Purchase_History__b();
ph.Contact__c = c.Id;
ph.Product_Code__c = '000004';
ph.Purchase_DateTime__c = Datetime.newInstance(2022, 5, 1);
ph.Payment_Date__c = Datetime.newInstance(2022, 5, 1);
ph.Payment_Method__c = 'クレジット決済';
ph.Quantity__c = 20;
ph.Unit_Price__c = 100;
Database.SaveResult sr = database.insertImmediate(ph);
insert acc;
updateやupsert,deleteについてもBig ObjectのinsertImmediateを同時に行うことはできません。
サンプルコード:updateと同じトランザクションでinsertImmediateはできない
Account acc = [SELECT Id, Name FROM Account WHERE Name = 'テスト取引先_001' LIMIT 1];
acc.Name = 'テスト取引先_002';
Contact c = [SELECT Id FROM Contact WHERE Name = 'Barr Tim' LIMIT 1];
Id contactId = c.Id;
Purchase_History__b ph = new Purchase_History__b();
ph.Contact__c = c.Id;
ph.Product_Code__c = '000004';
ph.Purchase_DateTime__c = Datetime.newInstance(2022, 5, 1);
ph.Payment_Date__c = Datetime.newInstance(2022, 5, 1);
ph.Payment_Method__c = 'クレジット決済';
ph.Quantity__c = 30;
ph.Unit_Price__c = 200;
update acc;
Database.SaveResult sr = database.insertImmediate(ph);
サンプルコード:upsertと同じトランザクションでinsertImmediateはできない
Account acc = new Account();
acc.Name = 'テスト取引先_003';
Contact c = [SELECT Id FROM Contact WHERE Name = 'Barr Tim' LIMIT 1];
Id contactId = c.Id;
Purchase_History__b ph = new Purchase_History__b();
ph.Contact__c = c.Id;
ph.Product_Code__c = '000005';
ph.Purchase_DateTime__c = Datetime.newInstance(2022, 5, 1);
ph.Payment_Date__c = Datetime.newInstance(2022, 5, 1);
ph.Payment_Method__c = 'クレジット決済';
ph.Quantity__c = 20;
ph.Unit_Price__c = 100;
upsert acc;
Database.SaveResult sr = database.insertImmediate(ph);
サンプルコード:deleteと同じトランザクションでinsertImmediateはできない
Account acc = [SELECT Id FROM Account WHERE Name = 'テスト取引先_001' LIMIT 1];
Contact c = [SELECT Id FROM Contact WHERE Name = 'Barr Tim' LIMIT 1];
Id contactId = c.Id;
Purchase_History__b ph = new Purchase_History__b();
ph.Contact__c = c.Id;
ph.Product_Code__c = '000004';
ph.Purchase_DateTime__c = Datetime.newInstance(2022, 5, 1);
ph.Payment_Date__c = Datetime.newInstance(2022, 5, 1);
ph.Payment_Method__c = 'クレジット決済';
ph.Quantity__c = 40;
ph.Unit_Price__c = 300;
delete acc;
Database.SaveResult sr = database.insertImmediate(ph);
同様の理由ででinsertとBig ObjectのdeleteImmediateを同時に行うことはできません。
サンプルコード:insertと同じトランザクションでdeleteImmediateはできない
Account acc = new Account();
acc.Name = 'テスト取引先_001';
Contact c = [SELECT Id FROM Contact WHERE Name = 'Barr Tim' LIMIT 1];
Id contactId = c.Id;
Datetime dt = Datetime.newInstance(2022, 5, 1);
Purchase_History__b ph = [SELECT Contact__c, Product_Code__c, Purchase_DateTime__c
FROM Purchase_History__b
WHERE Contact__c = :contactId
AND Product_Code__c = '000004'
AND Purchase_DateTime__c = :dt
LIMIT 1];
insert acc;
Database.DeleteResult dr = database.deleteImmediate(ph);
サンプルコードは省きますが、updateやupsert,deleteについてもBig ObjectのdeleteImmediateを同時に行うことはできません。
Big Objectと標準オブジェクト、カスタムオブジェクトについて同時に操作したい場合は気を付ける必要があります。
Big Objectの項目に参照項目がある場合は特に関連レコードの操作を行いたい場面があると思いますので注意が必要です。
最後に
ここまで記事を読んでいただきありがとうございます。
今回の記事ではBig ObjectをApexクラスで扱う方法や注意点について説明いたしました。
次回の記事ではBig Objectでできること・できないことについてまとめていきたいと思います。