Browse Source

feature model interface (#222)

* make variable declaration more concise

* add model interface

* optimize interface methods

* fix: go test failed

* warp returns

* optimize
Keson 4 years ago
parent
commit
6e57f6c527

+ 211 - 176
tools/goctl/model/sql/README.MD

@@ -7,7 +7,7 @@ goctl model 为go-zero下的工具模块中的组件之一,目前支持识别m
 * 通过ddl生成
 * 通过ddl生成
 
 
     ```shell script
     ```shell script
-    goctl model mysql ddl -src="./*.sql" -dir="./sql/model" -c=true
+    goctl model mysql ddl -src="./*.sql" -dir="./sql/model" -c
     ```
     ```
 
 
     执行上述命令后即可快速生成CURD代码。
     执行上述命令后即可快速生成CURD代码。
@@ -29,156 +29,191 @@ goctl model 为go-zero下的工具模块中的组件之一,目前支持识别m
 	```go
 	```go
 
 
 	package model
 	package model
+    
+    import (
+    	"database/sql"
+    	"fmt"
+    	"strings"
+    	"time"
+    
+    	"github.com/tal-tech/go-zero/core/stores/cache"
+    	"github.com/tal-tech/go-zero/core/stores/sqlc"
+    	"github.com/tal-tech/go-zero/core/stores/sqlx"
+    	"github.com/tal-tech/go-zero/core/stringx"
+    	"github.com/tal-tech/go-zero/tools/goctl/model/sql/builderx"
+    )
+    
+    var (
+    	userFieldNames          = builderx.FieldNames(&User{})
+    	userRows                = strings.Join(userFieldNames, ",")
+    	userRowsExpectAutoSet   = strings.Join(stringx.Remove(userFieldNames, "id", "create_time", "update_time"), ",")
+    	userRowsWithPlaceHolder = strings.Join(stringx.Remove(userFieldNames, "id", "create_time", "update_time"), "=?,") + "=?"
+    
+    	cacheUserPrefix       = "cache#User#user#"
+    	cacheUserNamePrefix   = "cache#User#name#"
+    	cacheUserMobilePrefix = "cache#User#mobile#"
+    	cacheUserIdPrefix     = "cache#User#id#"
+    )
+    
+    type (
+    	UserModel interface {
+    		Insert(data User) (sql.Result, error)
+    		FindOne(id int64) (*User, error)
+    		FindOneByUser(user string) (*User, error)
+    		FindOneByName(name string) (*User, error)
+    		FindOneByMobile(mobile string) (*User, error)
+    		Update(data User) error
+    		Delete(id int64) error
+    	}
+    
+    	defaultUserModel struct {
+    		sqlc.CachedConn
+    		table string
+    	}
+    
+    	User struct {
+    		Id         int64     `db:"id"`
+    		User       string    `db:"user"`     // 用户
+    		Name       string    `db:"name"`     // 用户名称
+    		Password   string    `db:"password"` // 用户密码
+    		Mobile     string    `db:"mobile"`   // 手机号
+    		Gender     string    `db:"gender"`   // 男|女|未公开
+    		Nickname   string    `db:"nickname"` // 用户昵称
+    		CreateTime time.Time `db:"create_time"`
+    		UpdateTime time.Time `db:"update_time"`
+    	}
+    )
+    
+    func NewUserModel(conn sqlx.SqlConn, c cache.CacheConf) UserModel {
+    	return &defaultUserModel{
+    		CachedConn: sqlc.NewConn(conn, c),
+    		table:      "user",
+    	}
+    }
+    
+    func (m *defaultUserModel) Insert(data User) (sql.Result, error) {
+    	userKey := fmt.Sprintf("%s%v", cacheUserPrefix, data.User)
+    	userNameKey := fmt.Sprintf("%s%v", cacheUserNamePrefix, data.Name)
+    	userMobileKey := fmt.Sprintf("%s%v", cacheUserMobilePrefix, data.Mobile)
+    	ret, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
+    		query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?)", m.table, userRowsExpectAutoSet)
+    		return conn.Exec(query, data.User, data.Name, data.Password, data.Mobile, data.Gender, data.Nickname)
+    	}, userMobileKey, userKey, userNameKey)
+    	return ret, err
+    }
+    
+    func (m *defaultUserModel) FindOne(id int64) (*User, error) {
+    	userIdKey := fmt.Sprintf("%s%v", cacheUserIdPrefix, id)
+    	var resp User
+    	err := m.QueryRow(&resp, userIdKey, func(conn sqlx.SqlConn, v interface{}) error {
+    		query := fmt.Sprintf("select %s from %s where id = ? limit 1", userRows, m.table)
+    		return conn.QueryRow(v, query, id)
+    	})
+    	switch err {
+    	case nil:
+    		return &resp, nil
+    	case sqlc.ErrNotFound:
+    		return nil, ErrNotFound
+    	default:
+    		return nil, err
+    	}
+    }
+    
+    func (m *defaultUserModel) FindOneByUser(user string) (*User, error) {
+    	userKey := fmt.Sprintf("%s%v", cacheUserPrefix, user)
+    	var resp User
+    	err := m.QueryRowIndex(&resp, userKey, m.formatPrimary, func(conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
+    		query := fmt.Sprintf("select %s from %s where user = ? limit 1", userRows, m.table)
+    		if err := conn.QueryRow(&resp, query, user); err != nil {
+    			return nil, err
+    		}
+    		return resp.Id, nil
+    	}, m.queryPrimary)
+    	switch err {
+    	case nil:
+    		return &resp, nil
+    	case sqlc.ErrNotFound:
+    		return nil, ErrNotFound
+    	default:
+    		return nil, err
+    	}
+    }
+    
+    func (m *defaultUserModel) FindOneByName(name string) (*User, error) {
+    	userNameKey := fmt.Sprintf("%s%v", cacheUserNamePrefix, name)
+    	var resp User
+    	err := m.QueryRowIndex(&resp, userNameKey, m.formatPrimary, func(conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
+    		query := fmt.Sprintf("select %s from %s where name = ? limit 1", userRows, m.table)
+    		if err := conn.QueryRow(&resp, query, name); err != nil {
+    			return nil, err
+    		}
+    		return resp.Id, nil
+    	}, m.queryPrimary)
+    	switch err {
+    	case nil:
+    		return &resp, nil
+    	case sqlc.ErrNotFound:
+    		return nil, ErrNotFound
+    	default:
+    		return nil, err
+    	}
+    }
+    
+    func (m *defaultUserModel) FindOneByMobile(mobile string) (*User, error) {
+    	userMobileKey := fmt.Sprintf("%s%v", cacheUserMobilePrefix, mobile)
+    	var resp User
+    	err := m.QueryRowIndex(&resp, userMobileKey, m.formatPrimary, func(conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
+    		query := fmt.Sprintf("select %s from %s where mobile = ? limit 1", userRows, m.table)
+    		if err := conn.QueryRow(&resp, query, mobile); err != nil {
+    			return nil, err
+    		}
+    		return resp.Id, nil
+    	}, m.queryPrimary)
+    	switch err {
+    	case nil:
+    		return &resp, nil
+    	case sqlc.ErrNotFound:
+    		return nil, ErrNotFound
+    	default:
+    		return nil, err
+    	}
+    }
+    
+    func (m *defaultUserModel) Update(data User) error {
+    	userIdKey := fmt.Sprintf("%s%v", cacheUserIdPrefix, data.Id)
+    	_, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
+    		query := fmt.Sprintf("update %s set %s where id = ?", m.table, userRowsWithPlaceHolder)
+    		return conn.Exec(query, data.User, data.Name, data.Password, data.Mobile, data.Gender, data.Nickname, data.Id)
+    	}, userIdKey)
+    	return err
+    }
+    
+    func (m *defaultUserModel) Delete(id int64) error {
+    	data, err := m.FindOne(id)
+    	if err != nil {
+    		return err
+    	}
+    
+    	userIdKey := fmt.Sprintf("%s%v", cacheUserIdPrefix, id)
+    	userKey := fmt.Sprintf("%s%v", cacheUserPrefix, data.User)
+    	userNameKey := fmt.Sprintf("%s%v", cacheUserNamePrefix, data.Name)
+    	userMobileKey := fmt.Sprintf("%s%v", cacheUserMobilePrefix, data.Mobile)
+    	_, err = m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
+    		query := fmt.Sprintf("delete from %s where id = ?", m.table)
+    		return conn.Exec(query, id)
+    	}, userIdKey, userKey, userNameKey, userMobileKey)
+    	return err
+    }
+    
+    func (m *defaultUserModel) formatPrimary(primary interface{}) string {
+    	return fmt.Sprintf("%s%v", cacheUserIdPrefix, primary)
+    }
+    
+    func (m *defaultUserModel) queryPrimary(conn sqlx.SqlConn, v, primary interface{}) error {
+    	query := fmt.Sprintf("select %s from %s where id = ? limit 1", userRows, m.table)
+    	return conn.QueryRow(v, query, primary)
+    }
 
 
-	import (
-		"database/sql"
-		"fmt"
-		"strings"
-		"time"
-
-		"github.com/tal-tech/go-zero/core/stores/cache"
-		"github.com/tal-tech/go-zero/core/stores/sqlc"
-		"github.com/tal-tech/go-zero/core/stores/sqlx"
-		"github.com/tal-tech/go-zero/core/stringx"
-		"github.com/tal-tech/go-zero/tools/goctl/model/sql/builderx"
-	)
-
-	var (
-		userFieldNames          = builderx.FieldNames(&User{})
-		userRows                = strings.Join(userFieldNames, ",")
-		userRowsExpectAutoSet   = strings.Join(stringx.Remove(userFieldNames, "id", "create_time", "update_time"), ",")
-		userRowsWithPlaceHolder = strings.Join(stringx.Remove(userFieldNames, "id", "create_time", "update_time"), "=?,") + "=?"
-
-		cacheUserIdPrefix     = "cache#User#id#"
-		cacheUserNamePrefix   = "cache#User#name#"
-		cacheUserMobilePrefix = "cache#User#mobile#"
-	)
-
-	type (
-		UserModel struct {
-			sqlc.CachedConn
-			table string
-		}
-
-		User struct {
-			Id         int64     `db:"id"`
-			Name       string    `db:"name"`     // 用户名称
-			Password   string    `db:"password"` // 用户密码
-			Mobile     string    `db:"mobile"`   // 手机号
-			Gender     string    `db:"gender"`   // 男|女|未公开
-			Nickname   string    `db:"nickname"` // 用户昵称
-			CreateTime time.Time `db:"create_time"`
-			UpdateTime time.Time `db:"update_time"`
-		}
-	)
-
-	func NewUserModel(conn sqlx.SqlConn, c cache.CacheConf) *UserModel {
-		return &UserModel{
-			CachedConn: sqlc.NewConn(conn, c),
-			table:      "user",
-		}
-	}
-
-	func (m *UserModel) Insert(data User) (sql.Result, error) {
-		userNameKey := fmt.Sprintf("%s%v", cacheUserNamePrefix, data.Name)
-		userMobileKey := fmt.Sprintf("%s%v", cacheUserMobilePrefix, data.Mobile)
-		ret, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
-			query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?)", m.table, userRowsExpectAutoSet)
-			return conn.Exec(query, data.Name, data.Password, data.Mobile, data.Gender, data.Nickname)
-		}, userNameKey, userMobileKey)
-		return ret, err
-	}
-
-	func (m *UserModel) FindOne(id int64) (*User, error) {
-		userIdKey := fmt.Sprintf("%s%v", cacheUserIdPrefix, id)
-		var resp User
-		err := m.QueryRow(&resp, userIdKey, func(conn sqlx.SqlConn, v interface{}) error {
-			query := fmt.Sprintf("select %s from %s where id = ? limit 1", userRows, m.table)
-			return conn.QueryRow(v, query, id)
-		})
-		switch err {
-		case nil:
-			return &resp, nil
-		case sqlc.ErrNotFound:
-			return nil, ErrNotFound
-		default:
-			return nil, err
-		}
-	}
-
-	func (m *UserModel) FindOneByName(name string) (*User, error) {
-		userNameKey := fmt.Sprintf("%s%v", cacheUserNamePrefix, name)
-		var resp User
-		err := m.QueryRowIndex(&resp, userNameKey, m.formatPrimary, func(conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
-			query := fmt.Sprintf("select %s from %s where name = ? limit 1", userRows, m.table)
-			if err := conn.QueryRow(&resp, query, name); err != nil {
-				return nil, err
-			}
-			return resp.Id, nil
-		}, m.queryPrimary)
-		switch err {
-		case nil:
-			return &resp, nil
-		case sqlc.ErrNotFound:
-			return nil, ErrNotFound
-		default:
-			return nil, err
-		}
-	}
-
-	func (m *UserModel) FindOneByMobile(mobile string) (*User, error) {
-		userMobileKey := fmt.Sprintf("%s%v", cacheUserMobilePrefix, mobile)
-		var resp User
-		err := m.QueryRowIndex(&resp, userMobileKey, m.formatPrimary, func(conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
-			query := fmt.Sprintf("select %s from %s where mobile = ? limit 1", userRows, m.table)
-			if err := conn.QueryRow(&resp, query, mobile); err != nil {
-				return nil, err
-			}
-			return resp.Id, nil
-		}, m.queryPrimary)
-		switch err {
-		case nil:
-			return &resp, nil
-		case sqlc.ErrNotFound:
-			return nil, ErrNotFound
-		default:
-			return nil, err
-		}
-	}
-
-	func (m *UserModel) Update(data User) error {
-		userIdKey := fmt.Sprintf("%s%v", cacheUserIdPrefix, data.Id)
-		_, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
-			query := fmt.Sprintf("update %s set %s where id = ?", m.table, userRowsWithPlaceHolder)
-			return conn.Exec(query, data.Name, data.Password, data.Mobile, data.Gender, data.Nickname, data.Id)
-		}, userIdKey)
-		return err
-	}
-
-	func (m *UserModel) Delete(id int64) error {
-		data, err := m.FindOne(id)
-		if err != nil {
-			return err
-		}
-
-		userMobileKey := fmt.Sprintf("%s%v", cacheUserMobilePrefix, data.Mobile)
-		userIdKey := fmt.Sprintf("%s%v", cacheUserIdPrefix, id)
-		userNameKey := fmt.Sprintf("%s%v", cacheUserNamePrefix, data.Name)
-		_, err = m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
-			query := fmt.Sprintf("delete from %s where id = ?", m.table)
-			return conn.Exec(query, id)
-		}, userMobileKey, userIdKey, userNameKey)
-		return err
-	}
-
-	func (m *UserModel) formatPrimary(primary interface{}) string {
-		return fmt.Sprintf("%s%v", cacheUserIdPrefix, primary)
-	}
-
-	func (m *UserModel) queryPrimary(conn sqlx.SqlConn, v, primary interface{}) error {
-		query := fmt.Sprintf("select %s from %s where id = ? limit 1", userRows, m.table)
-		return conn.QueryRow(v, query, primary)
-	}
 	```
 	```
 
 
 ## 用法
 ## 用法
