mysql 代码生成

mysql 代码生成

MySQL 用法

概述

mysql 代码生成支持从 sql 文件和数据库链接生成, 且支持生成带缓存逻辑代码。

mysql 生成的代码内容有数据表对应的 golang 结构体、CURD 操作方法,缓存逻辑等信息,更多详细的数据库代码生成可参考指南 goctl model

任务目标

  1. 熟悉 goctl 生成 mysql 代码的命令使用,了解目前支持的指令和功能
  2. 初步了解 goctl 生成 mysql 代码的格式
  3. 初步掌握从 sql 文件编写到 mysql 代码的生成流程

准备条件

  1. 完成 golang 安装
  2. 完成 goctl 安装

代码生成

  1. 首先执行如下指令将示例 sql 文件存储到本地的 user.sql 文件中。
CREATE TABLE user (
    id bigint AUTO_INCREMENT,
    name varchar(255) NULL COMMENT 'The username',
    password varchar(255) NOT NULL DEFAULT '' COMMENT 'The user password',
    mobile varchar(255) NOT NULL DEFAULT '' COMMENT 'The mobile phone number',
    gender char(10) NOT NULL DEFAULT 'male' COMMENT 'gender,male|female|unknown',
    nickname varchar(255) NULL DEFAULT '' COMMENT 'The nickname',
    type tinyint(1) NULL DEFAULT 0 COMMENT 'The user type, 0:normal,1:vip, for test golang keyword',
    create_at timestamp NULL,
    update_at timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    UNIQUE mobile_index (mobile),
    UNIQUE name_index (name),
    PRIMARY KEY (id)
) ENGINE = InnoDB COLLATE utf8mb4_general_ci COMMENT 'user table';
  1. 新建工作空间和目录工程
$ mkdir -p ~/workspace/model/mysql
  1. 将上文中存储的 user.sql 文件移动到 ~/workspace/model/mysql 目录下

  2. 生成 model 代码

$ cd ~/workspace/model/mysql
$ goctl model mysql ddl --src user.sql --dir .
Done.

当你看到 Done. 输出则代表生成成功了,接下来我们来看一下生成的代码内容:

## 列出当前目录下的文件
$ ls
user.sql         usermodel.go     usermodel_gen.go vars.go
## 查看目录树
$ tree
.
├── user.sql
├── usermodel.go
├── usermodel_gen.go
└── vars.go

0 directories, 4 files
  1. 代码查看

    • user.sql
    • usermodel.go
    • usermodel_gen.go
    • vars.go
CREATE TABLE user (
    id bigint AUTO_INCREMENT,
    name varchar(255) NULL COMMENT 'The username',
    password varchar(255) NOT NULL DEFAULT '' COMMENT 'The user password',
    mobile varchar(255) NOT NULL DEFAULT '' COMMENT 'The mobile phone number',
    gender char(10) NOT NULL DEFAULT 'male' COMMENT 'gender,male|female|unknown',
    nickname varchar(255) NULL DEFAULT '' COMMENT 'The nickname',
    type tinyint(1) NULL DEFAULT 0 COMMENT 'The user type, 0:normal,1:vip, for test golang keyword',
    create_at timestamp NULL,
    update_at timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    UNIQUE mobile_index (mobile),
    UNIQUE name_index (name),
    PRIMARY KEY (id)
) ENGINE = InnoDB COLLATE utf8mb4_general_ci COMMENT 'user table';
``` ```
package mysql

import "github.com/zeromicro/go-zero/core/stores/sqlx"

var _ UserModel = (*customUserModel)(nil)

type (
    // UserModel is an interface to be customized, add more methods here,
    // and implement the added methods in customUserModel.
    UserModel interface {
        userModel
    }

    customUserModel struct {
        *defaultUserModel
    }
)

// NewUserModel returns a model for the database table.
func NewUserModel(conn sqlx.SqlConn) UserModel {
    return &customUserModel{
        defaultUserModel: newUserModel(conn),
    }
}
``` ```
// Code generated by goctl. DO NOT EDIT.

package mysql

import (
    "context"
    "database/sql"
    "fmt"
    "strings"
    "time"

    "github.com/zeromicro/go-zero/core/stores/builder"
    "github.com/zeromicro/go-zero/core/stores/sqlc"
    "github.com/zeromicro/go-zero/core/stores/sqlx"
    "github.com/zeromicro/go-zero/core/stringx"
)

