跳至主要內容

关系字段

Mr.Hope大约 5 分钟

关系字段

字段类型

业务类型Java类型数据库类型规则说明
O2O模型/DataMap不存储或varchar、text一对一关系
M2O模型/DataMap不存储或varchar、text多对一关系
O2MList<模型/DataMap>不存储或varchar、text一对多关系
M2MList<模型/DataMap>不存储或varchar、text多对多关系

多值字段或者关系字段需要存储,默认使用JSON格式序列化。多值字段数据库字段类型默认为varchar(1024);关系字段数据库字段类型默认为text。

关联关系用于描述模型间的关联方式:

  • 多对一关系,主要用于明确从属关系
  • 一对多关系,主要用于明确从属关系
  • 多对多关系,主要用于弱依赖关系的处理,提供中间模型进行关联关系的操作
  • 一对一关系,主要用于多表继承和行内合并数据

名词解释

关联关系比较重要的名词解释如下:

  • 关联关系:使用relation表示,模型间的关联方式的一种描述,包括关联关系类型、关联关系双边的模型和关联关系的读写
  • 关联关系字段:业务类型ttype为O2O、O2M、M2O或M2M的字段
  • 关联模型:使用references表示,自身模型关联的模型
  • 关联字段:使用referenceFields表示,关联模型的字段,表示关联模型的哪些字段与自身模型的哪些字段建立关系
  • 关系模型:自身模型
  • 关系字段:使用relationFields表示,自身模型的字段,表示自身模型的哪些字段与关联模型的哪些字段建立关系
  • 中间模型,使用through表示,只有多对多存在中间模型,模型的relationship=true

O2M关系类型

O2M跟M2O和M2M不一样,O2M的交互方式新建关联模型记录并一把提交,而M2O和M2M而是通过添加方式选择已有关联模型记录。

O2O关系类型

O2O与M2O相比,在从前端交互体验上跟M2O一样都是下拉单选,但有一个区别在于目标对象只能被一个操作对象绑定。 限制:同时模型的O2O字段关联的模型与本模型必须要在同一模块中,否则会报错。因为O2O字段需要两边对等建立关系字段

M2M关系类型

多对多关系,主要用于弱依赖关系的处理,提供中间模型进行关联关系的操作。这也是在业务开发中很常见用于描述单据间关系,该例子会举例两种方式描述多对多关系中间表,一是中间表没有在系统显示定义模型,二种是中间表显示定义模型。第一种往往仅是维护多对多关系,第二种往往用于多对多关系中间表自身也需要管理有业务含义,中间表模型还经常额外增加其他字段。

一是中间表没有在系统显示定义模型:如果出现跨模块的场景,在分布式环境下两个模块独立启动,有可能会导致系统关系表被删除的情况发生,因为没有显示定义中间表模型,中间表的模型所属模块会根据两边模型的名称计算,如果刚好被计算到非关系字段所属模型的模块。那么单独启动非关系字段所属模型的模块,则会导致删除关系表。

为什么不直接把中间表的模型所属模块设置为关系字段所属模型的模块?因为如果这样做,当模型两边都定义了多对多关系字段则会导致M2M关系表的所属模块出现混乱。

所以这里建议大家都选用:第二种中间表显示定义模型,不论扩展性还是适应性都会好很多。请用:through=XXXRelationModel.MODEL_MODEL 或者 throughClass=XXXRelationModel.class

参数属性

//关联注解
@Field.Relation(store = true, relationFields = "", referenceClass = Empty.class,
               referenceFields = {""}, domainSize = 15, domain = "", context = "",
               search = "", columnSize() = 1024)

//一对一关系
@Field.one2one

//一对多关系
@Field.one2many(limit = -1, pageSize = 20L, ordering = "", inverse = false)

//多对一关系
@Field.many2one()

//多对多关系
@Field.many2many(through = "", throughDisplayName = "", throughClass = Empty.class,
                relationFields = "", referenceFields = "", limit = -1, pageSize = 20L,
                ordering = "")
  • Relation
    • store:是否存储,默认为true
    • relationFields: 自身模型的关系字段,外键,用于取值作为查询条件查询关联模型,与referenceField的字段一一对应,如果relationField与referenceField完全一致,可缺省
    • references:关联模型
    • referenceClass:关联模型class,java模型有class可以填此项
    • referenceFields:关联模型的关联字段,关联模型的唯一索引
    • domainSize:模型筛选可选项每页个数,默认为15
    • domain:模型筛选,数据查询过滤条件
    • context:上下文,查询时前端传入,JSON字符串
    • search:搜索函数(函数编码)
    • columnSize:序列化存储时的存储长度
  • one2many
    • limit:关系数量限制,默认为-1,即不限制
    • pageSize:查询每页个数(前端交互参数)
    • ordering:排序(前端交互参数)
    • inverse:反向关联,关系关联存储在一对多关系的“一”这一端
  • many2many
    • through:中间模型
    • throughDisplayName:中间模型显示名称,如果默认生成的显示名称重复,可以使用该注解解决冲突
    • throughClass:中间模型calss,默认为Empty.class
    • relationFields:中间模型与关系模型的关联字段
    • referenceFields:中间模型与关联模型的关联字段
    • limit:关系数量限制。默认为-1,表示不限制
    • pageSize:查询每页个数(前端交互参数)
    • ordering:排序(前端交互参数)

使用示例

基本用法

@Field.one2one
@Field(displayName = "测试一对一关系")
private PetCatType petCatTypeShow;

@Field.one2many
@Field.Relation(relationFields = {"businessId"},referenceFields = {"code"})
@Field(displayName = "测试一对多关系")
private List<PetShop> petShopList;

@Field.many2one
@Field(displayName = "品种")
private PetDogType type;

@Field.many2many(relationFields = {"petShopId"}, referenceFields = {"petTalentId"}, throughClass = PetShopRelPetTalent.class)
@Field(displayName = "推荐达人", summary = "推荐该商品的达人们")
private List<PetTalent> petTalents;

更多用法

//反向关联,关联关系存储在PetShop这一端
@Field.one2many(inverse = true)
@Field.Relation(relationFields = {"businessId"},referenceFields = {"code"})
@Field(displayName = "测试一对多关系")
private List<PetShop> petShopList;