@@ -211,25 +246,24 @@ OPTIONS:
   * ddl
   * ddl
 
 
 	```shell script
 	```shell script
-	goctl model mysql -src={patterns} -dir={dir} -cache=true
+	goctl model mysql -src={patterns} -dir={dir} -cache
 	```
 	```
 
 
 	help
 	help
 
 
 	```
 	```
 	NAME:
 	NAME:
-	goctl model mysql ddl - generate mysql model from ddl
-
-	USAGE:
-	goctl model mysql ddl [command options] [arguments...]
-
-	OPTIONS:
-	--src value, -s value  the path or path globbing patterns of the ddl
-	--dir value, -d value  the target dir
-	--style value          the file naming style, lower|camel|underline,default is lower
-	--cache, -c            generate code with cache [optional]
-	--idea                 for idea plugin [optional]
-
+       goctl model mysql ddl - generate mysql model from ddl
+    
+    USAGE:
+       goctl model mysql ddl [command options] [arguments...]
+    
+    OPTIONS:
+       --src value, -s value  the path or path globbing patterns of the ddl
+       --dir value, -d value  the target dir
+       --style value          the file naming format, see [https://github.com/tal-tech/go-zero/tree/master/tools/goctl/config/readme.md]
+       --cache, -c            generate code with cache [optional]
+       --idea                 for idea plugin [optional]
 	```
 	```
 
 
   * datasource
   * datasource
@@ -242,18 +276,19 @@ OPTIONS:
 
 
 	```
 	```
 	NAME:
 	NAME:
-	goctl model mysql datasource - generate model from datasource
+       goctl model mysql datasource - generate model from datasource
+    
+    USAGE:
+       goctl model mysql datasource [command options] [arguments...]
+    
+    OPTIONS:
+       --url value              the data source of database,like "root:password@tcp(127.0.0.1:3306)/database
+       --table value, -t value  the table or table globbing patterns in the database
+       --cache, -c              generate code with cache [optional]
+       --dir value, -d value    the target dir
+       --style value            the file naming format, see [https://github.com/tal-tech/go-zero/tree/master/tools/goctl/config/readme.md]
+       --idea                   for idea plugin [optional]
 
 
-	USAGE:
-	goctl model mysql datasource [command options] [arguments...]
-
-	OPTIONS:
-	--url value              the data source of database,like "root:password@tcp(127.0.0.1:3306)/database
-	--table value, -t value  the table or table globbing patterns in the database
-	--cache, -c              generate code with cache [optional]
-	--dir value, -d value    the target dir
-	--style value            the file naming style, lower|camel|snake, default is lower
-	--idea                   for idea plugin [optional]
 
 
 	```
 	```
 
 
@@ -281,13 +316,13 @@ OPTIONS:
   * ddl
   * ddl
 
 
       ```shell script
       ```shell script
-        goctl model -src={patterns} -dir={dir} -cache=false
+        goctl model -src={patterns} -dir={dir}
       ```
       ```
 
 
   * datasource
   * datasource
   
   
       ```shell script
       ```shell script
-        goctl model mysql datasource -url={datasource} -table={patterns}  -dir={dir} -cache=false
+        goctl model mysql datasource -url={datasource} -table={patterns}  -dir={dir}
       ```
       ```
   
   
 生成代码仅基本的CURD结构。
 生成代码仅基本的CURD结构。

+ 0 - 1
tools/goctl/model/sql/command/command.go

@@ -39,7 +39,6 @@ func MysqlDDL(ctx *cli.Context) error {
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
-
 	return fromDDl(src, dir, cfg, cache, idea)
 	return fromDDl(src, dir, cfg, cache, idea)
 }
 }
 
 

+ 2 - 2
tools/goctl/model/sql/example/makefile

@@ -2,7 +2,7 @@
 
 
 # generate model with cache from ddl
 # generate model with cache from ddl
 fromDDL:
 fromDDL:
-	goctl model mysql ddl -src="./sql/*.sql" -dir="./sql/model/user" -c
+	goctl model mysql ddl -src="./sql/*.sql" -dir="./sql/model/user" -cache
 
 
 
 
 # generate model with cache from data source
 # generate model with cache from data source
@@ -12,4 +12,4 @@ datasource=127.0.0.1:3306
 database=gozero
 database=gozero
 
 
 fromDataSource:
 fromDataSource:
-	goctl model mysql datasource -url="$(user):$(password)@tcp($(datasource))/$(database)" -table="*" -dir ./model/cache -c -style camel
+	goctl model mysql datasource -url="$(user):$(password)@tcp($(datasource))/$(database)" -table="*" -dir ./model/cache -c -style gozero

+ 2 - 0
tools/goctl/model/sql/example/sql/user.sql

@@ -1,6 +1,7 @@
 -- 用户表 --
 -- 用户表 --
 CREATE TABLE `user` (
 CREATE TABLE `user` (
   `id` bigint(10) NOT NULL AUTO_INCREMENT,
   `id` bigint(10) NOT NULL AUTO_INCREMENT,
+  `user` varchar(50) NOT NULL DEFAULT '' COMMENT '用户',
   `name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户名称',
   `name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户名称',
   `password` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户密码',
   `password` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户密码',
   `mobile` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '手机号',
   `mobile` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '手机号',
@@ -10,6 +11,7 @@ CREATE TABLE `user` (
   `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
   `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
   PRIMARY KEY (`id`),
   PRIMARY KEY (`id`),
   UNIQUE KEY `name_index` (`name`),
   UNIQUE KEY `name_index` (`name`),
+  UNIQUE KEY `user_index` (`user`),
   UNIQUE KEY `mobile_index` (`mobile`)
   UNIQUE KEY `mobile_index` (`mobile`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
 
 

+ 19 - 4
tools/goctl/model/sql/gen/delete.go

@@ -9,7 +9,7 @@ import (
 	"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
 	"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
 )
 )
 
 
-func genDelete(table Table, withCache bool) (string, error) {
+func genDelete(table Table, withCache bool) (string, string, error) {
 	keySet := collection.NewSet()
 	keySet := collection.NewSet()
 	keyVariableSet := collection.NewSet()
 	keyVariableSet := collection.NewSet()
 	for fieldName, key := range table.CacheKey {
 	for fieldName, key := range table.CacheKey {
@@ -24,7 +24,7 @@ func genDelete(table Table, withCache bool) (string, error) {
 	camel := table.Name.ToCamel()
 	camel := table.Name.ToCamel()
 	text, err := util.LoadTemplate(category, deleteTemplateFile, template.Delete)
 	text, err := util.LoadTemplate(category, deleteTemplateFile, template.Delete)
 	if err != nil {
 	if err != nil {
-		return "", err
+		return "", "", err
 	}
 	}
 
 
 	output, err := util.With("delete").
 	output, err := util.With("delete").
@@ -40,8 +40,23 @@ func genDelete(table Table, withCache bool) (string, error) {
 			"keyValues":                 strings.Join(keyVariableSet.KeysStr(), ", "),
 			"keyValues":                 strings.Join(keyVariableSet.KeysStr(), ", "),
 		})
 		})
 	if err != nil {
 	if err != nil {
-		return "", err
+		return "", "", err
 	}
 	}
 
 
-	return output.String(), nil
+	// interface method
+	text, err = util.LoadTemplate(category, deleteMethodTemplateFile, template.DeleteMethod)
+	if err != nil {
+		return "", "", err
+	}
+
+	deleteMethodOut, err := util.With("deleteMethod").
+		Parse(text).
+		Execute(map[string]interface{}{
+			"lowerStartCamelPrimaryKey": stringx.From(table.PrimaryKey.Name.ToCamel()).UnTitle(),
+			"dataType":                  table.PrimaryKey.DataType,
+		})
+	if err != nil {
+		return "", "", err
+	}
+	return output.String(), deleteMethodOut.String(), nil
 }
 }

+ 19 - 4
tools/goctl/model/sql/gen/findone.go

@@ -6,11 +6,11 @@ import (
 	"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
 	"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
 )
 )
 
 
-func genFindOne(table Table, withCache bool) (string, error) {
+func genFindOne(table Table, withCache bool) (string, string, error) {
 	camel := table.Name.ToCamel()
 	camel := table.Name.ToCamel()
 	text, err := util.LoadTemplate(category, findOneTemplateFile, template.FindOne)
 	text, err := util.LoadTemplate(category, findOneTemplateFile, template.FindOne)
 	if err != nil {
 	if err != nil {
-		return "", err
+		return "", "", err
 	}
 	}
 
 
 	output, err := util.With("findOne").
 	output, err := util.With("findOne").
@@ -26,8 +26,23 @@ func genFindOne(table Table, withCache bool) (string, error) {
 			"cacheKeyVariable":          table.CacheKey[table.PrimaryKey.Name.Source()].Variable,
 			"cacheKeyVariable":          table.CacheKey[table.PrimaryKey.Name.Source()].Variable,
 		})
 		})
 	if err != nil {
 	if err != nil {
-		return "", err
+		return "", "", err
 	}
 	}
 
 
-	return output.String(), nil
+	text, err = util.LoadTemplate(category, findOneMethodTemplateFile, template.FindOneMethod)
+	if err != nil {
+		return "", "", err
+	}
+
+	findOneMethod, err := util.With("findOneMethod").
+		Parse(text).
+		Execute(map[string]interface{}{
+			"upperStartCamelObject":     camel,
+			"lowerStartCamelPrimaryKey": stringx.From(table.PrimaryKey.Name.ToCamel()).UnTitle(),
+			"dataType":                  table.PrimaryKey.DataType,
+		})
+	if err != nil {
+		return "", "", err
+	}
+	return output.String(), findOneMethod.String(), nil
 }
 }

