4.1.20 框架之Session

在日常开发中,我们经常需要把一些通用的信息放入程序执行的上下文中,以便业务开发人员快速获取。那么oinone的PamirsSession就是来解决此类问题的。

一、PamirsSession介绍

在oinone的体系中PamirsSession是执行上下文的承载,您能从中获取业务基础信息、指令信息、元数据信息、环境信息、请求参数,以及前后端MessageHub等。在前面的学习过程中我们已经多次接触到了如何使用PamirsSession:

  1. 在4.1.19【框架之网关协议-后端占位符】一文中,使用PamirsSession.getUserId()来获取当前登入用户Id,诸如此类的业务基础信息;

  2. 在4.1.18【框架之网关协议-variables变量】一文中,使用PamirsSession.getRequestVariables()得到PamirsRequestVariables对象,进而获取前端请求的相关信息;

  3. 在4.1.5【模型之持久层配置】一文中,使用PamirsSession.directive(),来操作元位指令系统,进而影响执行策略;

  4. 在4.1.13【Action之校验】、3.4.1【构建第一个Function】等文章中,都用到PamirsSession.getMessageHub()来设置返回消息。

二、构建模块自身Session(举例)

不同的应用场景对PamirsSession的诉求是不一样的,这个时候我们就可以去扩展PamirsSession来达到我们的目的

构建模块自身Session的步骤

  1. 构建自身特有的数据结构XSessionData

  2. 对XSessionData进行线程级缓存封装

  3. 利用Hook机制初始化XSessionData并放到ThreadLocal中

  4. 定义自身XSessionApi

  5. 实现XSessionApi接口、SessionClearApi。在请求结束时会调用SessionClearApi的clear方法

  6. 定义XSession继承PamirsSession

扩展PamirsSession的经典案例设计图

4.1.20 框架之Session

图4-1-20-1 扩展PamirsSession的经典案例设计图

构建Demo应用自身Session

下面的例子为给Session放入当前登陆用户

Step1 新建DemoSessionData类

构建自身特有的数据结构DemoSessionData,增加一个模型为PamirsUser的字段user,DemoSessionData用Data注解,注意要用Oinone平台提供的@Data

package pro.shushi.pamirs.demo.core.session;

import pro.shushi.pamirs.meta.annotation.fun.Data;
import pro.shushi.pamirs.user.api.model.PamirsUser;

@Data
public class DemoSessionData {

    private PamirsUser user;

}

图4-1-20-2 新建DemoSessionData类

Step2 新建DemoSessionCache

对DemoSessionData进行线程级缓存封装

package pro.shushi.pamirs.demo.core.session;

import pro.shushi.pamirs.meta.api.CommonApiFactory;
import pro.shushi.pamirs.meta.api.session.PamirsSession;
import pro.shushi.pamirs.user.api.model.PamirsUser;
import pro.shushi.pamirs.user.api.service.UserService;

public class DemoSessionCache {
    private static final ThreadLocal<DemoSessionData> BIZ_DATA_THREAD_LOCAL = new ThreadLocal<>();
    public static PamirsUser getUser(){
        return BIZ_DATA_THREAD_LOCAL.get()==null?null:BIZ_DATA_THREAD_LOCAL.get().getUser();
    }
    public static void init(){
        if(getUser()!=null){
            return ;
        }
        Long uid = PamirsSession.getUserId();
        if(uid == null){
            return;
        }
        PamirsUser user = CommonApiFactory.getApi(UserService.class).queryById(uid);
        if(user!=null){
            DemoSessionData demoSessionData = new DemoSessionData();
            demoSessionData.setUser(user);
            BIZ_DATA_THREAD_LOCAL.set(demoSessionData);
        }
    }
    public static void clear(){
        BIZ_DATA_THREAD_LOCAL.remove();
    }
}

图4-1-20-3 对DemoSessionData进行线程级缓存封装

Step3 新建DemoSessionHook

利用Hook机制,调用DemoSessionCache的init方法初始化DemoSessionData并放到ThreadLocal中。

