十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
通过 AUTO_INCREMENT设置SQL INSERT语句的时候,要避免 指定那个自增的字段.否则会发生主键的冲突。通过 ALTER TABLE语句 可以修改 自增的数值, 但是只能增加,不能减少。TRUNCATE TABLE 语句,会将自增ID重置为零。mysql CREATE TABLE test_c...
让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:域名注册、雅安服务器托管、营销软件、网站建设、宝安网站维护、网站推广。
增加 json 格式的扩展字段。
下面配合一些代码来描述这个解决方案,读者便于去理解。
mysql 数据库脚本:
DROP TABLE IF EXISTS `cs_dustbin`;
CREATE TABLE IF NOT EXISTS `cs_dustbin` (
`id` VARCHAR(45) NOT NULL COMMENT '主键自增id',
`rfid_no` VARCHAR(20) NOT NULL COMMENT 'rfid 卡号',
`state` INT(1) NOT NULL COMMENT '垃圾桶状态:0:已注销;1:未使用;2:待使用;3:已使用(绑定收集点);',
`user_id` INT NOT NULL COMMENT '登记人,负责录入垃圾桶的人',
`type` INT(1) NOT NULL DEFAULT 1 COMMENT '垃圾桶类型:1:餐厨垃圾桶',
`street_code` INT(11) DEFAULT NULL COMMENT '所在镇街 code,根据状态,这里的含义可能是领用镇街、退还镇街。',
`create_time` DATETIME NOT NULL DEFAULT now() COMMENT '创建时间',
`update_time` DATETIME NOT NULL DEFAULT now() COMMENT '更新时间',
`ext` VARCHAR(1000) NOT NULL DEFAULT '{}' COMMENT '扩展字段',
...
PRIMARY KEY (`id`))
ENGINE = InnoDB
COMMENT = '垃圾桶表';
复制代码Java 代码:
import com.alibaba.fastjson.JSON;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.List;
/**
* 垃圾桶实体
* Created by Blink on 6/28/2018 AD.
*
* @author Blink
*/
@Data
public class Dustbin {
private String id;
/**
* rfid 卡号
*/
@NotNull
private String rfidNo;
/**
* 垃圾桶状态:0:已注销;1:未使用;2:待使用;3:已使用(绑定收集点);
* 对应 Dustbin.StateEnum 类
*/
@NotNull
private Integer state;
/**
* 录入垃圾桶的人员id
*/
@NotNull
private Long userId;
/**
* 垃圾桶类型:1:餐厨垃圾桶
* DefaultValue: 1
*/
@NotNull
private Integer type;
/**
* 所在镇街 code
* 根据状态,这里的含义可能是领用镇街、退还镇街
*/
private Integer streetCode;
/**
* 创建时间
* defaultValue : now()
*/
@NotNull
private Date createTime;
/**
* 更新时间
*/
@NotNull
private Date updateTime;
/**
* 扩展字段,详细数据查看 DustbinExt.java
* DefaultValue: {}
*/
private String ext;
...
public DustbinExt getExtObject() {
return JSON.parseObject(this.getExt(), DustbinExt.class);
}
public void setExtObject(DustbinExt ext) {
this.ext = JSON.toJSONString(ext);
}
/**
* 垃圾桶扩展属性
* Created by Blink on 6/28/2018 AD.
*
* @author Blink
*/
@Data
public static class DustbinExt {
/**
* 所在镇街
* 根据状态,这里的含义可能是领用镇街、退还镇街、绑定的镇街
*/
private String street;
/**
* 客户(收集点)id,绑定收集点的时候需要填入
* 根据目前的需求(2018-06-29),当收集点解绑的时候
* 需要保存垃圾桶最新绑定收集点名称,所以在解绑垃圾桶的时候不会把这个信息删掉
* 只有当绑定收集点的时候才把他覆盖
*/
private Long customerId;
/**
* 客户(收集点)名称,绑定收集点的时候需要填入
* 根据目前的需求(2018-06-29),当收集点解绑的时候
* 需要保存垃圾桶最新绑定收集点名称,所以在解绑垃圾桶的时候不会把这个信息删掉
* 只有当绑定收集点的时候才把他覆盖
*/
private String customer;
/**
* 损坏部位
* 1:桶盖;2:桶口;3:桶身;4:桶轴;5:桶底;6:桶轮;
* 对应 DustbinDamagePartEnum 类
*/
private ListInteger parts;
}
...
}
复制代码mysql 脚本可以看到扩展字段的信息:
ext VARCHAR(1000) NOT NULL DEFAULT '{}' COMMENT '扩展字段'
复制代码可以看到这么一段 Java 代码:
...
/**
* 扩展字段,详细字段查看 DustbinExt 类
* DefaultValue: {}
*/
private String ext;
public DustbinExt getExtObject() {
return JSON.parseObject(this.getExt(), DustbinExt.class);
}
public void setExtObject(DustbinExt ext) {
this.ext = JSON.toJSONString(ext);
}
...
复制代码可以看到 ext 字段就是用来存储 json 格式的数据,它可以动态地增加任何字段,甚至是对象,不需要通过 DDL(Data Definition Language) 去创建字段,非常适合用来解决上面提到的问题。
Java 代码在这里起到辅助性作用,通过定义一个内部类来管理扩展字段的属性,方便我们了解和管理扩展字段,提高代码的可读性和可维护性,java 这种方式也是笔者总结出来的较为优雅的做法(个人观点)。
局限性
有经验的读者可能会提出,ext 字段在 Mysql 5.7.8 以下版本无法对扩展字段中的某一个或一部分字段建立索引,因为 Mysql 5.7.8 版本以下不支持(Mysql 5.7.8 支持为 Json Data Type 建立索引)。
没错,这是这个解决方案的一个局限性,在 Mysql 5.7.8 以下版本,我的建议是, ext 扩展字段不要存储热点数据,只存储非热点数据,这样就可以避免查询操作,降低维护 ext 字段带来的成本和风险,那如何识别新增字段是不是热点数据呢?这个需要结合实际业务需求来判断,也可以询问对业务和技术更有经验的同事,便于读者更快得出结论。
终极版解决方案
在一些极端的情况下,变化可能来得太快,而我们要的是减少变化带来的成本和风险,所以在表设计之初可以根据自身经验,或者找更有经验的人寻求帮助,预估一下需要预留多少个备用字段,再配合扩展字段,基本上可以把改变(添加字段)表结构的次数降至一个非常少的次数。
总结
在特殊情况下,通过扩展字段 + 预留字段基本上可以做到动态扩展字段,又不会影响为热点数据建立索引的情况,这样我们得到了一个非常灵活的表结构,便于我们应对未来的变化,但是请注意,要维护好我们的实体,包括里面的每一个字段,敬畏每一行代码。
你如果想要给表增加一个字段,那么有很多种方法可以完成,比如说直接add一个字段在add的后面写上字段的名称和属性。