说明

数据库组件是基于gorm实现的,现已升级到2.0版本,支持读写分离与多数据库连接。

配置项

  • 示例

    1. mysql: # mysql配置。支持多数据库,读写分离
    2. maxIdleConnections: 10 # 最大空闲连接数
    3. maxOpenConnections: 40 # 最大打开连接数
    4. maxLifeTime: 8 # 超时时间
    5. dsn: root:123456@tcp(127.0.0.1:3306)/demo?charset=utf8mb4 # 主连接
    6. other: # 另外的库连接
    7. sources: # 主库
    8. - root:123456@tcp(127.0.0.1:3307)/other?charset=utf8mb4
    9. replicas: # 从库
    10. - root:123456@tcp(127.0.0.1:3308)/other?charset=utf8mb4
    11. tables:
    12. - orders # gorm会根据表自动切换连接,及其方便
  • 说明

    • maxIdleConnections: 连接池的最大空闲数
    • maxOpenConnections: 连接池的最大打开连接数
    • maxLifeTime: 超时时间
    • dsn: 数据库相关配置

初始化

一般加载数据库是在main.go里的init函数,连接数据库放在加载配置项成功后。

  1. import (
  2. "github.com/ebar-go/ego/app"
  3. "github.com/ebar-go/ego/component/mysql"
  4. "github.com/ebar-go/egu"
  5. )
  6. func init() {
  7. // 加载配置
  8. egu.SecurePanic(app.Config().LoadFile("app.yaml"))
  9. // 初始化数据库
  10. egu.SecurePanic(app.InitDB())
  11. // 可选,使用集群和多连接配置
  12. egu.SecurePanic(app.DB().Use(mysql.Resolver().Register(mysql.ResolverConfig(mysql.ResolverItem{
  13. Sources: app.Config().GetStringSlice("mysql.other.sources"),
  14. Replicas: app.Config().GetStringSlice("mysql.other.replicas"),
  15. Tables: app.Config().GetStringSlice("mysql.other.tables"),
  16. }))))
  17. }

表结构

  1. drop table if exists users;
  2. create table users (
  3. id int unsigned not null primary key auto_increment comment '主键',
  4. email varchar(255) not null default '' comment '邮箱',
  5. password varchar(32) not null default '' comment '密码',
  6. is_del tinyint unsigned not null default 0 comment '是否删除',
  7. created_at int unsigned not null default 0 comment '创建时间',
  8. updated_at int unsigned not null default 0 comment '更新时间',
  9. key `idx_is_del`(`is_del`),
  10. key `idx_updated_at`(`updated_at`)
  11. )charset=utf8mb4 comment='用户信息';

定义实体

  1. package entity
  2. const (
  3. TableUser = "users" // 表名
  4. // 用户实体
  5. type UserEntity struct {
  6. mysql.BaseEntity
  7. Email string `json:"email" gorm:"column:email"`
  8. Password string `json:"-" gorm:"column:password"`
  9. }
  10. // TableName 指定模型的表名称
  11. func (UserEntity) TableName() string {
  12. return TableUser
  13. }

定义Dao

  • BaseDao.go

    1. package dao
    2. import(...)
    3. const SoftDeleteCondition = "is_del = 0" // 软删除条件
    4. // 基础dao
    5. type BaseDao struct {
    6. db *gorm.DB
    7. }
    8. // Create 创建
    9. func (dao *BaseDao) Create(entity interface{}) error {
    10. return dao.db.Create(entity).Error
    11. }
    12. // Update 更新
    13. func (dao *BaseDao) Update(entity interface{}) error {
    14. return dao.db.Save(entity).Error
    15. }
    16. // Delete 删除
    17. func (dao *BaseDao) Delete(entity interface{}) error {
    18. return dao.db.Model(entity).UpdateColumns(mysql.Columns{
    19. "is_del": 1,
    20. }).Error
    21. }
  • UserDao.go

    1. package dao
    2. import(...)
    3. type userDao struct {
    4. BaseDao
    5. }
    6. func User(db *gorm.DB) *userDao {
    7. return &userDao{BaseDao{
    8. db: db,
    9. }}
    10. }
    11. // GetByUsername 根据用户名获取记录
    12. func (dao *userDao) GetByEmail(email string) (*entity.UserEntity, error) {
    13. query := dao.Table(entity.TableUser).
    14. Where("email = ?", email)
    15. user := new(entity.UserEntity)
    16. if err := query.First(user).Error; err != nil {
    17. return nil, err
    18. }
    19. return user, nil
    20. }
    21. // 分页查询
    22. func (dao *userDao) PaginateQuery(request request.UserQueryRequest) ([]entity.UserEntity, *paginate.Pagination, error) {
    23. query := dao.db.Table(entity.TableUser).Where(SoftDeleteCondition).Order("id desc")
    24. var totalCount int
    25. if err := query.Count(&totalCount).Error; err != nil {
    26. return nil, nil, err
    27. }
    28. pagination := paginate.Paginate(totalCount, request.CurrentPage, request.PageSize)
    29. items := make([]entity.UserEntity, 0)
    30. if err := query.Offset(pagination.GetOffset()).Limit(pagination.Limit).
    31. Scan(&items).Error; err != nil {
    32. return nil, nil, err
    33. }
    34. return items, &pagination, nil
    35. }

使用事务

  1. package service
  2. import(...)
  3. type userService struct {}
  4. // User 用户服务
  5. func User()*userService {
  6. return &userService{}
  7. }
  8. // Register 注册
  9. func (service *userService) Register(req request.UserRegisterRequest) error {
  10. // 将数据库操作包裹在Transaction内部,保证事务执行完整
  11. err := app.DB().Transaction(func(tx *gorm.DB) error {
  12. userDao := dao.User(tx)
  13. // 根据邮箱获取用户信息
  14. user, err := userDao.GetByEmail(req.Email)
  15. if err != nil && err != gorm.ErrRecordNotFound {
  16. return fmt.Errorf("获取用户信息失败:%v", err)
  17. }
  18. // 用户已存在
  19. if user != nil {
  20. return fmt.Errorf("该邮箱已被注册")
  21. }
  22. now := int(date.GetLocalTime().Unix())
  23. user = new(entity.UserEntity)
  24. user.Email = req.Email
  25. user.Password = strings.Md5(req.Pass)
  26. user.CreatedAt = now
  27. user.UpdatedAt = now
  28. return userDao.Create(user)
  29. })
  30. if err != nil {
  31. return errors.New(enum.DatabaseSaveFailed, fmt.Sprintf("保存数据失败:%v", err))
  32. }
  33. return nil
  34. }