四赤阳阵の多表视图
最后更新于:2022-04-01 23:47:03
[TOC=3]
> ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/d378f9e8f9b184b4bea76a622179de9f_341x201.png)
> 四赤阳阵是一种结界忍术,比“四紫炎阵”强上数十倍,必须要四位影级人物同时发动。
视图和四赤阳阵非常像,一般视图由多个表组成一个整体进行展示。
### 数据库View的概念
* 传统DB视图,主要用于多表内容聚合展示,不支持直接基于视图进行新增和修改。
* 视图的主要作用是聚合查询,并不是为了自动关联修改。
### 需求的合理性
* 1V1关联表,可以直接操作
* 1VN or NVN 关联,仅提供查询,不应该提供编辑功能
即使隔着屏幕,我仿佛也能感受到你们有些茫然的样子
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/7aee62f28419dd8bff2c7357ca856faa_208x159.png)
但是,相信看完这以下介绍您就会理解。
### 什么是1V1关联表?
~~~
SELECT
`users`.`id` AS `id`,
`users`.`status` AS `status`,
`users`.`login_id` AS `login_id`,
`users`.`login_pwd` AS `login_pwd`,
`users`.`nickname` AS `nickname`,
`users`.`reg_time` AS `reg_time`,
`users`.`info` AS `info`,
`users_exp`.`users_id` AS `users_id`,
`users_exp`.`exp` AS `exp`,
`users_exp`.`avg` AS `avg`,
`users_exp`.`qq` AS `qq`
FROM
(`users` JOIN `users_exp`)
WHERE
(
`users`.`id` = `users_exp`.`users_id`
)
~~~
上面的视图就是 users 1V1 users_exp ,关联条件是 ``users`.`id` = `users_exp`.`users_id``
所以称之为1V1关联,因为用户和用户扩展信息表是通过user id 进行关联的,一个对一个。
**反之除了1V1,其它的都是1VN or NVN**
在进行非1V1业务时,比如:老师和学生
老师有N个学生
学生有N个老师
学生列表
| ID | 姓名 | 我最喜欢的老师 |
| --- | --- | --- |
| 1 | 张三 | 熊雯 |
ID和姓名来自学生表,我的老师的名字来自老师表,通过中间关系表,多表联查形成上面的列表。
但是修改这个列表的时候,显然不能直接将老师的名字给改了并且更新到老师表中。
合理的需求是,可以修改学生的姓名,学生和老师的关系。
但你不能直接改老师名字,你能喜欢英语老师,别人也可以喜欢,你改了名,别人还咋喜欢,都不认识了。
好吧,扯这么多,就是希望大家不要在使用视图的时候陷入误区。
* * * * *
再看一个段子:
问程序员,你会啥?
我会增删改查。
问程序员,软件是啥?
软件除了增删改查,还是增删改查。
貌似听起来没啥毛病吧?
* * * * *
在实际企业级项目中,很少有功能模块是纯单表操作的,多多少少关联其它表的某些字段。
这时候除了增删改查,就是复杂的增删改查了,不是单表的增删改查。
一个业务,需要操作3张以内的表,我们可以简单的说这是一个简单的功能。
一个业务,需要操作5张以内的表,我们还可以说这是一个简单的功能吗。
5张表意味着什么?
5表联查,5表更新,5表。。。。尼玛想想都疼蛋。。。
> PS:所以在设计表结构的时候不要将关系复杂化,应该遵循大事化小小事化了的原则,该冗余的地方就冗余,不要盲目套三大范式,你设计的表是给人用的,不是给老师打分的。
但是往往,肯定会遇到一小波业务就是有那么复杂,需要三表,甚至更多的表,联合作业。
甚至在复杂业务的系统里,这是家常便饭?
怎么破?
> 在经历了很多方案的来回推倒,重写,来回折腾之后最终决定如下!
> 以下方案完全是在无尽的折磨中,尝试出来的,没有参考任何第三方系统和设计,如果雷同,纯属山寨!
> 至于下述方案到底能支撑什么样的业务场景,各位智者见智,应该拥有无限可能!
### EOVA视图处理的设计 V1.6
* 目的:让操作多表,像操作单表一样简单
### 使用思路
* 自建View 提供 元数据导入,支撑复杂的列表查询展现
* 复杂表单后端逻辑通过Aop增强(配合DIY_JS 操控前端)
* 超复杂的自定义按钮,自定义前端Form和后端逻辑
导入视图和导入普通数据表一样,没有什么特殊的地方!
列表查询和展现也没有什么特殊的地方
一个是form table
一个是form view
需求背景描述:
代码: com.oss.order.OrderIntercept By V1.6 OSS Demo
订单关联用户和收获地址:
orders 订单表
users 用户表
address 收获地址表
下面主要描述核心的也是最复杂多变的地方.
新增AOP:
~~~
/**
* 推荐使用Model来实现业务逻辑,万物皆对象,不要问我为什么!
*/
@Override
public String addBefore(AopContext ac) throws Exception {
Record data = ac.record;
// 获取用户信息 保存
Users user = RecordUtil.peelModel(Users.class, data, "login_id", "nickname", "info");
user.save();
int uid = user.getInt("id");
LogKit.info("新增用户成功:" + user.getInt("id"));
// 获取收获信息 保存
Address address = RecordUtil.peelModel(Address.class, data, "name", "full", "mobilephone");
address.save();
int aid = address.getInt("id");
LogKit.info("新增收获信息成功:" + aid);
Orders order = RecordUtil.peelModel(Orders.class, data);
order.set("address_id", aid);
order.set("create_user_id", uid);
order.set("update_user_id", uid);
order.set("create_time", new Date());
order.set("update_time", new Date());
order.save();
LogKit.info("新增订单信息成功:");
return super.addBefore(ac);
}
~~~
修改AOP:
~~~
/**
* 懒人做法Record,一条龙全部搞定,简单粗暴!
*/
@Override
public String updateBefore(AopContext ac) throws Exception {
Record r = ac.record;
// 获取用户信息 更新
Record user = RecordUtil.peel(r, "create_user_id -> id", "login_id", "nickname", "info");
Db.update("users", user);
int uid = user.getInt("id");
LogKit.info("更新用户成功:" + uid);
// 获取收获信息 更新(下面的特殊语法可自行研究源码)
Record address = RecordUtil.peel(r, "address_id -> id", "name", "full", "mobilephone");
Db.update("address", address);
int aid = address.getInt("id");
LogKit.info("更新收获信息成功:" + aid);
Db.update("orders", r);
LogKit.info("更新订单信息成功:");
return super.updateBefore(ac);
}
~~~
> 如上是不是分分钟搞定,复杂的多表业务逻辑!
';