zoukankan      html  css  js  c++  java
  • Salesforce LWC学习(三十八) lwc下如何更新超过1万的数据

    背景: 今天项目组小伙伴问了一个问题,如果更新数据超过1万条的情况下,有什么好的方式来实现呢?我们都知道一个transaction只能做10000条DML数据操作,那客户的操作的数据就是超过10000条的情况下,我们就只能搬出来salesforce government limitation进行拒绝吗?这显然也是不友好的行为。

    实现方案: 

    1. 代码中调用batch,batch处理的数据量多,从而可以忽略这个问题。当然,这种缺点很明显:

      1)不是实时的操作,什么时候执行取决于系统的可用线程,什么执行不知道;

      2)如果batch数据中有报错情况下,我们应该如何处理呢?全部回滚?继续操作?可能不同的业务不同的场景,哪样都不太理想。所以batch这种方案不到万不得已,基本不要考虑。

    2. 前端进行分批操作,既然每一个transaction有限制,我们就将数据进行分拆操作,比如每2000或者其他的数量作为一批操作,然后进行后台交互,这样我们可以实时的获取状态,一批数据处理完成以后,我们在进行另外一批。正好博客中貌似没有记录这种的需求,所以整理一篇,js能力有限,抛砖引玉,欢迎小伙伴多多的交流沟通。

    TestObjectController.cls: 获取数据,以及更新数据两个简单方法

    public with sharing class TestObjectController {
        @AuraEnabled(cacheable=true)
        public static List<Test_Object__c> getTestObjectList() {
            List<Test_Object__c> testObjectList = [SELECT Id,Name 
                    from Test_Object__c
                    ORDER BY CREATEDDATE limit 50000];
            return testObjectList;
        }
    
        @AuraEnabled
        public static Boolean updateTestObjectList(List<Id> testObjectIdList) {
            List<Test_Object__c> testObjectList = new List<Test_Object__c>();
            for(Id testObjectId : testObjectIdList) {
                Test_Object__c objItem = new Test_Object__c();
                objItem.Id = testObjectId;
                objItem.Active__c = true;
                testObjectList.add(objItem);
            }
            update testObjectList;
            return true;
        }
    }

    testLargeDataOperationComponent.html

    <template>
        <lightning-button label="mass update" onclick={handleMassUpdateAction}></lightning-button>
        <template if:true={isExecution}>
            <lightning-spinner size="large"  alternative-text="operation in progress"></lightning-spinner>
        </template>
        <div style="height: 600px;">
            <lightning-datatable 
                hide-checkbox-column
                key-field="Id"
                data={testObjectList}
                columns={columns}>
            </lightning-datatable>
        </div>
    </template>

    testLargeDataOperationComponent.js:因为测试环境的数据有 data storage 5M的限制,所以数据达不到1万条,这里将每批处理的数据进行设置小一点点,打开log,从而更好的查看展示效果。

    import { LightningElement, track, wire,api } from 'lwc';
    import getTestObjectList from '@salesforce/apex/TestObjectController.getTestObjectList';
    import updateTestObjectList from '@salesforce/apex/TestObjectController.updateTestObjectList';
    import { ShowToastEvent } from 'lightning/platformShowToastEvent';
    const columns = [
        {label: 'Name', fieldName: 'Name',editable:false}
    ];
    export default class testLargeDataOperationComponent extends LightningElement {
        @track testObjectList = [];
        @track columns = columns;
        @track isExecution = false;
        @wire(getTestObjectList)
        wiredTestObjectList({data, error}) {
            if(data) {
                this.testObjectList = data;
            } else if(error) {
                console.log(JSON.stringify(error));
            }
        }
    
    
        async handleMassUpdateAction() {
            let listSize = this.testObjectList.length;
            let allOperateSuccess = false;
            this.isExecution = true;
            //hard code, default operate 1000 per transcation
            let offset = 200;
            let idList = [];
            for(let index = 0; index < listSize; index ++) {
                idList.push(this.testObjectList[index].Id);
                if(index === listSize - 1) {
                    console.log('*** index : ' + index);
                    const finalResult = await updateTestObjectList({testObjectIdList: idList});
                    if(finalResult) {
                        this.isExecution = false;
                        this.dispatchEvent(
                            new ShowToastEvent({
                                title: 'operation successed',
                                message: 'the records are all updated success, size : '+ listSize,
                                variant: 'success'
                            })
                        );
                        idList = [];
                    }
                } else if(index % offset == (offset -1)){
                    console.log('---index : ' + index);
                    const processResult = await updateTestObjectList({testObjectIdList: idList});
                    if(processResult) {
                        idList = [];
                    } else {
                        this.dispatchEvent(
                            new ShowToastEvent({
                                title: 'failed',
                                message: 'operation failed',
                                variant: 'error'
                            })
                        );
                        this.isExecution = false;
                        break;
                    }
                }
            }
        }
    }

    效果展示

    1. 初始化数据2000条,状态都是false

    2. 当点击按钮时,展示spinner,同时每200条数据准备好会在后台进行一次数据操作,结果返回以后,在进行前端的整理,周而复始,一个说不上递归的数据操作。

     当全部完成以后,展示成功toast信息

     这样操作就可以实现超过10000条情况下,也可以进行同步的更新操作了。当然,这个现在只是一个初版,有没有什么问题呢?肯定有,比如在执行某200条数据错误的情况下,如何所有的数据进行回滚呢?如何记录已有的已经操作的数据呢?我们的后台返回类型可能就不是一个布尔类型可以搞定的了,有可能需要一个wrapper去封装一下曾经操作过的数据的ID,如果真的有错误情况下,调用其他的方法进行数据回滚操作(业务上回滚,而不是 savePoint rollback操作,此种实现不了)。

    总结:相信不同的老司机对这种需求处理方式会有不同,本篇抛砖引玉,欢迎大神们交流以及给更好的建议意见。篇中错误地方欢迎指出,有不懂欢迎留言。

    作者:zero

    博客地址:http://www.cnblogs.com/zero-zyq/

    本文欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接

    个人下载了一些相关学习的PDF文件,如果需要下载请访问百度云 点击此处访问 密码:jhuy

    如果文章的内容对你有帮助,欢迎点赞~

    为方便手机端查看博客,现正在将博客迁移至微信公众号:Salesforce零基础学习,欢迎各位关注。

  • 相关阅读:
    MySQL 数据库入门操作
    select count(*)和select count(1)
    Oracle instr 及 like
    myeclipse添加svn
    Lanucherr 默认显示第几屏
    【毕设】班级管理系统——易搜
    【毕设】班级管理系统——找回密码模块
    【毕设】班级管理系统——登录模块
    【毕设】班级管理系统——系统介绍
    快速生成扇形图
  • 原文地址:https://www.cnblogs.com/zero-zyq/p/15751009.html
Copyright © 2011-2022 走看看