@Hook(module= DemoModule.MODULE_MODULE), 规定只有增对DemoModule模块访问的请求该拦截器才会生效,不然其他模块的请求都会被DemoSessionHook拦截。

package pro.shushi.pamirs.demo.core.hook;

import org.springframework.stereotype.Component;
import pro.shushi.pamirs.demo.api.DemoModule;
import pro.shushi.pamirs.demo.core.session.DemoSessionCache;
import pro.shushi.pamirs.meta.annotation.Hook;
import pro.shushi.pamirs.meta.api.core.faas.HookBefore;
import pro.shushi.pamirs.meta.api.dto.fun.Function;

@Component
public class DemoSessionHook implements HookBefore {
    @Override
    @Hook(priority = 1,module = DemoModule.MODULE_MODULE)
    public Object run(Function function, Object... args) {
        DemoSessionCache.init();
        return function;
    }
}

图4-1-20-4 新建DemoSessionHook

Step4 新建DemoSessionApi

package pro.shushi.pamirs.demo.core.session;

import pro.shushi.pamirs.meta.api.CommonApi;
import pro.shushi.pamirs.user.api.model.PamirsUser;

public interface DemoSessionApi extends  CommonApi {
    PamirsUser getUser();
}

图4-1-20-5 新建DemoSessionApi

Step5 新建DemoSessionHolder

  1. 实现DemoSessionApi接口

  2. 实现SessionClearApi接口,在请求结束时会调用SessionClearApi的clear方法

package pro.shushi.pamirs.demo.core.session;

import org.springframework.stereotype.Component;
import pro.shushi.pamirs.meta.api.core.session.SessionClearApi;
import pro.shushi.pamirs.user.api.model.PamirsUser;

@Component
public class DemoSessionHolder implements DemoSessionApi, SessionClearApi {
    @Override
    public PamirsUser getUser() {
        return DemoSessionCache.getUser();
    }

    @Override
    public void clear() {
        DemoSessionCache.clear();
    }
}

图4-1-20-6 新建DemoSessionHolder

Step6 新建DemoSession

package pro.shushi.pamirs.demo.core.session;

import pro.shushi.pamirs.meta.api.CommonApiFactory;
import pro.shushi.pamirs.meta.api.session.PamirsSession;
import pro.shushi.pamirs.user.api.model.PamirsUser;

public class DemoSession extends PamirsSession {
    public static PamirsUser getUser(){
        return CommonApiFactory.getApi(DemoSessionApi.class).getUser();
    }
}

图4-1-20-7 新建DemoSession

Step7 修改UserPlaceHolder

使用DemoSession.getUser().getId()替代PamirsSession.getUserId()

package pro.shushi.pamirs.demo.core.placeholder;

import org.springframework.stereotype.Component;
import pro.shushi.pamirs.demo.core.session.DemoSession;
import pro.shushi.pamirs.user.api.AbstractPlaceHolderParser;

@Component
public class UserPlaceHolder extends AbstractPlaceHolderParser {
    @Override
    protected String value() {
        return DemoSession.getUser().getId().toString();
    }

    @Override
    public Integer priority() {
        return 10;
    }

    @Override
    public Boolean active() {
        return Boolean.TRUE;
    }

    @Override
    public String namespace() {
        return "currentUserId";
    }
}

图4-1-20-8 修改UserPlaceHolder

Step8 重启看效果

效果跟4.1.19【框架之网关协议-后端占位符】一文中的例子一样

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

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

Like (0)
史, 昂's avatar史, 昂数式管理员
Previous 2024年5月23日 am8:43
Next 2024年5月23日 am8:45