+ 45 - 7
tools/goctl/model/sql/gen/findonebyfield.go

@@ -9,10 +9,16 @@ import (
 	"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
 	"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
 )
 )
 
 
-func genFindOneByField(table Table, withCache bool) (string, string, error) {
+type findOneCode struct {
+	findOneMethod          string
+	findOneInterfaceMethod string
+	cacheExtra             string
+}
+
+func genFindOneByField(table Table, withCache bool) (*findOneCode, error) {
 	text, err := util.LoadTemplate(category, findOneByFieldTemplateFile, template.FindOneByField)
 	text, err := util.LoadTemplate(category, findOneByFieldTemplateFile, template.FindOneByField)
 	if err != nil {
 	if err != nil {
-		return "", "", err
+		return nil, err
 	}
 	}
 
 
 	t := util.With("findOneByField").Parse(text)
 	t := util.With("findOneByField").Parse(text)
@@ -36,15 +42,40 @@ func genFindOneByField(table Table, withCache bool) (string, string, error) {
 			"originalField":             field.Name.Source(),
 			"originalField":             field.Name.Source(),
 		})
 		})
 		if err != nil {
 		if err != nil {
-			return "", "", err
+			return nil, err
 		}
 		}
 
 
 		list = append(list, output.String())
 		list = append(list, output.String())
 	}
 	}
