自定义createorupdate方法时,关联模型数据怎么保存?

需要自己手动增加保存关联模型数据的逻辑。

  • 多对一、一对一以及一对多

可直接用fieldSave进行保存即可

//如 data.fieldSave(PamirsEmployee::getPositions);
  • 多对多

需要对数据进行处理,前端提交过来的数据,进行判断,是新增还是修改,或者删除

Oinone社区 作者:oinone原创文章,如若转载,请注明出处:https://doc.oinone.top/backend/6.html

访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验

(0)
oinone的头像oinone
上一篇 2023年6月20日 pm4:07
下一篇 2023年11月2日 pm1:58

相关推荐

  • 自定义用户中心菜单

    使用扩展点实现用户中心菜单替换 1. 工程中引起pamirs-user-api <dependency> <groupId>pro.shushi.pamirs.core</groupId> <artifactId>pamirs-user-api</artifactId> </dependency> 2. 实现TopBarUserBlockAction的后置扩展 实现HookAfter后置扩展接口 @Hook(model = {TopBarUserBlock.MODEL_MODEL}, fun = {"construct"})添加Hook注解注明是TopBarUserBlock模型的construct函数的后置扩展。 增加用户中心菜单 @Component @Order(1) @SPI.Service public class MyTopBarActionExt implements TopBarActionExtendApi { public void edit(List<TopBarAction> list) { list.add(new TopBarAction("top_demo", "top.Teacher", "uiView9a0caf1d574a42c9847a057a0c4a4ad1", ActionTypeEnum.VIEW, 1) .setDisplayName("商品管理") .setIcon("oinone-gongzuotai") ); } } 实现效果 替换原有的用户中心菜单 替换原有的菜单跳转 @Component public class DemoTopBarUserBlockDataHookAfter implements HookAfter { @Override @Hook(model = {TopBarUserBlock.MODEL_MODEL}, fun = {"construct"}) public Object run(Function function, Object ret) { if (ret == null) { return null; } TopBarUserBlock result = null; if (ret instanceof Object[]) { Object[] rets = (Object[]) ((Object[]) ret); if (rets.length == 1) { result = (TopBarUserBlock) rets[0]; //例:替换用户中心:修改密码菜单 //使用name和model查询出模型的ViewAction替换修改密码ViewAction ViewAction demoViewAction = PamirsSession.getContext().getExtendCache(ActionCacheApi.class).get(Dog.MODEL_MODEL, "changePassword"); //设置菜单的icon Map<String, Object> attributes = Optional.ofNullable(demoViewAction.getAttributes()).orElse(new HashMap<>()); attributes.put("icon", "oinone-xiugaimima"); demoViewAction.setAttributes(attributes); //UserViewAction第0个是修改密码ViewAction,使用自定义的ViewAction就可以实现替换 result.getUserViewAction().set(0, demoViewAction); } } else { result = (TopBarUserBlock) ret; } return result; } } 使用@UxRouteButton方式新增ViewAction,更多新增Action方式详见:Action的类型 @Model.model(Dog.MODEL_MODEL) @Component @UxRouteButton( action = @UxAction(name = "changePassword", displayName = "修改密码"), value = @UxRoute(model = Dog.MODEL_MODEL, openType = ActionTargetEnum.DIALOG)) public class DogAction { } 替换原有的个人设置头像跳转 修改点击头像绑定的跳转逻辑 @Order(10) @Component @SPI.Service public class DemoTopBarUserBlockDataApi implements TopBarUserBlockDataApi { @Override public TopBarUserBlock extendData(TopBarUserBlock data) { //例如增加一个菜单, PamirsDemo.MODEL_MODEL: 模型。 MenuuiMenu31f22466735a4abe8e0544b428ed88ac:viewAction的name。 Action demoViewAction =…

    2024年7月4日
    1.4K00
  • Oinone请求路由源码分析

    通过源码分析,从页面发起请求,如果通过graphQL传输到具体action的链路,并且在这之间做了哪些隐式处理分析源码版本5.1.x 请求流程大致如下: 拦截所有指定的请求 组装成graphQL请求信息 调用graphQL执行 通过hook拦截先执行 RsqlDecodeHook:rsql解密 UserHook: 获取用户信息, 通过cookies获取用户ID,再查表获取用户信息,放到本地Local线程里 RoleHook: 角色Hook FunctionPermissionHook: 函数权限Hook ,跳过权限拦截的实现放在这一层,对应的配置 pamirs: auth: fun-filter: – namespace: user.PamirsUserTransient fun: login #登录 – namespace: top.PetShop fun: action DataPermissionHook: 数据权限hook PlaceHolderHook:占位符转化替换hook RsqlParseHook: 解释Rsql hook SingletonModelUpdateHookBefore 执行post具体内容 通过hook拦截后执行 QueryPageHook4TreeAfter: 树形Parent查询优化 FieldPermissionHook: 字段权限Hook UserQueryPageHookAfter UserQueryOneHookAfter 封装执行结果信息返回 时序图 核心源码解析 拦截所有指定的请求 /pamirs/模块名RequestController @RequestMapping( value = "/pamirs/{moduleName:^[a-zA-Z][a-zA-Z0-9_]+[a-zA-Z0-9]$}", method = RequestMethod.POST ) public String pamirsPost(@PathVariable("moduleName") String moduleName, @RequestBody PamirsClientRequestParam gql, HttpServletRequest request, HttpServletResponse response) { } DefaultRequestExecutor 构建graph请求信息,并调用graph请求 () -> execute(GraphQL::execute, param), param private <T> T execute(BiFunction<GraphQL, ExecutionInput, T> executor, PamirsRequestParam param) { // 获取GraphQL请求信息,包含grapsh schema GraphQL graphQL = buildGraphQL(param); … ExecutionInput executionInput = ExecutionInput.newExecutionInput() .query(param.getQuery()) .variables(param.getVariables().getVariables()) .dataLoaderRegistry(Spider.getDefaultExtension(DataLoaderRegistryApi.class).dataLoader()) .build(); … // 调用 GraphQL的方法execute 执行 T result = executor.apply(graphQL, executionInput); … return result; } QueryAndMutationBinder 绑定graphQL读取写入操作 public static DataFetcher<?> dataFetcher(Function function, ModelConfig modelConfig) { if (isAsync()) { if (FunctionTypeEnum.QUERY.in(function.getType())) { return AsyncDataFetcher.async(dataFetchingEnvironment -> dataFetcherAction(function, modelConfig, dataFetchingEnvironment), ExecutorServiceApi.getExecutorService()); } else { return dataFetchingEnvironment -> dataFetcherAction(function, modelConfig, dataFetchingEnvironment); } } else { return dataFetchingEnvironment -> dataFetcherAction(function, modelConfig, dataFetchingEnvironment); } } private static Object dataFetcherAction(Function function, ModelConfig modelConfig, DataFetchingEnvironment environment) { try { SessionExtendUtils.tagMainRequest(); // 使用共享的请求和响应对象 return Spider.getDefaultExtension(ActionBinderApi.class) .action(modelConfig,…

    2024年8月21日
    5.4K02
  • docker status exited(255)

    虚拟机异常退出再启动后,docker run 出现错误: 查看所有容器发现确实存在一个容器,status是 exited(255) docker container ls -all 删除这个容器,命令 docker run 容器id docker rm 56e0  

    2024年11月23日
    73100
  • 工作流引入流程概览与流程监控

    流程概览依赖说明 使用 流程概览 功能前,需要在项目中引入 pamirs-workflow-datavi-core、 pamirs-data-visualization-core依赖,并启动datavi模块: <dependency> <groupId>pro.shushi.pamirs.workflow</groupId> <artifactId>pamirs-workflow-datavi-core</artifactId> </dependency> <dependency> <groupId>pro.shushi.pamirs.data.visualization</groupId> <artifactId>pamirs-data-visualization-core</artifactId> </dependency> 警告: 在 oinone 平台启用「流程概览」能力时,应用启动模块一旦引入 pamirs-workflow-api/core,必须同时引入 pamirs-workflow-datavi-api/core。在多启动模块架构下,严禁出现仅部分启动模块引入 pamirs-workflow-core 而未引入 pamirs-workflow-datavi-core 的情况,否则将导致流程概览相关元数据计算异常,出现删表等情况。 流程概览配置项 流程概览页面内置缓存机制,可通过配置项调整缓存刷新周期及图表展示的数据条数: pamirs: workflow: dashboard: cache-time: 10 # 流程概览缓存刷新时间(单位:分钟),默认 10 分钟 page-size: 10 # 流程运行分析中 4 个图表的展示数量,默认查询前 10 条数据 统计指标说明 引入 pamirs-workflow-datavi-core 依赖后,系统会按照以下规则进行数据同步: 当日数据同步:每小时同步一次当日数据; 昨日数据同步:次日凌晨同步前一日数据。 由于在引入依赖后才会开始执行数据同步,统计指标页提供了「同步」按钮,可用于对历史数据进行补采。即使不执行历史同步,也不会影响核心业务流程,仅会影响统计数据和图表的展示效果。 统计指标数据主要用于 支撑 流程概览 和 流程监控 中的统计图表展示; 为数据分析与可视化提供基础数据。 上述统计数据对工作流的审批、流转等核心业务无任何影响。如有需要,也可以基于流程监控的数据,配合数据可视化设计器,自定义构建符合业务需求的展示页面。

    2025年11月17日
    11800
  • 自定义数据权限拦截处理

    业务场景 公司给员工对哪些模块有访问权限,这个时候就需要在员工访问模块表的时候做数据过滤, 解决方案 我们可以通过平台提供的数据过滤占位符解决这个问题,新建一条数据行权限,过滤语句条件是占位符,再编写占位符的解析逻辑 1.初始化权限基础数据 package pro.shushi.pamirs.demo.core.init; import com.google.common.collect.Lists; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import pro.shushi.pamirs.auth.api.constants.AuthConstants; import pro.shushi.pamirs.auth.api.enmu.AuthGroupTypeEnum; import pro.shushi.pamirs.auth.api.enmu.PermissionDataSourceEnum; import pro.shushi.pamirs.auth.api.enmu.PermissionTypeEnum; import pro.shushi.pamirs.auth.api.model.AuthGroup; import pro.shushi.pamirs.auth.api.model.AuthRole; import pro.shushi.pamirs.auth.api.model.ResourcePermission; import pro.shushi.pamirs.boot.base.model.UeModule; import pro.shushi.pamirs.boot.common.api.command.AppLifecycleCommand; import pro.shushi.pamirs.boot.common.api.init.InstallDataInit; import pro.shushi.pamirs.boot.common.api.init.UpgradeDataInit; import pro.shushi.pamirs.demo.api.DemoModule; import pro.shushi.pamirs.demo.core.placeholder.EmployeeModulePlaceholder; import pro.shushi.pamirs.framework.common.utils.ObjectUtils; import pro.shushi.pamirs.meta.annotation.fun.extern.Slf4j; import pro.shushi.pamirs.meta.domain.module.ModuleDefinition; import java.util.Collections; import java.util.List; @Slf4j @Component @Order(0) public class DemoModuleBizInit implements InstallDataInit, UpgradeDataInit { @Override public List<String> modules() { return Collections.singletonList(DemoModule.MODULE_MODULE); } @Override public int priority() { return 0; } @Override public boolean init(AppLifecycleCommand command, String version) { this.initAuth(); return true; } @Override public boolean upgrade(AppLifecycleCommand command, String version, String existVersion) { this.initAuth(); return true; } private void initAuth() { AuthGroup authGroup = new AuthGroup(); authGroup.setName("测试权限组") .setDisplayName("测试权限组") .setType(AuthGroupTypeEnum.RUNTIME) .setActive(true); authGroup.createOrUpdate(); AuthRole authRole = new AuthRole(); authRole.setCode("TEST_ROLE_1") .setName("测试角色") .setRoleTypeCode(AuthConstants.ROLE_SYSTEM_TYPE_CODE) .setPermissionDataSource(PermissionDataSourceEnum.CUSTOM) .setActive(true); authRole.createOrUpdate(); authRole.setGroups(Lists.newArrayList(authGroup)); authRole.fieldSave(AuthRole::getGroups); ResourcePermission authPermission = new ResourcePermission(); authPermission.setName("测试模块权限过滤") .setDomainExp(EmployeeModulePlaceholder.PLACEHOLDER) .setModel(ModuleDefinition.MODEL_MODEL) .setPermRead(true) .setPermRun(true) .setPermissionType(PermissionTypeEnum.ROW) .setPermissionDataSource(PermissionDataSourceEnum.CUSTOM) .setCanShow(true) .setActive(true); ResourcePermission authPermission2 = ObjectUtils.clone(authPermission); authPermission2.setName("测试ue模块权限过滤").setModel(UeModule.MODEL_MODEL); authGroup.setPermissions(Lists.newArrayList(authPermission, authPermission2)); authGroup.fieldSave(AuthGroup::getPermissions); } } 这里演示的module表比较特殊,需要同时设置ModuleDefinition和UeModule这2个模型做数据过滤 2.编写占位符拦截替换逻辑 package pro.shushi.pamirs.demo.core.placeholder; import org.springframework.stereotype.Component; import pro.shushi.pamirs.user.api.AbstractPlaceHolderParser; @Component public class EmployeeModulePlaceholder extends AbstractPlaceHolderParser { public static final String PLACEHOLDER = "${employeeModulePlaceholder}"; protected String value() { // TODO…

    2023年11月24日
    1.0K00

Leave a Reply

登录后才能评论