一、批量操作
批量操作包括批量创建与批量更新。批量操作的提交类型系统默认值为batchCommit。
批量提交类型:
- useAffectRows,循环单次单条脚本提交,返回实际影响行数
- useAndJudgeAffectRows,循环单次单条脚本提交,返回实际影响行数,若实际影响行数与输入不一致,抛出异常
- collectionCommit,将多个单条更新脚本拼接成一个脚本提交,不能返回实际影响行数
- batchCommit,使用单条更新脚本批量提交,不能返回实际影响行数。
全局配置
pamirs:
mapper:
batch: batchCommit
图4-1-5-1 全局配置
运行时配置
非乐观锁模型系统默认采用batchCommit提交更新操作;乐观锁模型默认采用useAndJudgeAffectRows提交更新操作。也可以使用以下方式在运行时改变批量提交方式。
Spider.getDefaultExtension(BatchApi.class).run(() -> {
更新逻辑
}, 批量提交类型枚举);
图4-1-5-2 运行时配置
运行时校正
如果模型配置了数据库自增主键,而批量新增的批量提交类型为batchCommit,则系统将批量提交类型变更为collectionCommit(如果使用batchCommit,则需要单条提交以获得正确的主键返回值,性能有所损失)。
如果模型配置了乐观锁,而批量更新的批量提交类型为collectionCommit或者batchCommit,则系统将批量提交类型变更为useAndJudgeAffectRows。也可以失效乐观锁,让系统不做批量提交类型变更处理。
二、乐观锁(举例)
在一些会碰到并发修改的数据,往往需要进行并发控制,一般数据库层面有两种一种是悲观锁、一种是乐观锁。oinone对乐观锁进行了良好支持
定义方式
乐观锁的两种定义方式:
-
通过快捷继承VersionModel,构建带有乐观锁,唯一编码code且主键为id的模型。
-
可以在字段上使用@Field.Version注解来标识该模型更新数据时使用乐观锁
如果更新的实际影响行数与入参数量不一致,则会抛出异常,错误码为10150024。如果是批量更新数据,为了返回准确的实际影响行数,批量更新由批量提交改为循环单条数据提交更新,性能有所损失。
失效乐观锁
一个模型在某些场景下需要使用乐观锁来更新数据,而另一些场景不需要使用乐观锁来更新数据,则可以使用以下方式在一些场景下失效乐观锁。更多元位指令用法详见4.1.9【函数之元位指令】一文。
PamirsSession.directive().disableOptimisticLocker();
try{
更新逻辑
} finally {
PamirsSession.directive().enableOptimisticLocker();
}
图4-1-5-3 失效乐观锁
不抛乐观锁异常
将批量提交类型设置为useAffectRows即可,这样可改由外层逻辑对返回的实际影响行数进行自主判断。
Spider.getDefaultExtension(BatchApi.class).run(() -> {
更新逻辑,返回实际影响行数
}, BatchCommitTypeEnum.useAffectRows);
图4-1-5-4 将批量提交类型设置为useAffectRows
构建第一个VersionModel
Step1 新建PetItemInventroy模型,继承快捷模型VersionModel
package pro.shushi.pamirs.demo.api.model;
import pro.shushi.pamirs.meta.annotation.Field;
import pro.shushi.pamirs.meta.annotation.Model;
import pro.shushi.pamirs.meta.base.common.VersionModel;
import java.math.BigDecimal;
@Model.model(PetItemInventroy.MODEL_MODEL)
@Model(displayName = "宠物商品库存",summary="宠物商品库存",labelFields = {"itemName"})
public class PetItemInventroy extends VersionModel {
public static final String MODEL_MODEL="demo.PetItemInventroy";
@Field(displayName = "商品名称")
private String itemName;
@Field(displayName = "库存数量")
private BigDecimal quantity;
}
图4-1-5-5 新建PetItemInventroy模型
Step2 修改DemoMenu,增加访问入口
@UxMenu("商品库存")@UxRoute(PetItemInventroy.MODEL_MODEL) class PetItemInventroyMenu{}
图4-1-5-6 修改DemoMenu
Step3 重启看效果
体验一:页面上新增、修改数据库字段中的opt_version会自动加一
图4-1-5-7 示例效果一
图4-1-5-8 示例效果二
图4-1-5-9 示例效果三
图4-1-5-10 示例效果四
体验二:同时打两个页面,依次点击,您会发现一个改成功,一个没有改成功。但页面都没有报错,只是update返回影响行数一个为1,另一个为0而已。
图4-1-5-11 编辑宠物商品库存
图4-1-5-12 宠物商品库存列表
注:增加了乐观锁,我们在写代码的时候一定要注意,单记录更新操作的时候要去判断返回结果(影响行数),不然没改成功,程序是不会抛错的。不像batch接口默认会报错
Step4 预留任务:重写PetItemInventroy的update函数
留个任务,请各位小伙伴自行测试玩玩,这样会更有体感
package pro.shushi.pamirs.demo.core.action;
import org.springframework.stereotype.Component;
import pro.shushi.pamirs.demo.api.enumeration.DemoExpEnumerate;
import pro.shushi.pamirs.demo.api.model.PetItemInventroy;
import pro.shushi.pamirs.demo.api.model.PetTalent;
import pro.shushi.pamirs.meta.annotation.Function;
import pro.shushi.pamirs.meta.annotation.Model;
import pro.shushi.pamirs.meta.common.exception.PamirsException;
import pro.shushi.pamirs.meta.constant.FunctionConstants;
import pro.shushi.pamirs.meta.enmu.FunctionOpenEnum;
import pro.shushi.pamirs.meta.enmu.FunctionTypeEnum;
import java.util.ArrayList;
import java.util.List;
@Model.model(PetItemInventroy.MODEL_MODEL)
@Component
public class PetItemInventroyAction {
@Function.Advanced(type= FunctionTypeEnum.UPDATE)
@Function.fun(FunctionConstants.update)
@Function(openLevel = {FunctionOpenEnum.API})
public PetItemInventroy update(PetItemInventroy data){
List<PetItemInventroy> inventroys = new ArrayList<>();
inventroys.add(data);
//批量更新会,自动抛错
int i = data.updateBatch(inventroys);
//单记录更新,不自动抛售需要自行判断
// int i = data.updateById();
// if(i!=1){
// throw PamirsException.construct(DemoExpEnumerate.PET_ITEM_INVENTROY_UPDATE_VERSION_ERROR).errThrow();
// }
return data;
}
}
图4-1-5-13 重写PetItemInventroy的update函数
注意事项:
如果是自定义页面需要把optVersion字段配置到视图的xml中去,可以配置为隐藏 。例子中因为默认页面已经自动带上了optVersion,所以容易被人忽视掉。
Oinone社区 作者:史, 昂原创文章,如若转载,请注明出处:https://doc.oinone.top/oio4/9280.html
访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验