4.2 数据模型的扩充处理

4.2.1 分离字段存储到Redis中

在上一个章节中,我们能够正常的读写数据库,创建一条提示词。但是其中

type Prompts struct {
    ...
    ...
    Body string `json:"Body" form:"Body" gorm:"column:body;comment:;type:text;"`
}

这里的Body(提示词正文)部分还是以TEXT的方式保存在MySQL的。

如果我们想要将其放在Redis中,那么需要对Model进行一些改造,而且在改造以后要对业务透明。这样我们的业务逻辑不需要去管存储介质和存储路径。

type Prompts struct {
    ...
    ...
    Body string `json:"Body" form:"Body" gorm:"-:all"`
}

通过将gorm:"-:all"将这个字段从orm的绑定上删除,这样读写的时候gorm不会管这个字段。

然后在模型中补充两个函数:


func (p *Prompts) AfterCreate(tx *gorm.DB) (err error) {
    // 将Redis中存储键交给getRedisKey,而不是每次自己拼凑,防止拼写错误
	redisKey := p.getRedisKey()
	if global.GVA_REDIS == nil {
		return fmt.Errorf("Redis客户端未初始化")
	}
	err = global.GVA_REDIS.Set(context.Background(), redisKey, p.Body, 0).Err()
	return nil
}

// 根据记录的MySQL中的主键值返回Redis中存储的键名
func (p *Prompts) getRedisKey() string {
	return fmt.Sprintf("prompt_body:%d", p.ID)
}

我们再执行CreatePrompts的时候,就会自动将数据保存到Redis,并且当插入Redis失败的时候,会自动回滚MySQL的插入操作,以保证数据一致性。

4.2.2 读取数据时,自动补全Redis中的字段

func (p *Prompts) AfterFind(tx *gorm.DB) (err error) {
  // 获取Key,详见上一章
  redisKey := p.getRedisKey()

  // 从Redis获取Value
  if global.GVA_REDIS != nil {
    p.Body, _ = global.GVA_REDIS.Get(redisKey).Result()
  }

  return 
}
  • 对于Service而言,不关心Model写入数据的逻辑细节,只需要获取其所需的数据,并且做完业务加工以后,扔给Model处理就行;

  • 同样对于Controller而言,抑不关心Service的实现,只需要做好数据的验证和参数的获取,然后调用不同的Service协作完成任务。

在传统的软件架构中,模型(Model)、服务(Service)和控制器(Controller)各执其职,它们共同工作以实现软件的业务逻辑和数据处理。那么到底应该谁轻谁重呢?

模型(Model):

  • 应该相对轻:模型通常是轻量级的,只定义数据结构和数据库层面的操作。它们应包含数据验证和基本的方法来表达它们的直接数据关系,但避免包含业务逻辑。

  • 为什么:使模型保持轻量可以增加代码的可复用性,并避免模型变得过于复杂,这样在业务逻辑变更时,模型层通常无需变动。

服务(Service):

  • 应该相对重:服务层是应用程序的核心,它应包含大部分的业务逻辑。服务层作为模型和控制器之间的桥梁,负责编排模型方法的调用,处理复杂的业务规则,以及确保数据传输对象和领域模型之间的数据映射。

  • 为什么:将业务逻辑放在服务层可以实现逻辑的集中管理,便于测试和维护,并且可以在不同的控制器之间重用服务逻辑。

控制器(Controller):

  • 应该相对轻:控制器负责接收用户请求并将请求传递给 Service 层。还负责将 Service 层的响应返回给用户。

  • 为什么:轻控制器使得代码更易于阅读和维护,因为它们的工作仅仅是请求的入口和出口点。这种分离也使得控制器成为一种轻薄的适配层,容易适应外部接口的变化。

通过这种分层方式,可以增加应用程序的灵活性和可维护性。服务层的“重”使得业务逻辑更集中、更有条理,而模型和控制器的“轻”则使得系统的其他部分更加灵活,易于适应变化。这样的架构也有利于实现关注点分离(Separation of Concerns),每一层只关心其职责范围内的问题,便于团队协作和代码管理。

Last updated