数据库设计
数据库设计是底层,关乎代码质量与可阅读性,如果说你要筑起大厦,数据库就是地基。你不想来一个大换血对吧,那就要好好思考数据库的设计。
首先你得给表起一个名字。
就拿cluster和node来说,cluster里面很多node。
为确定唯一cluster,我们为cluster单独建一张表,有很多元素可以描述cluster,其中包括id,id设计为自动递增,cluster_name, status描述当前状态,ctreate_time,update_time方便查询记录,如果说我忘了cluster名字,但我可以通过时间追溯。有些字段可以在后面设计陆续添加。
node存在于cluster,通过nodeId和clusterId确定唯一一个node,有多元素可以描述node,如node_id,node_name, cluster_id绑定cluster的id,status1,status2…标记当前node的状态。有些字段可以在后面设计陆续添加。
如何将cluster的id和node里面的cluster_id关联起来?
你创建一个cluster,前端肯定会送过来一个cluster_name,把他放到数据库里面,然后你在controller里面通过cluster_name获取唯一cluster,拿到你刚创建的cluster然后取出其id,创建node的时候,再把这个cluster的id送过去。
id设计为自动递增 类型为int 长度为11 小数点为0
数字 类型为int 长度为11 小数点为0
字符串 类型为varchar 长度一般为128 小数点为0
时间 类型为timestamp 长度为0 小数点为0
浮点型的数据你就当字符串去保存,用的时候只需要把字符串转为浮点型即可。
数据库表结构的设计:关于varchar的总结
参考文章:敲码前洗一波脑 后台开发
GORM 中文文档:
go mod tidy
go get github.com/jinzhu/gorm
https://jasperxu.com/Programming/Golang/GORM/
https://learnku.com/docs/gorm/v2
数据库设计与代码关联起来
数据库你想要查询记录,你忘了名字,但你可以通过时间追溯
新增字段:create_time update_time 类型: timestamp
你在module写:
type Cluster struct {
Id int `json:"id"`
Cluster_name string `json:"cluster_name"`
Cluster_status int `json:"cluster_status"`
Create_time string `json:"create_time"`
Update_time string `json:"update_time"`
}
这样你返回的json,开头都是小写,本身是结构体的字段会根据tag解析到对应的json里面。
你在dao里面写
func (dto *ClusterDao) CreateCluster (clusterName string) models.Cluster {
var cluster models.Cluster
cluster.Cluster_name = clusterName
cluster.Cluster_status = 0
cluster.Create_time = utils.GetlocalTime()
cluster.Update_time = utils.GetlocalTime()
db := GetDb()
db.Table("cluster").Create(&cluster)//&很重要,就是这个&把db查询到的数据赋值给了cluster
return cluster
}
代码run起来
执行的语句:
INSERT INTO `cluster` (`cluster_name`,`cluster_status`,`create_time`,`update_time`) VALUES ('test42',0,'2021-06-25 15:14:09','2021-06-25 15:14:09')
insert into casbin_rule (v1,v3) values ('/move/cdddddter/cddddrs/create','root');
insert数据的时候,有些数据你不写
instert的时候,有些字段你不能写,就比如时间,id,id是自动递增的。
insert into cluster (cluster_name,cluster_status) values ('lala',5);
实体操作
查看list
功能:支持分页查看,当前页和limit,模糊匹配or强匹配,模块复用。
分页查看?
没有输入当前页和limit,当前页默认为1,limit默认为n
list模块复用?
就是你一个clusterlist可以通过clusterName或者clusterId去查看。
什么时候用模糊匹配,什么时候用强匹配?
我无法精确的去定位一条数据,比如淘宝的某一家店的某一条裙子,这个时候我就会输入关键词,模糊匹配。强匹配,我非常清楚我要查找的数据,如学生管理系统,输入学号便可以查找唯一一条信息。
dao这里这么写
/*
ClusterListByClusterMsg:查看clusterList
clusterMsg:可能是clusterId,clusterName,模块复用
limitInt:页面显示多少条数据
pageInt:当前页
*/
func (dao *ClusterDao) ClusterListByClusterMsg(clusterMsg string, limitInt, pageInt int) ([]models.Cluster, int) {
var clusters []models.Cluster
db := GetDb()
var total int
clusterIdInt,err := strconv.Atoi(clusterMsg)//如果能转成数字,说明是clusterId,不行则是clusterName
if err != nil {
db.Table("cluster").Where("cluster_name = ?", clusterMsg).Count(&total)
if limitInt == 0 && pageInt == 0 {//默认设置limit和page
limitInt = 10
pageInt = 1
}else{//边界页的设置
totali := limitInt * pageInt
pageInti := total / limitInt
if (pageInti*limitInt) < totali && totali < ((pageInti+1)*limitInt) {
limitInt = total % limitInt
}
if pageInt > pageInti+1 {
return nil, total
}
fmt.Print("totoai-->",totali,"total-->",total)
}
db.Table("cluster").Where("cluster_name = ?", clusterMsg).Limit(limitInt).Offset((pageInt - 1) * limitInt).Find(&clusters)
}else{
db.Table("cluster").Where("cluster_id = ?", clusterIdInt).Count(&total)
if limitInt == 0 && pageInt == 0 {
limitInt = 10
pageInt = 1
}else{
totali := limitInt * pageInt
pageInti := total / limitInt
if (pageInti*limitInt) < totali && totali < ((pageInti+1)*limitInt) {
limitInt = total % limitInt
}
if pageInt > pageInti+1 {
return nil, total
}
fmt.Print("totoai-->",totali,"total-->",total)
}
db.Table("cluster").Where("cluster_id = ?", jobIdInt).Limit(limitInt).Offset((pageInt - 1) * limitInt).Find(&clusters)
}
return clusters, total
}
create实体
你想传实体给service
我们传值能不用指针就不用指针。
不用指针
dao–>db这里
在db里面设置clusterId自动递增,那么你往db里面插入数据,可以不用赋值给clusterId。
func (dao *ClusterDao) CreateCluster (clusterName string) models.Cluster {
var cluster models.Cluster
cluster.Cluster_name = clusterName
cluster.Cluster_status = 0
cluster.Create_time = utils.GetlocalTime()
cluster.Update_time = utils.GetlocalTime()
db := GetDb()
db.Table("cluster").Create(&cluster)//&很重要,就是这个&把db查询到的数据赋值给了cluster
return cluster
}
service这里
cluster := ms.dao.CreateCluster(clusterName)
if cluster != (models.Cluster {}) {//判断结构体是否被赋值
fmt.Println("ClusterId--->",cluster.Cluster_id)
}
非得用指针
service这里
newCluster := &models.Cluster{//&就注定它是一个指针
Cluster_id: cluster_id,
Cluster_name: cluster_name,
Node_num: node_num,
}
cluster := ms.dao.CreateCluster(newCluster)
if cluster != nil {//判断指针是否成功赋值
fmt.Println("ClusterId--->",cluster.Cluster_id)
}
dao这里
func (dao *ClusterDao) CreateCluster (cluster *models.Cluster) *models.Cluster{
db := GetDb()
db.Table("cluster").Create(cluster)
return cluster
}
get实体
通过主键获取实体
func (dao *Cluster) GetClusterById(nodeIdInt, podIdInt int) models.Cluster {
var cluster models.Cluster
db.Table("cluster").Where("node_id = ? and pod_id = ?", nodeIdInt, podIdInt).First(&cluster)
return cluster
}
service
func (ms *JobService)GetJobById(jobId string) models.Job {
jobIdInt, _ := strconv.Atoi(jobId)
return ms.dao.GetJobById(jobIdInt)
}
controller
job := jobService.GetJobById(jobId)
if job == (models.Job{}) {
return errors.New(fmt.Sprintf("job_id=%v :数据不存在 ", jobId))
}
判断结构体是否为空
job == (models.Job{})
获取列表
controller
name := c.PostForm("name")
cluster := c.PostForm("cluster")
user := c.PostForm("user")
if self.BindAndValidate(c, &name) {
if name == "" || cluster == "" {
log.Error("参数错误")
}
data := nameSpaceService.CreateNameSpace(name,cluster,user)
self.Resp(c, map[string]interface{}{
"data": data,
})
}
service
func (ms *NameSpaceService) NameSpaceList (page, limit string) ([]models.NameSpace, int) {
pageInt, _ := strconv.Atoi(page)
limitInt, _ := strconv.Atoi(limit)
data, total := ms.dao.NameSpaceList(pageInt, limitInt)
return data, total
}
dao
func (dao *NameSpaceDao) NameSpaceList (pageInt, limitInt int) ([]models.NameSpace, int){
var nameSpaces []models.NameSpace
db := GetDb()
var total int
if limitInt == 0 && pageInt == 0 {
limitInt = 10
pageInt = 1
}
db.Table("namespace").Limit(limitInt).Offset((pageInt - 1) * limitInt).Find(&nameSpaces)
db.Table("namespace").Count(&total)
return nameSpaces, total
}
update实体
dao这里
func (dao *ClusterDao) UpdateClusterById (cluster models.Cluster) int64{
cluster.Update_time = utils.GetlocalTime()
c := db.Table("cluster").Where("node_id = ? and pod_id = ?", cluster.Node_id, cluster.Pod_id).Updates(cluster)
return c.RowsAffected
}
service这里
cluster.Cluster_status = 1
affected := ms.dao.UpdateClusterById (cluster)
if affected <= 0 {
return errors.New("fail to update")
}else{
fmt.Println("更新成功“)
}
delete实体
dao这里
func (dao *ClusterDao) DeleteClusterById(id string) int64 {
var cluster models.Cluster
db := GetDb()
c := db.Table("cluster").Where("id = ?", id).Delete(&cluster)
return c.RowsAffected
}
数据库表结构设计与优化
参考文章:数据库性能优化之表结构