模型定义在数据库中的映射

模型定义在数据库中的映射

Oinone中通过定义模型来建立数据表,使用注解的方式来使多张表之间的关联。

  1. 数据库字段与模型定义字段映射

    模型定义在数据库中的映射

    package pro.shushi.pamirs.top.api.model;
    
    import pro.shushi.pamirs.core.common.enmu.DataStatusEnum;
    import pro.shushi.pamirs.meta.annotation.Field;
    import pro.shushi.pamirs.meta.annotation.Model;
    import pro.shushi.pamirs.meta.base.IdModel;
    import pro.shushi.pamirs.meta.enmu.DateFormatEnum;
    import pro.shushi.pamirs.meta.enmu.DateTypeEnum;
    import pro.shushi.pamirs.meta.enmu.MimeTypeEnum;
    
    import java.math.BigDecimal;
    import java.util.Date;
    
    @Model.model(PamirsDemo.MODEL_MODEL)
    @Model(displayName = "PamirsDemo")
    public class PamirsDemo extends IdModel {
    
       public static final String MODEL_MODEL = "top.PamirsDemo";
    
       @Field.Binary(mime = MimeTypeEnum.html)
       @Field(displayName = "二进制类型")
       private Byte[] byteType;
    
       @Field.Integer
       @Field(displayName = "整数")
       private Long longType;
    
       @Field.Float
       @Field(displayName = "浮点数")
       private BigDecimal floatType;
    
       @Field.Boolean
       @Field(displayName = "布尔类型")
       private Boolean booleanType;
    
       @Field.Enum
       @Field(displayName = "枚举")
       private DataStatusEnum enumType;
    
       @Field.String
       @Field(displayName = "字符串")
       private String stringType;
    
       @Field.Text
       @Field(displayName = "多行文本")
       private String textType;
    
       @Field.Html
       @Field(displayName = "富文本")
       private String richText;
    
       @Field.Date(type = DateTypeEnum.DATE, format = DateFormatEnum.DATE)
       @Field(displayName = "日期类型")
       private Date dataType;
    
       @Field.Date(type = DateTypeEnum.DATETIME, format = DateFormatEnum.DATETIME)
       @Field(displayName = "日期时间类型")
       private Date dataTimeType;
    
       @Field.Money
       @Field(displayName = "金额")
       private BigDecimal amount;
    }
    

    更多字段基础请参考文档字段基础与复合

  2. 多对一的关系映射

    例:设计一张教师表,一张科目表,教师表对科目表属于多对一的关系,在教师表中使用科目id管理关联关系。

    教师表teacher

    模型定义在数据库中的映射

    科目表professional

    模型定义在数据库中的映射


    那么在Oinone的模型定义中,这两张表定义是这样的;

    教师模型

    package pro.shushi.pamirs.top.api.model;
    
    import pro.shushi.pamirs.meta.annotation.Field;
    import pro.shushi.pamirs.meta.annotation.Model;
    import pro.shushi.pamirs.meta.base.IdModel;
    
    @Model.model(Teacher.MODEL_MODEL)
    @Model(displayName = "教师", summary = "教师")
    public class Teacher extends IdModel {
    
       public static final String MODEL_MODEL = "top.Teacher";
    
       @Field.String
       @Field(displayName = "教师名字")
       private String teacherName;
    
       @Field.Integer
       @Field(displayName = "科目id")
       private Long professionalId;
    
       @Field(displayName = "关联科目")
       @Field.many2one
       @Field.Relation(relationFields = {"professionalId"},referenceFields = {"id"})
       private Professional professional;
    }
    

    该模型创建的数据库如下:

    模型定义在数据库中的映射

    科目模型

    package pro.shushi.pamirs.top.api.model;
    
    import pro.shushi.pamirs.meta.annotation.Field;
    import pro.shushi.pamirs.meta.annotation.Model;
    import pro.shushi.pamirs.meta.base.IdModel;
    
    import java.util.List;
    
    @Model.model(Professional.MODEL_MODEL)
    @Model(displayName = "科目", summary = "科目")
    public class Professional extends IdModel {
    
       public static final String MODEL_MODEL = "top.Professional";
    
       @Field.String
       @Field(displayName = "科目名称")
       private String professionalName;
    
    }

    该模型创建的数据库如下:

    模型定义在数据库中的映射

    使用@Field.many2one注解管理教师与科目的多对一关系,在表操作时会自动维护关联关系。如果业务上是一对一的关系,在模型定义中建议使用多对一进行关联。

  3. 一对多的关系映射

    例:设计一张学生表,一张科目表,学生表对科目表属于一对多的关系,在科目表里使用学生ID与学生表进行关联。

    学生表student
    模型定义在数据库中的映射
    科目表professional
    模型定义在数据库中的映射


    那么在Oinone的模型定义中,这两张表定义是这样的;
    学生模型

    package pro.shushi.pamirs.top.api.model;
    import pro.shushi.pamirs.meta.annotation.Field;
    import pro.shushi.pamirs.meta.annotation.Model;
    import pro.shushi.pamirs.meta.base.IdModel;
    @Model.model(Student.MODEL_MODEL)
    @Model(displayName = "学生", summary = "学生")
    public class Student extends IdModel {
    
        public static final String MODEL_MODEL = "top.Student";
    
        @Field(displayName = "学生名字")
        @Field.String
        private String studentName;
    
        @Field(displayName = "学生ID")
        @Field.Integer
        private Long studentId;
    }
    

    该模型创建的数据库如下:
    模型定义在数据库中的映射

    科目模型

     package pro.shushi.pamirs.top.api.model;
    
     import pro.shushi.pamirs.meta.annotation.Field;
     import pro.shushi.pamirs.meta.annotation.Model;
     import pro.shushi.pamirs.meta.base.IdModel;
    
     import java.util.List;
    
     @Model.model(Professional.MODEL_MODEL)
     @Model(displayName = "科目", summary = "科目")
     public class Professional extends IdModel {
    
     public static final String MODEL_MODEL = "top.Professional";
    
         @Field.String
        @Field(displayName = "科目名称")
        private String professionalName;
    
        @Field(displayName = "关联学生")
        @Field.one2many
        @Field.Relation(relationFields = {"id"},referenceFields = {"studentId"})
        private List<Student> studentList;
    }

    在科目模型中建立@Field.one2many来管理学生和科目的关联关系。该模型创建的数据库如下:
    模型定义在数据库中的映射

  4. 多对多关系的关系映射

    例:设计一张教师表,一张学生表,教师表对学生表属于多对多的关系,使用中间表管理教师和学生的关联关系。

    教师表teacher

    模型定义在数据库中的映射

    学生表student

    模型定义在数据库中的映射

    教师学生中间表teacher_rel_student

    模型定义在数据库中的映射


    那么在Oinone的模型定义中,多对多关系是这样定义的;

    教师模型

    package pro.shushi.pamirs.top.api.model;
    
    import pro.shushi.pamirs.meta.annotation.Field;
    import pro.shushi.pamirs.meta.annotation.Model;
    import pro.shushi.pamirs.meta.base.IdModel;
    
    import java.util.List;
    
    @Model.model(Teacher.MODEL_MODEL)
    @Model(displayName = "教师", summary = "教师")
    public class Teacher extends IdModel {
    
       public static final String MODEL_MODEL = "top.Teacher";
    
       @Field.String
       @Field(displayName = "教师名字")
       private String teacherName;
    
       @Field(displayName = "教师关联学生")
       @Field.many2many(through = TeacherRelStudent.MODEL_MODEL, relationFields = {"teacherId"}, referenceFields = {"studentId"})
       @Field.Relation(relationFields = {"id"}, referenceFields = {"id"})
       private List<Student> studentList;
    }

    该模型创建的数据库如下:

    模型定义在数据库中的映射

    学生模型

    package pro.shushi.pamirs.top.api.model;
    
    import pro.shushi.pamirs.meta.annotation.Field;
    import pro.shushi.pamirs.meta.annotation.Model;
    import pro.shushi.pamirs.meta.base.IdModel;
    
    @Model.model(Student.MODEL_MODEL)
    @Model(displayName = "学生", summary = "学生")
    public class Student extends IdModel {
    
       public static final String MODEL_MODEL = "top.Student";
    
       @Field(displayName = "学生名字")
       @Field.String
       private String studentName;
    }

    该模型创建的数据库如下:

    模型定义在数据库中的映射

    教师学生关系模型

    package pro.shushi.pamirs.top.api.model;
    
    import pro.shushi.pamirs.meta.annotation.Field;
    import pro.shushi.pamirs.meta.annotation.Model;
    import pro.shushi.pamirs.meta.base.BaseRelation;
    
    @Model.model(TeacherRelStudent.MODEL_MODEL)
    @Model(displayName = "教师学生关系表", summary = "教师学生关系表")
    public class TeacherRelStudent extends BaseRelation {
    
       public static final String MODEL_MODEL = "top.TeacherRelStudent";
    
       @Field.Integer
       @Field(displayName = "教师ID")
       private Long teacherId;
    
       @Field.Integer
       @Field(displayName = "学生ID")
       private Long studentId;
    }

    该模型创建的数据库如下:

    模型定义在数据库中的映射

    使用@Field.many2many注解以及中间管理关联关系,在表操作时自动维护关联关系。