+
+	text, err = util.LoadTemplate(category, findOneByFieldMethodTemplateFile, template.FindOneByFieldMethod)
+	if err != nil {
+		return nil, err
+	}
+
+	t = util.With("findOneByFieldMethod").Parse(text)
+	var listMethod []string
+	for _, field := range table.Fields {
+		if field.IsPrimaryKey || !field.IsUniqueKey {
+			continue
+		}
+		camelFieldName := field.Name.ToCamel()
+		output, err := t.Execute(map[string]interface{}{
+			"upperStartCamelObject": camelTableName,
+			"upperField":            camelFieldName,
+			"in":                    fmt.Sprintf("%s %s", stringx.From(camelFieldName).UnTitle(), field.DataType),
+		})
+		if err != nil {
+			return nil, err
+		}
+
+		listMethod = append(listMethod, output.String())
+	}
+
 	if withCache {
 	if withCache {
 		text, err := util.LoadTemplate(category, findOneByFieldExtraMethodTemplateFile, template.FindOneByFieldExtraMethod)
 		text, err := util.LoadTemplate(category, findOneByFieldExtraMethodTemplateFile, template.FindOneByFieldExtraMethod)
 		if err != nil {
 		if err != nil {
-			return "", "", err
+			return nil, err
 		}
 		}
 
 
 		out, err := util.With("findOneByFieldExtraMethod").Parse(text).Execute(map[string]interface{}{
 		out, err := util.With("findOneByFieldExtraMethod").Parse(text).Execute(map[string]interface{}{
@@ -54,11 +85,18 @@ func genFindOneByField(table Table, withCache bool) (string, string, error) {
 			"originalPrimaryField":  table.PrimaryKey.Name.Source(),
 			"originalPrimaryField":  table.PrimaryKey.Name.Source(),
 		})
 		})
 		if err != nil {
 		if err != nil {
-			return "", "", err
+			return nil, err
 		}
 		}
 
 
-		return strings.Join(list, "\n"), out.String(), nil
+		return &findOneCode{
+			findOneMethod:          strings.Join(list, util.NL),
+			findOneInterfaceMethod: strings.Join(listMethod, util.NL),
+			cacheExtra:             out.String(),
+		}, nil
 	}
 	}
-	return strings.Join(list, "\n"), "", nil
 
 
+	return &findOneCode{
+		findOneMethod:          strings.Join(list, util.NL),
+		findOneInterfaceMethod: strings.Join(listMethod, util.NL),
+	}, nil
 }
 }