var (
    userFieldNames          = builder.RawFieldNames(&User{})
    userRows                = strings.Join(userFieldNames, ",")
    userRowsExpectAutoSet   = strings.Join(stringx.Remove(userFieldNames, "`id`", "`update_time`", "`create_at`", "`created_at`", "`create_time`", "`update_at`", "`updated_at`"), ",")
    userRowsWithPlaceHolder = strings.Join(stringx.Remove(userFieldNames, "`id`", "`update_time`", "`create_at`", "`created_at`", "`create_time`", "`update_at`", "`updated_at`"), "=?,") + "=?"
)

type (
    userModel interface {
        Insert(ctx context.Context, data *User) (sql.Result, error)
        FindOne(ctx context.Context, id int64) (*User, error)
        FindOneByMobile(ctx context.Context, mobile string) (*User, error)
        FindOneByName(ctx context.Context, name sql.NullString) (*User, error)
        Update(ctx context.Context, data *User) error
        Delete(ctx context.Context, id int64) error
    }

    defaultUserModel struct {
        conn  sqlx.SqlConn
        table string
    }

    User struct {
        Id       int64          `db:"id"`
        Name     sql.NullString `db:"name"`     // The username
        Password string         `db:"password"` // The user password
        Mobile   string         `db:"mobile"`   // The mobile phone number
        Gender   string         `db:"gender"`   // gender,male|female|unknown
        Nickname string         `db:"nickname"` // The nickname
        Type     int64          `db:"type"`     // The user type, 0:normal,1:vip, for test golang keyword
        CreateAt sql.NullTime   `db:"create_at"`
        UpdateAt time.Time      `db:"update_at"`
    }
)

func newUserModel(conn sqlx.SqlConn) *defaultUserModel {
    return &defaultUserModel{
        conn:  conn,
        table: "`user`",
    }
}

func (m *defaultUserModel) Delete(ctx context.Context, id int64) error {
    query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
    _, err := m.conn.ExecCtx(ctx, query, id)
    return err
}

func (m *defaultUserModel) FindOne(ctx context.Context, id int64) (*User, error) {
    query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", userRows, m.table)
    var resp User
    err := m.conn.QueryRowCtx(ctx, &resp, query, id)
    switch err {
    case nil:
        return &resp, nil
    case sqlc.ErrNotFound:
        return nil, ErrNotFound
    default:
        return nil, err
    }
}

func (m *defaultUserModel) FindOneByMobile(ctx context.Context, mobile string) (*User, error) {
    var resp User
    query := fmt.Sprintf("select %s from %s where `mobile` = ? limit 1", userRows, m.table)
    err := m.conn.QueryRowCtx(ctx, &resp, query, mobile)
    switch err {
    case nil:
        return &resp, nil
    case sqlc.ErrNotFound:
        return nil, ErrNotFound
    default:
        return nil, err
    }
}

func (m *defaultUserModel) FindOneByName(ctx context.Context, name sql.NullString) (*User, error) {
    var resp User
    query := fmt.Sprintf("select %s from %s where `name` = ? limit 1", userRows, m.table)
    err := m.conn.QueryRowCtx(ctx, &resp, query, name)
    switch err {
    case nil:
        return &resp, nil
    case sqlc.ErrNotFound:
        return nil, ErrNotFound
    default:
        return nil, err
    }
}

func (m *defaultUserModel) Insert(ctx context.Context, data *User) (sql.Result, error) {
    query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?)", m.table, userRowsExpectAutoSet)
    ret, err := m.conn.ExecCtx(ctx, query, data.Name, data.Password, data.Mobile, data.Gender, data.Nickname, data.Type)
    return ret, err
}

func (m *defaultUserModel) Update(ctx context.Context, newData *User) error {
    query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, userRowsWithPlaceHolder)
    _, err := m.conn.ExecCtx(ctx, query, newData.Name, newData.Password, newData.Mobile, newData.Gender, newData.Nickname, newData.Type, newData.Id)
    return err
}

func (m *defaultUserModel) tableName() string {
    return m.table
}
``` ```
package mysql

import "github.com/zeromicro/go-zero/core/stores/sqlx"

var ErrNotFound = sqlx.ErrNotFound