Oinone社区 作者:yexiu原创文章,如若转载,请注明出处:https://doc.oinone.top/dai-ma-shi-jian/16109.html

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

(1)
yexiu的头像yexiu数式员工
上一篇 2024年8月16日 pm4:24
下一篇 2024年8月17日 pm3:50

相关推荐

  • 对字段进行加密存储

    需求: 模型字段上使用 pro.shushi.pamirs.user.api.crypto.annotation.EncryptField 注解模型动作上使用 pro.shushi.pamirs.user.api.crypto.annotation.NeedDecrypt 注解 示例: 对需要加密的字段添加@EncryptField注解 @Model.model(Student.MODEL_MODEL) @Model(displayName = "学生", summary = "学生") public class Student extends IdModel { public static final String MODEL_MODEL = "top.Student"; @Field(displayName = "学生名字") @Field.String private String studentName; @Field(displayName = "学生ID") @Field.Integer private Long studentId; @Field(displayName = "学生卡号") @Field.String @EncryptField private String studentCard; } 对函数添加@NeedDecrypt注解 @Action.Advanced(name = FunctionConstants.create, managed = true)//默认取的是方法名 @Action(displayName = "确定", summary = "添加", bindingType = ViewTypeEnum.FORM) @Function(name = FunctionConstants.create)//默认取的是方法名 @Function.fun(FunctionConstants.create)//默认取的是方法名 @NeedDecrypt public Student create(Student data) { String studentCard = data.getStudentCard(); if (studentCard != null) { //自定义加密方法 data.setStudentCard(StudentEncoder.encode(studentCard)); } return data.create(); }

    2024年10月10日
    1.4K00
  • 非存储字段搜索,适应灵活的搜索场景

    1、非存储字段搜索 1.1 描述 通常根据本模型之外的信息作为搜索条件时,通常会把 这些字段放在代理模型上。这类场景我们称之为 非存储字段搜索 1.2 场景一 非存储字段为基本的String。1.代码定义:非存储字段为基本的包装数据类型 @Field(displayName = "确认密码", store = NullableBoolEnum.FALSE) private String confirmPassword; 2.设计器拖拽:列表中需要有退拽这个字段,字段是否隐藏的逻辑自身业务是否需要决定。3.页面通过非存储字段为基本的包装数据类型进行搜索时。会拼在 queryWrapper 的属性queryData中,queryData为Map,key为字段名,value为搜索值。4.后台逻辑处理代码示例: Map<String, Object> queryData = queryWrapper.getQueryData(); if (null != queryData) { Object productIdObj = queryData.get(PRODUCT_ID); if (Objects.nonNull(productIdObj)) { String productId = productIdObj.toString(); queryWrapper.lambda().eq(MesProduceOrderProxy::getProductId, productId); } } 1.3 场景二 非存储字段为非存储对象。 定义 为非存储的 @Field(displayName = "款", store = NullableBoolEnum.FALSE) @Field.many2one @Field.Relation(store = false) private MesProduct product; 2.页面在搜索栏拖拽非存储字段作为搜索条件 3.后台逻辑处理代码示例: try { if (null != queryData && !queryData.isEmpty()) { List<Long> detailId = null; BasicSupplier supplier = JsonUtils.parseMap2Object((Map<String, Object>) queryData.get(supplierField), BasicSupplier.class); MesProduct product = JsonUtils.parseMap2Object((Map<String, Object>) queryData.get(productField), MesProduct.class); MesMaterial material = JsonUtils.parseMap2Object((Map<String, Object>) queryData.get(materialField), MesMaterial.class); if (supplier != null) { detailId = bomService.queryBomDetailIdBySupplierId(supplier.getId()); if (CollectionUtils.isEmpty(detailId)) { detailId.add(-1L); } } if (product != null) { List<Long> produceOrderId = produceOrderService.queryProductOrderIdByProductIds(product.getId()); if (CollectionUtils.isNotEmpty(produceOrderId)) { queryWrapper.lambda().in(MesProduceBomSizes::getProduceOrderId, produceOrderId); } } if (material != null) { //找出两个bom列表的并集 List<Long> materBomDetailId = bomService.queryBomDetailIdByMaterialId(material.getId()); if (CollectionUtils.isNotEmpty(detailId)) { detailId = detailId.stream().filter(materBomDetailId::contains).collect(Collectors.toList()); } else { detailId = new ArrayList<>(); if (CollectionUtils.isEmpty(materBomDetailId)) { detailId.add(-1L); } else { detailId.addAll(materBomDetailId); } } } if (CollectionUtils.isNotEmpty(detailId)) { queryWrapper.lambda().in(MesProduceBomSizes::getProductBomId, detailId); } } } catch (Exception e) { log.error("queryData处理异常", e); } 注意:…

    2024年2月20日
    1.5K00
  • 如何改变调度策略,让Schedule独立执行线程

    schedule里,相同的taskType跑多个业务任务,如果其中一个任务大量重试占满了调度线程,会影响别的业务任务及时被执行,如下面截图中,taskType用的是平台内置的常量,这个常量会被其他任务也使用,如果当前任务出现了异常占用了这个taskType的所有线程,那么这个taskType下面的其他任务就会被阻塞延后执行。应该给需要业务及时性的任务单独建立自定义的taskType,这样每个taskType的线程就是独立的,A任务异常不会影响B任务的执行。 1、后台创建task type相关的类,继承BaseScheduleNoTransactionTask,要加springbean的注解,参考:task type建议使用类名 2、提交任务的时候,设置tasktype为步骤1的TaskType 3、控制台新增策略和任务bean名称为步骤1的spring beanName,任务名称 $xxx,右边的占位符内容为yml里面配置的ownSign字段任务的名称也是步骤1的 spring beanName 4、配置完成后,控制台启动任务,就可以测试了

    2024年2月20日
    1.0K00
  • 如何选择适合的模型类型?

    介绍 通过Oinone 7天从入门到精通的模型的类型章节我们可以知道模型有抽象模型、存储模型、代理模型、传输模型这四种。但是在在定义模型的时候我们可能不知道该如何选择类型,下面结合业务场景为大家讲解几种模型的典型使用场景。 抽象模型 抽象模型往往是提供公共能力和字段的模型,它本身不会直接用于构建协议和基础设施(如表结构等)。 场景:猫、鸟都继承自动物这个抽象模型 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.annotation.sys.Base; import pro.shushi.pamirs.meta.base.IdModel; import pro.shushi.pamirs.meta.enmu.ModelTypeEnum; @Base @Model.model(AbstractAnimal.MODEL_MODEL) @Model.Advanced(type = ModelTypeEnum.ABSTRACT) @Model(displayName = "动物") public abstract class AbstractAnimal extends IdModel { public static final String MODEL_MODEL = "demo.AbstractAnimal"; @Field.String @Field(displayName = "名称") private String name; @Field.String @Field(displayName = "颜色") private String color; } package pro.shushi.pamirs.demo.api.model; import pro.shushi.pamirs.meta.annotation.Field; import pro.shushi.pamirs.meta.annotation.Model; @Model.model(Cat.MODEL_MODEL) @Model(displayName = "猫") public class Cat extends AbstractAnimal { private static final long serialVersionUID = -5104390780952634397L; public static final String MODEL_MODEL = "demo.Cat"; @Field.Integer @Field(displayName = "尾巴长度") private Integer tailLength; } package pro.shushi.pamirs.demo.api.model; import pro.shushi.pamirs.meta.annotation.Field; import pro.shushi.pamirs.meta.annotation.Model; @Model.model(Bird.MODEL_MODEL) @Model(displayName = "鸟") public class Bird extends AbstractAnimal { private static final long serialVersionUID = -5144390780952634397L; public static final String MODEL_MODEL = "demo.Bird"; @Field.Integer @Field(displayName = "翼展宽度") private Integer wingSpanWidth; } 存储模型 存储模型用于定义数据表结构和数据的增删改查(数据管理器)功能,是直接与连接器进行交互的数据容器。 场景:存储模型对应传统开发模式中的数据表,上面例子中的Cat和Birdd都属于传输模型,由于模型定义的注解@Model.Advanced(type = ModelTypeEnum.STORE)默认值就是存储模型,所以一般不用手动指定 代理模型 代理模型是用于代理存储模型的数据管理器能力,同时又可以扩展出非存储数据信息的交互功能的模型。 场景一:隔离数据权限 场景二:增强列表的搜索项 场景三:导入导出的时候增加其他特殊信息 场景四:重写下拉组件的查询逻辑做数据过滤 传输模型 传输模型不会在数据库生成的表,只是作为数据的传输使用,跟传统开发模式中的DTO有一点相似。 场景一:批量处理数据 场景二:处理一些跟数据表无关的操作,如:清理指定业务的缓存、查看一些系统监控信息,可以根据业务信息建立对应的传输模型,在传输模型上创建action动作 场景三:通过传输模型完成复杂页面数据传输

    2024年4月7日
    1.5K00
  • 读写分离

    总体介绍 Oinone的读写分离方案是基于Sharding-JDBC的整合方案,要先具备一些Sharding-JDBC的知识。 [Sharding-JDBC] 读写分离依赖于主从复制来同步数据,从库复制数据后,才能通过读写分离策略将读请求分发到从库,实现读写操作的分流,请根据业务需求自行实现主从配置。 配置读写策略 配置 top_demo 模块走读写分离的逻辑数据源 pamirsSharding。 配置数据源。 为 pamirsSharding 配置数据源以及 sharding 规则。 指定需要被sharding-jdbc接管的模块 指定top_demo模块给 Sharding-JDBC 接管,接管逻辑数据源名为 pamirsSharding pamirs: framework: data: ds-map: base: base top_demo: pamirsSharding 配置数据源 pamirs: datasource: pamirsMaster: driverClassName: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource url: jdbc:mysql://127.0.0.1:3306/61_pamirs_mydemo_master?useSSL=false&allowPublicKeyRetrieval=true&useServerPrepStmts=true&cachePrepStmts=true&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&autoReconnect=true&allowMultiQueries=true username: root password: ma123456 initialSize: 5 maxActive: 200 minIdle: 5 maxWait: 60000 timeBetweenEvictionRunsMillis: 60000 testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true asyncInit: true pamirsSlaver: # 从库数据源配置 driverClassName: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource url: jdbc:mysql://127.0.0.1:3306/61_pamirs_mydemo_slaver?useSSL=false&allowPublicKeyRetrieval=true&useServerPrepStmts=true&cachePrepStmts=true&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&autoReconnect=true&allowMultiQueries=true username: root password: ma123456 initialSize: 5 maxActive: 200 minIdle: 5 maxWait: 60000 timeBetweenEvictionRunsMillis: 60000 testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true asyncInit: true 配置读写数据源及规则 pamirs: sharding: define: data-sources: pamirsSharding: pamirsMaster # 为逻辑数据源pamirsSharding指向主数据源pamirsMaster。 models: "[trigger.PamirsSchedule]": tables: 0..13 rule: pamirsSharding: actual-ds: # 指定逻辑数据源pamirsSharding代理的数据源为pamirsMaster、pamirsSlaver – pamirsMaster – pamirsSlaver # 以下配置跟sharding-jdbc配置一致 replicaQueryRules: – data-sources: pamirsSharding: primaryDataSourceName: pamirsMaster # 写库数据源 replicaDataSourceNames: – pamirsSlaver # 读库数据源 loadBalancerName: round_robin load-balancers: round_robin: type: ROUND_ROBIN # 读写规则

    2025年5月22日
    60800

Leave a Reply

登录后才能评论