+ 13 - 10
tools/goctl/model/sql/gen/gen.go

@@ -11,6 +11,7 @@ import (
 	"github.com/tal-tech/go-zero/tools/goctl/model/sql/model"
 	"github.com/tal-tech/go-zero/tools/goctl/model/sql/model"
 	"github.com/tal-tech/go-zero/tools/goctl/model/sql/parser"
 	"github.com/tal-tech/go-zero/tools/goctl/model/sql/parser"
 	"github.com/tal-tech/go-zero/tools/goctl/model/sql/template"
 	"github.com/tal-tech/go-zero/tools/goctl/model/sql/template"
+	modelutil "github.com/tal-tech/go-zero/tools/goctl/model/sql/util"
 	"github.com/tal-tech/go-zero/tools/goctl/util"
 	"github.com/tal-tech/go-zero/tools/goctl/util"
 	"github.com/tal-tech/go-zero/tools/goctl/util/console"
 	"github.com/tal-tech/go-zero/tools/goctl/util/console"
 	"github.com/tal-tech/go-zero/tools/goctl/util/format"
 	"github.com/tal-tech/go-zero/tools/goctl/util/format"
@@ -222,39 +223,41 @@ func (g *defaultGenerator) genModel(in parser.Table, withCache bool) (string, er
 		return "", err
 		return "", err
 	}
 	}
 
 
-	typesCode, err := genTypes(table, withCache)
+	insertCode, insertCodeMethod, err := genInsert(table, withCache)
 	if err != nil {
 	if err != nil {
 		return "", err
 		return "", err
 	}
 	}
 
 
-	newCode, err := genNew(table, withCache)
+	var findCode = make([]string, 0)
+	findOneCode, findOneCodeMethod, err := genFindOne(table, withCache)
 	if err != nil {
 	if err != nil {
 		return "", err
 		return "", err
 	}
 	}
 
 
-	insertCode, err := genInsert(table, withCache)
+	ret, err := genFindOneByField(table, withCache)
 	if err != nil {
 	if err != nil {
 		return "", err
 		return "", err
 	}
 	}
 
 
-	var findCode = make([]string, 0)
-	findOneCode, err := genFindOne(table, withCache)
+	findCode = append(findCode, findOneCode, ret.findOneMethod)
+	updateCode, updateCodeMethod, err := genUpdate(table, withCache)
 	if err != nil {
 	if err != nil {
 		return "", err
 		return "", err
 	}
 	}
 
 
-	findOneByFieldCode, extraMethod, err := genFindOneByField(table, withCache)
+	deleteCode, deleteCodeMethod, err := genDelete(table, withCache)
 	if err != nil {
 	if err != nil {
 		return "", err
 		return "", err
 	}
 	}
 
 
-	findCode = append(findCode, findOneCode, findOneByFieldCode)
-	updateCode, err := genUpdate(table, withCache)
+	var list []string
+	list = append(list, insertCodeMethod, findOneCodeMethod, ret.findOneInterfaceMethod, updateCodeMethod, deleteCodeMethod)
+	typesCode, err := genTypes(table, strings.Join(modelutil.TrimStringSlice(list), util.NL), withCache)
 	if err != nil {
 	if err != nil {
 		return "", err
 		return "", err
 	}
 	}
 
 
-	deleteCode, err := genDelete(table, withCache)
+	newCode, err := genNew(table, withCache)
 	if err != nil {
 	if err != nil {
 		return "", err
 		return "", err
 	}
 	}