相关推荐

  • 5.2 CDM之工程模式

    两种工程模式介绍 oinone推荐的两种工程模式都保留互联网特性,如跟业务无关的基础平台还是采用平台化思路建设。二种侧重点差异如下 第一种:比较适合企业采用多供应商联合开发场景,先以业务区分,各个业务线有独立的领域平台,最大限度保持不同业务线的独立性,有利于各个业务线独立发展(目前oinone上层星空系列产品采用这种工程模式,因为我们期望的时候帮助企业构建软件生态,必然要考虑不同供应商联合开发场景) 第二种:比较接近传统互联网架构,先按平台领域区分,如商品领域:商品平台做总工程,但里面按业务区分模块分子工程来保持业务相互独立,相对于第一种把领域的代码放一起,带来好处强化大家思考模型通用性。但不适用于跨公司主体间配合。 图5-2-1 Oinone-CDM的两种工程模式 注意事项: oinone兼容传统互联网架构 不管哪种模式,都需要解决CDM的维护问题 CDM维护的常见问题: Q:CDM层缺少模型怎么办? A:CDM层模型是逐步完善和丰富的。如果是特定业务自己需要的模型,这类模型无通用性。则加到自己的工程中;如果是通用的,则架构组确定是否需要纳入到CDM。 Q:CDM层已有的模型缺少字段怎么办? A:CDM层模型的字段也是逐步完善和丰富的,通用的字段在架构组确定后也会被吸收进来 Q:CDM层不同业务线相互影响怎么办? A:扩展字段最好带上自有前缀标志,如果觉得通用则提交架构组走模型缺少字段加入 Q:CDM层某模型新增加了的字段,但原先业务线已经加了相同含义字段 A:业务线可以把自己的字段related到CDM增加的新字段,并做数据迁移

    2024年5月23日
    2.4K00
  • 5.3 基础支撑之用户与客户域

    一、三户概念 三户由来 介绍下经典的三户模型,它是电信运营支持系统的基础。三户模型即客户、用户和帐户,来源于etom的模型。这三者之间的关系应该是一个相互关联但又是独立的三个实体,这种关联只是一个归属和映射的关系,而三个实体本身是相互独立的,分别是体现完全不同的几个域的信息,客户是体现了社会域的信息,用户体现了业务域的信息,帐户体现的是资金域的信息。 客户:它是个社会化的概念,一个自然人或一个法人 用户:它是客户使用运营商开发的一个产品以及基于该产品之上的增值业务时,产生的一个实体。如果说一个客户使用了多个产品,那么一个客户就会对应好几个用户(即产品) 账户:它的概念起源于金融业,只是一个客户在运营商存放资金的实体,目的是为选择的产品付费 Oinone的三户 在原三户模型中【用户】是购买关系产生的产品与客户关系的服务实例,在互联网发展中用户的概念发生了非常大的变化,【用户】概念变成了:使用者,是指使用电脑或网络服务的人,通常拥有一个用户账号,并以用户名识别。而且新概念在互联网强调用户数的大背景下已经被普遍介绍,再去强调电信行业的用户概念就会吃力不讨好。而且不管是企业应用领域和互联网领域,原用户概念都显得过于复杂和没有必要。也就有了特色的oinone的三户模型: 客户:它是个社会化的概念,一个自然人或一个法人 用户:使用者,是指使用电脑或网络服务的人,通常拥有一个用户账号,并以用户名识别 账户:它的概念起源于金融业,只是一个客户在运营商存放资金的实体,目的是为选择的产品付费 二、Oinone的客户与用户 三户模型是构建上层应用的基础支撑能力,任何业务行为都跟这里两个实体脱不了干系。以客户为中心建立商业关系与商业行为主体,以用户为中心构建一致体验与操作行为主体。在底层设计上二者相互独立并无关联,由上层应用自行作关联绑定,往往在登陆时在Session的处理逻辑中会根据【用户】去找到对应一个或多个【商业(主体)客户】,Session的实现可以参考4.1.20【框架之Session】一文。 图5-3-1 Oinone的客户与用户 客户设计说明 PamirsPartner作为商业关系与商业行为的主体,派生了两个子类PamirsCompany与PamirsPerson分别对应:公司(法人)客户、自然人客户 公司(法人)客户PamirsCompany对应多个组织部门PamirsDepartment,公司(法人)客户PamirsCompany对应多个员工PamirsEmployee 部门PamirsDepartment对应一个公司(法人)客户PamirsCompany,对应多个员工PamirsEmployee 员工PamirsEmployee对应多个部门PamirsDepartment,对应一个或多个公司(法人)客户PamirsCompany,其中有一个主的 用户设计说明 PamirsUser作为一致体验与操作行为主体,本身绑定登陆账号,并且可以关联多个三方登陆账户PamirsUserThirdParty 客户与用户如何关联(举例) 例子设计: 新建demo系统的PetComany和PetEmployee,用PetEmployee去关联用户。 当用户登陆时,根据用户Id找到PetEmployee,在根据PetEmployee找到PetComany,把PetComany放到Session中去 修改PetShop模型关联一个PamirsPartner,PamirsPartner的信息从Session取。 Step1 pamirs-demo-api工程增加依赖,并且DemoModule增加对BusinessModule的依赖 <dependency> <groupId>pro.shushi.pamirs.core</groupId> <artifactId>pamirs-business-api</artifactId> </dependency> 图5-3-2 pamirs-demo-api工程增加依赖 在DemoModule类中通过@Module.dependencies中增加BusinessModule.MODULE_MODULE @Module( dependencies = { BusinessModule.MODULE_MODULE} ) 图5-3-3 声明对BusinessModule的依赖 Step2 新建PetComany和PetEmployee,以及对应的服务 package pro.shushi.pamirs.demo.api.model; import pro.shushi.pamirs.business.api.model.PamirsEmployee; import pro.shushi.pamirs.meta.annotation.Field; import pro.shushi.pamirs.meta.annotation.Model; import pro.shushi.pamirs.user.api.model.PamirsUser; @Model.model(PetEmployee.MODEL_MODEL) @Model(displayName = "宠物公司员工",labelFields = "name") public class PetEmployee extends PamirsEmployee { public static final String MODEL_MODEL="demo.PetEmployee"; @Field(displayName = "用户") private PamirsUser user; } 图5-3-4 新建PetEmployee package pro.shushi.pamirs.demo.api.model; import pro.shushi.pamirs.business.api.entity.PamirsCompany; import pro.shushi.pamirs.meta.annotation.Field; import pro.shushi.pamirs.meta.annotation.Model; @Model.model(PetCompany.MODEL_MODEL) @Model(displayName = "宠物公司",labelFields = "name") public class PetCompany extends PamirsCompany { public static final String MODEL_MODEL="demo.PetCompany"; @Field.Text @Field(displayName = "简介") private String introductoin; } 图5-3-5 新建PetComany package pro.shushi.pamirs.demo.api.service; import pro.shushi.pamirs.demo.api.model.PetEmployee; import pro.shushi.pamirs.meta.annotation.Fun; import pro.shushi.pamirs.meta.annotation.Function; @Fun(PetEmployeeQueryService.FUN_NAMESPACE) public interface PetEmployeeQueryService { String FUN_NAMESPACE ="demo.PetEmployeeQueryService"; @Function PetEmployee queryByUserId(Long userId); } 图5-3-6 新建PetEmployee对应服务 package pro.shushi.pamirs.demo.core.service; import org.springframework.stereotype.Component; import pro.shushi.pamirs.demo.api.model.PetEmployee; import pro.shushi.pamirs.demo.api.service.PetEmployeeQueryService; import pro.shushi.pamirs.framework.connectors.data.sql.query.QueryWrapper; import pro.shushi.pamirs.meta.annotation.Fun; import pro.shushi.pamirs.meta.annotation.Function; @Fun(PetEmployeeQueryService.FUN_NAMESPACE) @Component public class PetEmployeeQueryServiceImpl implements PetEmployeeQueryService { @Override @Function public PetEmployee queryByUserId(Long userId) { if(userId==null){ return null; } QueryWrapper<PetEmployee> queryWrapper = new QueryWrapper<PetEmployee>().from(PetEmployee.MODEL_MODEL).eq("user_id", userId); return…

    2024年5月23日
    2.0K00
  • 4.1.9 函数之元位指令

    元位指令系统是通过给请求上下文的指令位字段作按位与标记来对函数处理下发对应指令的系统。 一、元位指令介绍 元位指令系统是通过给请求上下文的指令位字段作按位与标记来对函数处理下发对应指令的系统。 元位指令系统分为请求上下文指令和数据指令两种。 数据指令 数据指令基本都是系统内核指令。业务开发时用不到这里就不介绍了。前20位都是系统内核预留 请求上下文指令 请求上下文指令:使用session上下文中非持久化META_BIT属性设置指令。 位 指令 指令名 前端默认值 后端默认值 描述 20 builtAction 内建动作 否 否 是否是平台内置定义的服务器动作对应操作:PamirsSession.directive().disableBuiltAction(); PamirsSession.directive().enableBuiltAction(); 21 unlock 失效乐观锁 否 否 系统对带有乐观锁模型默认使用乐观锁对应操作:PamirsSession.directive().enableOptimisticLocker(); PamirsSession.directive().disableOptimisticLocker(); 22 check 数据校验 是 否 系统后端操作默认不进行数据校验,标记后生效数据校验对应操作:PamirsSession.directive().enableCheck(); PamirsSession.directive().disableCheck(); 23 defaultValue 默认值计算 是 否 是否自动填充默认值对应操作:PamirsSession.directive().enableDefaultValue(); PamirsSession.directive().disableDefaultValue(); 24 extPoint 执行扩展点 是 否 前端请求默认执行扩展点,可以标记忽略扩展点。后端编程式调用数据管理器默认不执行扩展点对应操作:PamirsSession.directive().enableExtPoint(); PamirsSession.directive().disableExtPoint(); 25 hook 拦截 是 否 是否进行函数调用拦截对应操作:PamirsSession.directive().enableHook(); PamirsSession.directive().disableHook(); 26 authenticate 鉴权 是 否 系统默认进行权限校验与过滤,标记后使用权限校验对应操作:PamirsSession.directive().sudo(); PamirsSession.directive().disableSudo(); 27 ormColumn ORM字段别名 否 否 系统指令,请勿设置 28 usePkStrategy 使用PK策略 是 否 使用PK是否空作为采用新增还是更新的持久化策略对应操作:PamirsSession.directive().enableUsePkStrategy(); PamirsSession.directive().disableUsePkStrategy(); 29 fromClient 是否客户端调用 是 否 是否客户端(前端)调用对应操作:PamirsSession.directive().enableFromClient(); PamirsSession.directive().disableFromClient(); 30 sync 同步执行函数 否 否 异步执行函数强制使用同步方式执行(仅对Spring Bean有效) 31 ignoreFunManagement 忽略函数管理 否 否 忽略函数管理器处理,防止Spring调用重复拦截对应操作:PamirsSession.directive().enableIgnoreFunManagement(); PamirsSession.directive().disableIgnoreFunManagement(); 表4-1-9-1 请求上下文指令 二、使用指令 普通模式 PamirsSession.directive().disableOptimisticLocker(); try{ 更新逻辑 } finally { PamirsSession.directive().enableOptimisticLocker(); } 图4-1-9-1 普通模式代码示意 批量设置模式 Models.directive().run(() -> {此处添加逻辑}, SystemDirectiveEnum.AUTHENTICATE) 图4-1-9-2 批量设置模式代码示意 三、使用举例 我们在4.1.5【模型之持久层配置】一文中提到过失效乐观锁,我们在这里就尝试下吧。 Step1 修改PetItemInventroyAction 手动失效乐观锁 package pro.shushi.pamirs.demo.core.action; import org.springframework.stereotype.Component; import pro.shushi.pamirs.demo.api.model.PetItemInventroy; import pro.shushi.pamirs.meta.annotation.Function; import pro.shushi.pamirs.meta.annotation.Model; import pro.shushi.pamirs.meta.api.session.PamirsSession; 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); PamirsSession.directive().disableOptimisticLocker(); try{ //批量更新会,自动抛错 int i = data.updateBatch(inventroys); //单记录更新,不自动抛售需要自行判断 // int i = data.updateById();…

    2024年5月23日
    1.6K00
  • 4.1.22 框架之分布式缓存

    分布式缓存Oinone平台主要用到了Redis,为了让业务研发时可以无感使用RedisTemplate和StringRedisTemplate,已经提前注册好了redisTemplate和stringRedisTemplate,而且内部会自动处理相关特殊逻辑以应对多租户环境,小伙伴不能自己重新定义Redis的相关bean。 使用说明 配置说明 spring: redis: database: 0 host: 127.0.0.1 port: 6379 timeout: 2000 # cluster: # nodes: # – 127.0.0.1:6379 # timeout: 2000 # max-redirects: 7 jedis: pool: # 连接池中的最大空闲连接 默认8 max-idle: 8 # 连接池中的最小空闲连接 默认0 min-idle: 0 # 连接池最大连接数 默认8 ,负数表示没有限制 max-active: 8 # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认-1 max-wait: -1 图4-1-22-1 分布式缓存配置说明 代码示例 package pro.shushi.pamirs.demo.core.service; import org.springframework.stereotype.Component; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; @Component public class Test { @Autowired private RedisTemplate redisTemplate; @Autowired private StringRedisTemplate stringRedisTemplate } 图4-1-22-2 代码示例

    Oinone 7天入门到精通 2024年5月23日
    2.1K00
  • 3.3.8 字段类型之基础与复合

    模型字段是描述实体的特征属性,本文介绍重点介绍字段的基础类型与复合类型 使用@Field注解来描述模型的字段。如果未配置字段类型,系统会根据Java代码的字段声明类型来自动获取业务类型。建议配置displayName属性来描述字段在前端的显示名称。可以使用defaultValue配置字段的默认值。 一、安装与更新 使用@Field.field来配置字段的不可变更编码。字段一旦安装,无法在对该字段编码值进行修改,之后的字段配置更新会依据该编码进行查找并更新;如果仍然修改该注解的配置值,则系统会将该字段识别为新字段,存储模型会创建新的数据库表字段,而原字段将会rename为废弃字段。 二、字段类型 类型系统由基本类型、复合(组件)类型、引用类型和关系类型四种类型系统构成。通过类型系统描述应用程序、数据库和前端视觉视图如何进行交互,数据及数据间关系如何处理的协议。其中引用类型和关系类型介绍详见3.3.9【字段类型之关系与引用】一文,字段命名规范参见3.3.1【构建第一个Model】一文,这里不再赘述。 基本类型 业务类型 Java类型 数据库类型 规则说明 BINARY ByteByte[] TINYINTBLOB 二进制类型,不推荐使用 INTEGER ShortIntegerLongBigInteger smallintintbigintdecimal(size,0) 整数, 包括整数(10-11位有效数字)、长整数(19-20位有效数字)和大整数(超过19位)。【数据库规则】:默认使用int;如果size小于6则使用smallint;如果size超过6则使用int;如果size超过10位数字,即大于11(包含符号位),则使用长整数bigint;如果size超过19位数字,即大于20(包含符号位),则使用大数decimal。若未配置size,则按Java类型推测。【前端交互规则】:整数使用Number类型,长整数和大整数前后端协议使用字符串类型。 FLOAT FloatDoubleBigDecimal float(M,D)double(M,D)decimal(M,D) 浮点数,?包括单精度浮点数(7-8位有效数字)、双精度浮点数(15-16位有效数字)和大数(超过15位)。【数据库规则】:默认使用单精度浮点数float;如果size超过7位数字,即大于等于8,则使用双精度浮点数double;如果size超过15位数字,即大于等于16,则使用大数decimal。若未配置size,则按Java类型推测。【前端交互规则】:单精度浮点数float和双精度浮点数double使用Number类型(因为都使用IEEE754协议64位进行存储),大数前后端协议使用字符串类型。 BOOLEAN Boolean tinyint(1) 布尔类型,值为1,true(真)或0,false(假) ENUM Enum 与数据字典指定基本类型一致 【前端交互规则】:可选项从ModelField的options字段获取,options字段值为字段指定数据字典子集的JSON序列化字符串。前后端传递的是可选项的name,数据库存储使用可选项的value。multi属性为true,则使用多选控件;multi属性为false,则使用单元控件 STRING String varchar(size) 字符串,size为长度限制默认值参考,前端可以view中覆盖该配置 TEXT String text 多行文本,编辑态组件为多行文本框,长度限制为配置项size值 HTML String text 富文本编辑器 DATETIME java.util.Datejava.sql.Timestamp datetime(fraction)timestamp(fraction) 日期时间类型【数据库规则】:日期和时间的组合,时间格式为?YYYY-MM-DD HH:MM:SS[.fraction],默认精确到秒,在默认的秒精确度上,可以带小数,最多带6位小数,即可以精确到?microseconds (6 digits) precision。可以通过设置fraction来设置精确小数位数,最终存储在字段的decimal属性上。【前端交互规则】:前端默认使用日期时间控件,根据日期时间类型格式化格式format格式化日期时间 YEAR java.util.Date year 年份类型日期类型【数据库规则】:默认“YYYY”格式表示的日期值【前端交互规则】:前端默认使用年份控件,根据日期类型格式化格式format格式化日期 DATE java.util.Datejava.sql.Date datedate 日期类型【数据库规则】:默认“YYYY-MM-DD”格式表示的日期值【前端交互规则】:前端默认使用日期控件,根据日期类型格式化格式format格式化日期 TIME java.util.Datejava.sql.Time time(fraction)time(fraction) 时间类型【数据库规则】:默认“HH:MM:SS”格式表示的时间值【前端交互规则】:前端默认使用时间控件,根据日期类型格式化格式format格式化日期 表3-3-8-1 字段基本类型 复合类型 业务类型 Java类型 数据库类型 规则说明 MONEY BigDecimal decimal(M,D) 金额,前端使用金额控件,可以使用currency设置币种字段 表3-3-8-2 字段复合类型 不可变更字段 使用immutable属性来描述该字段前后端都无法进行更新操作,系统会忽略不可变更字段的更新操作。 自动生成编码的字段 详见3.3.5【模型编码生成器】一文。 字段的序列化与反序列化 使用@Field注解的serialize属性来配置非字符串类型属性的序列化与反序列化方式,最终会以序列化后的字符串持久化到存储中。 详见3.3.7【字段之序列化方式】一文 前端默认配置 可以使用@Field注解中的以下属性来配置前端的默认视觉与交互规则,也可以在前端设置覆盖以下配置。 @Field(required),是否必填 @Field(invisible),是否不可见 @Field(priority),字段优先级,列表的列使用该属性进行排序 更多前端默认视图配置详见:3.5.4【Ux注解详解】一文,如:readonly是否只读等。 举例 回顾我们前面学习例子 现有PetShop代码如下 package pro.shushi.pamirs.demo.api.model; import pro.shushi.pamirs.core.common.enmu.DataStatusEnum; import pro.shushi.pamirs.demo.api.enumeration.PetShopOptionEnum; import pro.shushi.pamirs.meta.annotation.Field; import pro.shushi.pamirs.meta.annotation.Model; import java.sql.Time; import java.util.List; @Model.model(PetShop.MODEL_MODEL) @Model(displayName = 宠物店铺,summary=宠物店铺,labelFields ={shopName} ) @Model.Code(sequence = DATE_ORDERLY_SEQ,prefix = P,size=6,step=1,initial = 10000,format = yyyyMMdd) public class PetShop extends AbstractDemoIdModel { public static final String MODEL_MODEL=demo.PetShop; @Field(displayName = 店铺编码) private String code; @Field(displayName = 店铺编码2) @Field.Sequence(sequence = DATE_ORDERLY_SEQ,prefix = C,size=6,step=1,initial = 10000,format = yyyyMMdd) private String codeTwo; @Field(displayName = 店铺名称,required = true) private String shopName; @Field(displayName = 开店时间,required = true) private Time openTime; @Field(displayName = 闭店时间,required = true) private Time closeTime; @Field(displayName =…

    2024年5月23日
    1.8K00

Leave a Reply

Please Login to Comment