@@ -269,7 +272,7 @@ func (g *defaultGenerator) genModel(in parser.Table, withCache bool) (string, er
 		"find":        strings.Join(findCode, "\n"),
 		"find":        strings.Join(findCode, "\n"),
 		"update":      updateCode,
 		"update":      updateCode,
 		"delete":      deleteCode,
 		"delete":      deleteCode,
-		"extraMethod": extraMethod,
+		"extraMethod": ret.cacheExtra,
 	})
 	})
 	if err != nil {
 	if err != nil {
 		return "", err
 		return "", err

+ 19 - 4
tools/goctl/model/sql/gen/insert.go

@@ -9,7 +9,7 @@ import (
 	"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
 	"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
 )
 )
 
 
-func genInsert(table Table, withCache bool) (string, error) {
+func genInsert(table Table, withCache bool) (string, string, error) {
 	keySet := collection.NewSet()
 	keySet := collection.NewSet()
 	keyVariableSet := collection.NewSet()
 	keyVariableSet := collection.NewSet()
 	for fieldName, key := range table.CacheKey {
 	for fieldName, key := range table.CacheKey {
@@ -36,7 +36,7 @@ func genInsert(table Table, withCache bool) (string, error) {
 	camel := table.Name.ToCamel()
 	camel := table.Name.ToCamel()
 	text, err := util.LoadTemplate(category, insertTemplateFile, template.Insert)
 	text, err := util.LoadTemplate(category, insertTemplateFile, template.Insert)
 	if err != nil {
 	if err != nil {
-		return "", err
+		return "", "", err
 	}
 	}
 
 
 	output, err := util.With("insert").
 	output, err := util.With("insert").
@@ -52,8 +52,23 @@ func genInsert(table Table, withCache bool) (string, error) {
 			"keyValues":             strings.Join(keyVariableSet.KeysStr(), ", "),
 			"keyValues":             strings.Join(keyVariableSet.KeysStr(), ", "),
 		})
 		})
 	if err != nil {
 	if err != nil {
-		return "", err
+		return "", "", err
 	}
 	}
 
 
-	return output.String(), nil
+	// interface method
+	text, err = util.LoadTemplate(category, insertTemplateMethodFile, template.InsertMethod)
+	if err != nil {
+		return "", "", err
+	}
+
+	insertMethodOutput, err := util.With("insertMethod").
+		Parse(text).
+		Execute(map[string]interface{}{
+			"upperStartCamelObject": camel,
+		})
+	if err != nil {
+		return "", "", err
+	}
+
+	return output.String(), insertMethodOutput.String(), nil
 }
 }

+ 7 - 0
tools/goctl/model/sql/gen/keys.go

@@ -2,6 +2,7 @@ package gen
 
 
 import (
 import (
 	"fmt"
 	"fmt"
+	"strings"
 
 
 	"github.com/tal-tech/go-zero/tools/goctl/model/sql/parser"
 	"github.com/tal-tech/go-zero/tools/goctl/model/sql/parser"
 	"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
 	"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
@@ -33,8 +34,14 @@ func genCacheKeys(table parser.Table) (map[string]Key, error) {
 			camelFieldName := field.Name.ToCamel()
 			camelFieldName := field.Name.ToCamel()
 			lowerStartCamelFieldName := stringx.From(camelFieldName).UnTitle()
 			lowerStartCamelFieldName := stringx.From(camelFieldName).UnTitle()
 			left := fmt.Sprintf("cache%s%sPrefix", camelTableName, camelFieldName)
 			left := fmt.Sprintf("cache%s%sPrefix", camelTableName, camelFieldName)
+			if strings.ToLower(camelFieldName) == strings.ToLower(camelTableName) {
+				left = fmt.Sprintf("cache%sPrefix", camelTableName)
+			}
 			right := fmt.Sprintf("cache#%s#%s#", camelTableName, lowerStartCamelFieldName)
 			right := fmt.Sprintf("cache#%s#%s#", camelTableName, lowerStartCamelFieldName)
 			variable := fmt.Sprintf("%s%sKey", lowerStartCamelTableName, camelFieldName)
 			variable := fmt.Sprintf("%s%sKey", lowerStartCamelTableName, camelFieldName)
+			if strings.ToLower(lowerStartCamelTableName) == strings.ToLower(camelFieldName) {
+				variable = fmt.Sprintf("%sKey", lowerStartCamelTableName)
+			}
 			m[field.Name.Source()] = Key{
 			m[field.Name.Source()] = Key{
 				VarExpression:     fmt.Sprintf(`%s = "%s"`, left, right),
 				VarExpression:     fmt.Sprintf(`%s = "%s"`, left, right),
 				Left:              left,
 				Left:              left,

+ 9 - 0
tools/goctl/model/sql/gen/template.go

@@ -11,31 +11,40 @@ import (
 const (
 const (
 	category                              = "model"
 	category                              = "model"
 	deleteTemplateFile                    = "delete.tpl"
 	deleteTemplateFile                    = "delete.tpl"
+	deleteMethodTemplateFile              = "interface-delete.tpl"
 	fieldTemplateFile                     = "filed.tpl"
 	fieldTemplateFile                     = "filed.tpl"
 	findOneTemplateFile                   = "find-one.tpl"
 	findOneTemplateFile                   = "find-one.tpl"
+	findOneMethodTemplateFile             = "interface-find-one.tpl"
 	findOneByFieldTemplateFile            = "find-one-by-field.tpl"
 	findOneByFieldTemplateFile            = "find-one-by-field.tpl"
+	findOneByFieldMethodTemplateFile      = "interface-find-one-by-field.tpl"
 	findOneByFieldExtraMethodTemplateFile = "find-one-by-filed-extra-method.tpl"
 	findOneByFieldExtraMethodTemplateFile = "find-one-by-filed-extra-method.tpl"
 	importsTemplateFile                   = "import.tpl"
 	importsTemplateFile                   = "import.tpl"
 	importsWithNoCacheTemplateFile        = "import-no-cache.tpl"
 	importsWithNoCacheTemplateFile        = "import-no-cache.tpl"
 	insertTemplateFile                    = "insert.tpl"
 	insertTemplateFile                    = "insert.tpl"
+	insertTemplateMethodFile              = "interface-insert.tpl"
 	modelTemplateFile                     = "model.tpl"
 	modelTemplateFile                     = "model.tpl"
 	modelNewTemplateFile                  = "model-new.tpl"
 	modelNewTemplateFile                  = "model-new.tpl"
 	tagTemplateFile                       = "tag.tpl"
 	tagTemplateFile                       = "tag.tpl"
 	typesTemplateFile                     = "types.tpl"
 	typesTemplateFile                     = "types.tpl"
 	updateTemplateFile                    = "update.tpl"
 	updateTemplateFile                    = "update.tpl"
+	updateMethodTemplateFile              = "interface-update.tpl"
 	varTemplateFile                       = "var.tpl"
 	varTemplateFile                       = "var.tpl"
 	errTemplateFile                       = "err.tpl"
 	errTemplateFile                       = "err.tpl"
 )
 )
 
 
 var templates = map[string]string{
 var templates = map[string]string{
 	deleteTemplateFile:                    template.Delete,
 	deleteTemplateFile:                    template.Delete,
+	deleteMethodTemplateFile:              template.DeleteMethod,
 	fieldTemplateFile:                     template.Field,
 	fieldTemplateFile:                     template.Field,
 	findOneTemplateFile:                   template.FindOne,
 	findOneTemplateFile:                   template.FindOne,
+	findOneMethodTemplateFile:             template.FindOneMethod,
 	findOneByFieldTemplateFile:            template.FindOneByField,
 	findOneByFieldTemplateFile:            template.FindOneByField,
+	findOneByFieldMethodTemplateFile:      template.FindOneByFieldMethod,
 	findOneByFieldExtraMethodTemplateFile: template.FindOneByFieldExtraMethod,
 	findOneByFieldExtraMethodTemplateFile: template.FindOneByFieldExtraMethod,
 	importsTemplateFile:                   template.Imports,
 	importsTemplateFile:                   template.Imports,
 	importsWithNoCacheTemplateFile:        template.ImportsNoCache,
 	importsWithNoCacheTemplateFile:        template.ImportsNoCache,
 	insertTemplateFile:                    template.Insert,
 	insertTemplateFile:                    template.Insert,
+	insertTemplateMethodFile:              template.InsertMethod,
 	modelTemplateFile:                     template.Model,
 	modelTemplateFile:                     template.Model,
 	modelNewTemplateFile:                  template.New,
 	modelNewTemplateFile:                  template.New,
 	tagTemplateFile:                       template.Tag,
 	tagTemplateFile:                       template.Tag,

+ 2 - 1
tools/goctl/model/sql/gen/types.go

@@ -5,7 +5,7 @@ import (
 	"github.com/tal-tech/go-zero/tools/goctl/util"
 	"github.com/tal-tech/go-zero/tools/goctl/util"
 )
 )
 
 
-func genTypes(table Table, withCache bool) (string, error) {
+func genTypes(table Table, methods string, withCache bool) (string, error) {
 	fields := table.Fields
 	fields := table.Fields
 	fieldsString, err := genFields(fields)
 	fieldsString, err := genFields(fields)
 	if err != nil {
 	if err != nil {
@@ -21,6 +21,7 @@ func genTypes(table Table, withCache bool) (string, error) {
 		Parse(text).
 		Parse(text).
 		Execute(map[string]interface{}{
 		Execute(map[string]interface{}{
 			"withCache":             withCache,
 			"withCache":             withCache,
+			"method":                methods,
 			"upperStartCamelObject": table.Name.ToCamel(),
 			"upperStartCamelObject": table.Name.ToCamel(),
 			"fields":                fieldsString,
 			"fields":                fieldsString,
 		})
 		})

+ 19 - 4
tools/goctl/model/sql/gen/update.go

@@ -8,7 +8,7 @@ import (
 	"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
 	"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
 )
 )
 
 
-func genUpdate(table Table, withCache bool) (string, error) {
+func genUpdate(table Table, withCache bool) (string, string, error) {
 	expressionValues := make([]string, 0)
 	expressionValues := make([]string, 0)
 	for _, filed := range table.Fields {
 	for _, filed := range table.Fields {
 		camel := filed.Name.ToCamel()
 		camel := filed.Name.ToCamel()
@@ -24,7 +24,7 @@ func genUpdate(table Table, withCache bool) (string, error) {
 	camelTableName := table.Name.ToCamel()
 	camelTableName := table.Name.ToCamel()
 	text, err := util.LoadTemplate(category, updateTemplateFile, template.Update)
 	text, err := util.LoadTemplate(category, updateTemplateFile, template.Update)
 	if err != nil {
 	if err != nil {
-		return "", err
+		return "", "", err
 	}
 	}
 
 
 	output, err := util.With("update").
 	output, err := util.With("update").
@@ -39,8 +39,23 @@ func genUpdate(table Table, withCache bool) (string, error) {
 			"expressionValues":      strings.Join(expressionValues, ", "),
 			"expressionValues":      strings.Join(expressionValues, ", "),
 		})
 		})
 	if err != nil {
 	if err != nil {
-		return "", nil
+		return "", "", nil
 	}
 	}
 
 
-	return output.String(), nil
+	// update interface method
+	text, err = util.LoadTemplate(category, updateMethodTemplateFile, template.UpdateMethod)
+	if err != nil {
+		return "", "", err
+	}
+
+	updateMethodOutput, err := util.With("updateMethod").
+		Parse(text).
+		Execute(map[string]interface{}{
+			"upperStartCamelObject": camelTableName,
+		})
+	if err != nil {
+		return "", "", nil
+	}
+
+	return output.String(), updateMethodOutput.String(), nil
 }
 }

+ 5 - 2
tools/goctl/model/sql/parser/parser_test.go

@@ -76,6 +76,9 @@ func TestConvertColumn(t *testing.T) {
 	assert.Nil(t, err)
 	assert.Nil(t, err)
 	assert.True(t, table.PrimaryKey.AutoIncrement && table.PrimaryKey.IsPrimaryKey)
 	assert.True(t, table.PrimaryKey.AutoIncrement && table.PrimaryKey.IsPrimaryKey)
 	assert.Equal(t, "id", table.PrimaryKey.Name.Source())
 	assert.Equal(t, "id", table.PrimaryKey.Name.Source())
-	assert.Equal(t, "mobile", table.Fields[1].Name.Source())
-	assert.True(t, table.Fields[1].IsUniqueKey)
+	for _, item := range table.Fields {
+		if item.Name.Source() == "mobile" {
+			assert.True(t, item.IsUniqueKey)
+		}
+	}
 }
 }

+ 3 - 1
tools/goctl/model/sql/template/delete.go

@@ -1,7 +1,7 @@
 package template
 package template
 
 
 var Delete = `
 var Delete = `
-func (m *{{.upperStartCamelObject}}Model) Delete({{.lowerStartCamelPrimaryKey}} {{.dataType}}) error {
+func (m *default{{.upperStartCamelObject}}Model) Delete({{.lowerStartCamelPrimaryKey}} {{.dataType}}) error {
 	{{if .withCache}}{{if .containsIndexCache}}data, err:=m.FindOne({{.lowerStartCamelPrimaryKey}})
 	{{if .withCache}}{{if .containsIndexCache}}data, err:=m.FindOne({{.lowerStartCamelPrimaryKey}})
 	if err!=nil{
 	if err!=nil{
 		return err
 		return err
@@ -16,3 +16,5 @@ func (m *{{.upperStartCamelObject}}Model) Delete({{.lowerStartCamelPrimaryKey}}
 	return err
 	return err
 }
 }
 `
 `
+
+var DeleteMethod = `Delete({{.lowerStartCamelPrimaryKey}} {{.dataType}}) error`

+ 7 - 4
tools/goctl/model/sql/template/find.go

@@ -2,7 +2,7 @@ package template
 
 
 // 通过id查询
 // 通过id查询
 var FindOne = `
 var FindOne = `
-func (m *{{.upperStartCamelObject}}Model) FindOne({{.lowerStartCamelPrimaryKey}} {{.dataType}}) (*{{.upperStartCamelObject}}, error) {
+func (m *default{{.upperStartCamelObject}}Model) FindOne({{.lowerStartCamelPrimaryKey}} {{.dataType}}) (*{{.upperStartCamelObject}}, error) {
 	{{if .withCache}}{{.cacheKey}}
 	{{if .withCache}}{{.cacheKey}}
 	var resp {{.upperStartCamelObject}}
 	var resp {{.upperStartCamelObject}}
 	err := m.QueryRow(&resp, {{.cacheKeyVariable}}, func(conn sqlx.SqlConn, v interface{}) error {
 	err := m.QueryRow(&resp, {{.cacheKeyVariable}}, func(conn sqlx.SqlConn, v interface{}) error {
@@ -32,7 +32,7 @@ func (m *{{.upperStartCamelObject}}Model) FindOne({{.lowerStartCamelPrimaryKey}}
 
 
 // 通过指定字段查询
 // 通过指定字段查询
 var FindOneByField = `
 var FindOneByField = `
-func (m *{{.upperStartCamelObject}}Model) FindOneBy{{.upperField}}({{.in}}) (*{{.upperStartCamelObject}}, error) {
+func (m *default{{.upperStartCamelObject}}Model) FindOneBy{{.upperField}}({{.in}}) (*{{.upperStartCamelObject}}, error) {
 	{{if .withCache}}{{.cacheKey}}
 	{{if .withCache}}{{.cacheKey}}
 	var resp {{.upperStartCamelObject}}
 	var resp {{.upperStartCamelObject}}
 	err := m.QueryRowIndex(&resp, {{.cacheKeyVariable}}, m.formatPrimary, func(conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
 	err := m.QueryRowIndex(&resp, {{.cacheKeyVariable}}, m.formatPrimary, func(conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
@@ -64,12 +64,15 @@ func (m *{{.upperStartCamelObject}}Model) FindOneBy{{.upperField}}({{.in}}) (*{{
 }{{end}}
 }{{end}}
 `
 `
 var FindOneByFieldExtraMethod = `
 var FindOneByFieldExtraMethod = `
-func (m *{{.upperStartCamelObject}}Model) formatPrimary(primary interface{}) string {
+func (m *default{{.upperStartCamelObject}}Model) formatPrimary(primary interface{}) string {
 	return fmt.Sprintf("%s%v", {{.primaryKeyLeft}}, primary)
 	return fmt.Sprintf("%s%v", {{.primaryKeyLeft}}, primary)
 }
 }
 
 
-func (m *{{.upperStartCamelObject}}Model) queryPrimary(conn sqlx.SqlConn, v, primary interface{}) error {
+func (m *default{{.upperStartCamelObject}}Model) queryPrimary(conn sqlx.SqlConn, v, primary interface{}) error {
 	query := fmt.Sprintf("select %s from %s where {{.originalPrimaryField}} = ? limit 1", {{.lowerStartCamelObject}}Rows, m.table )
 	query := fmt.Sprintf("select %s from %s where {{.originalPrimaryField}} = ? limit 1", {{.lowerStartCamelObject}}Rows, m.table )
 	return conn.QueryRow(v, query, primary)
 	return conn.QueryRow(v, query, primary)
 }
 }
 `
 `
+
+var FindOneMethod = `FindOne({{.lowerStartCamelPrimaryKey}} {{.dataType}}) (*{{.upperStartCamelObject}}, error)`
+var FindOneByFieldMethod = `FindOneBy{{.upperField}}({{.in}}) (*{{.upperStartCamelObject}}, error) `

+ 3 - 1
tools/goctl/model/sql/template/insert.go

@@ -1,7 +1,7 @@
 package template
 package template
 
 
 var Insert = `
 var Insert = `
-func (m *{{.upperStartCamelObject}}Model) Insert(data {{.upperStartCamelObject}}) (sql.Result,error) {
+func (m *default{{.upperStartCamelObject}}Model) Insert(data {{.upperStartCamelObject}}) (sql.Result,error) {
 	{{if .withCache}}{{if .containsIndexCache}}{{.keys}}
 	{{if .withCache}}{{if .containsIndexCache}}{{.keys}}
     ret, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
     ret, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
 		query := fmt.Sprintf("insert into %s (%s) values ({{.expression}})", m.table, {{.lowerStartCamelObject}}RowsExpectAutoSet)
 		query := fmt.Sprintf("insert into %s (%s) values ({{.expression}})", m.table, {{.lowerStartCamelObject}}RowsExpectAutoSet)
@@ -13,3 +13,5 @@ func (m *{{.upperStartCamelObject}}Model) Insert(data {{.upperStartCamelObject}}
 	return ret,err
 	return ret,err
 }
 }
 `
 `
+
+var InsertMethod = `Insert(data {{.upperStartCamelObject}}) (sql.Result,error)`

+ 2 - 2
tools/goctl/model/sql/template/new.go

@@ -1,8 +1,8 @@
 package template
 package template
 
 
 var New = `
 var New = `
-func New{{.upperStartCamelObject}}Model(conn sqlx.SqlConn{{if .withCache}}, c cache.CacheConf{{end}}) *{{.upperStartCamelObject}}Model {
-	return &{{.upperStartCamelObject}}Model{
+func New{{.upperStartCamelObject}}Model(conn sqlx.SqlConn{{if .withCache}}, c cache.CacheConf{{end}}) {{.upperStartCamelObject}}Model {
+	return &default{{.upperStartCamelObject}}Model{
 		{{if .withCache}}CachedConn: sqlc.NewConn(conn, c){{else}}conn:conn{{end}},
 		{{if .withCache}}CachedConn: sqlc.NewConn(conn, c){{else}}conn:conn{{end}},
 		table:      "{{.table}}",
 		table:      "{{.table}}",
 	}
 	}

+ 5 - 1
tools/goctl/model/sql/template/types.go

@@ -2,7 +2,11 @@ package template
 
 
 var Types = `
 var Types = `
 type (
 type (
-	{{.upperStartCamelObject}}Model struct {
+	{{.upperStartCamelObject}}Model interface{
+		{{.method}}
+	}
+
+	default{{.upperStartCamelObject}}Model struct {
 		{{if .withCache}}sqlc.CachedConn{{else}}conn sqlx.SqlConn{{end}}
 		{{if .withCache}}sqlc.CachedConn{{else}}conn sqlx.SqlConn{{end}}
 		table string
 		table string
 	}
 	}

+ 3 - 1
tools/goctl/model/sql/template/update.go

@@ -1,7 +1,7 @@
 package template
 package template
 
 
 var Update = `
 var Update = `
-func (m *{{.upperStartCamelObject}}Model) Update(data {{.upperStartCamelObject}}) error {
+func (m *default{{.upperStartCamelObject}}Model) Update(data {{.upperStartCamelObject}}) error {
 	{{if .withCache}}{{.primaryCacheKey}}
 	{{if .withCache}}{{.primaryCacheKey}}
     _, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
     _, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
 		query := fmt.Sprintf("update %s set %s where {{.originalPrimaryKey}} = ?", m.table, {{.lowerStartCamelObject}}RowsWithPlaceHolder)
 		query := fmt.Sprintf("update %s set %s where {{.originalPrimaryKey}} = ?", m.table, {{.lowerStartCamelObject}}RowsWithPlaceHolder)
@@ -11,3 +11,5 @@ func (m *{{.upperStartCamelObject}}Model) Update(data {{.upperStartCamelObject}}
 	return err
 	return err
 }
 }
 `
 `
+
+var UpdateMethod = `Update(data {{.upperStartCamelObject}}) error`

+ 12 - 0
tools/goctl/model/sql/util/slice.go

@@ -0,0 +1,12 @@
+package util
+
+func TrimStringSlice(list []string) []string {
+	var out []string
+	for _, item := range list {
+		if len(item) == 0 {
+			continue
+		}
+		out = append(out, item)
+	}
+	return out
+}