go语言beego框架 orm实现insertOrUpdate功能
2016-07-14 23:21
731 查看
在beego1.6.1版本orm中并未提供insertOrUpdate,但是自己做项目时遇到了这个需求,顾写了一个自己的实现,暂只支持mysql与postgres。实现原理是数据自带可实现insertorupdate的功能语句。
mysql:-
postgres : -
然后去orm实现中自己拼装sql语句
好了,亮代码:
func (d *dbBase) InsertOrUpdate(q dbQuerier, mi *modelInfo,ind reflect.Value, tz *time.Location, dn string, args …string)
(int64, error) {
这就是实现功能的全部逻辑,当然要想在beego orm中使用insertorupdate还有一些其他的工作要做,首先这段代码应该添加在-
然后在
func (o *orm) InsertOrUpdate(md interface{},colConflitAndArgs …string) (int64, error) {
再在
**
**
好了,现在大功告成了。可以使用InssertOrUpdate功能了
列如:
mysql:
func IOUFinish(all *Finish) int64 {
这个函数在出入数据时有主键或者唯一键冲突,将执行update操作,其中step列执行+自增操作,其他列按model中的值进行update操作。其中”step=step+1”格式数据可以有多个也可以没有,这种格式只用于自增操作
postgres:
func IOUFinish(all *Finish) int64 {
当操作postgres数据库是,必须在model后的第一个参数指定你预期的冲突列的列名(由于实现此功能的sql语句需要且数据库版本必须大于9.5,因为实现的语句由9.5版本推出),其他与mysql一致。
提示:在使用自增操作是最好不要自增主键或者唯一键,可能会引起错误。
mysql:-
ON DUPLICATE KEY UPDATE
postgres : -
ON CONFLICT DO UPDATE SET
然后去orm实现中自己拼装sql语句
好了,亮代码:
func (d *dbBase) InsertOrUpdate(q dbQuerier, mi *modelInfo,ind reflect.Value, tz *time.Location, dn string, args …string)
(int64, error) {
iouStr := "" mysql := "mysql" postgres := "postgres" argsMap := map[string]string{} if dn == mysql { iouStr = "ON DUPLICATE KEY UPDATE" } else if dn == postgres && len(args) > 0 { args0 = args[0] iouStr = fmt.Sprintf("ON CONFLICT (%s) DO UPDATE SET", args0) } else { return 0, fmt.Errorf("`%s` nonsupport insert or update in beego", dn) } for _, v := range args { kv := strings.Split(v, "=") if len(kv) == 2 { argsMap[kv[0]] = kv[1] } } isMulti := false names := make([]string, 0, len(mi.fields.dbcols)-1) Q := d.ins.TableQuote() values, err := d.collectValues(mi, ind, mi.fields.dbcols, true, true, &names, tz) if err != nil { return 0, err marks := make([]string, len(names)) updateValues := make([]interface{}, 0) updates := make([]string, len(names)) var conflitValue interface{} for i, v := range names { marks[i] = "?" valueStr := argsMap[v] if v == args0 { conflitValue = values[i] } if valueStr != "" { switch dn { case mysql: updates[i] = v + "=" + valueStr break case postgres: if conflitValue != nil { updates[i] = fmt.Sprintf("%s=(select %s from %s where %s = ? )", v, valueStr, mi.table, args[0]) updateValues = append(updateValues, conflitValue) } else { return 0, fmt.Errorf("`%s` must be in front of `%s` in your struct", args[0], v) } break } } else { updates[i] = v + "=?" updateValues = append(updateValues, values[i]) } values = append(values, updateValues...) sep := fmt.Sprintf("%s, %s", Q, Q) qmarks := strings.Join(marks, ", ") qupdates := strings.Join(updates, ", ") columns := strings.Join(names, sep) multi := len(values) / len(names) if isMulti { qmarks = strings.Repeat(qmarks+"), (", multi-1) + qmarks } query := fmt.Sprintf("INSERT INTO %s%s%s (%s%s%s) VALUES (%s) %s "+qupdates, Q, mi.table, Q, Q, columns, Q, qmarks, iouStr) if isMulti || !d.ins.HasReturningID(mi, &query) { res, err := q.Exec(query, values...) if err == nil { if isMulti { return res.RowsAffected() } return res.LastInsertId() } return 0, err } row := q.QueryRow(query, values...) var id int64 err = row.Scan(&id) return id, err}
这就是实现功能的全部逻辑,当然要想在beego orm中使用insertorupdate还有一些其他的工作要做,首先这段代码应该添加在-
beego/orm文件夹下的db.go文件中
然后在
orm.go文件中添加
func (o *orm) InsertOrUpdate(md interface{},colConflitAndArgs …string) (int64, error) {
mi, ind := o.getMiInd(md, true) id, err := o.alias.DbBaser.InsertOrUpdate(o.db, mi, ind, o.alias.TZ, o.alias.DriverName, colConflitAndArgs...) if err != nil { return id, err } o.setPk(mi, ind, id) return id, nil}
再在
types.go文件中的type Ormer interface和type dbBaser interface中分别添加
**
InsertOrUpdate(md interface{}, colConflitAndArgs ...string) (int64, error)与
**
InsertOrUpdate(dbQuerier, *modelInfo, reflect.Value, *time.Location, string, ...string) (int64, error)
好了,现在大功告成了。可以使用InssertOrUpdate功能了
列如:
mysql:
func IOUFinish(all *Finish) int64 {
db := orm.NewOrm() db.Using("mysql") r, e := db.InsertOrUpdate(all, "step=step+1") if e != nil { fmt.Println(e) return 0 } fmt.Println(r) return r}
这个函数在出入数据时有主键或者唯一键冲突,将执行update操作,其中step列执行+自增操作,其他列按model中的值进行update操作。其中”step=step+1”格式数据可以有多个也可以没有,这种格式只用于自增操作
postgres:
func IOUFinish(all *Finish) int64 {
db := orm.NewOrm() db.Using("postgres") r, e := db.InsertOrUpdate(all,"confilctColumnName" "step=step+1") if e != nil { fmt.Println(e) return 0 } fmt.Println(r) return r}
当操作postgres数据库是,必须在model后的第一个参数指定你预期的冲突列的列名(由于实现此功能的sql语句需要且数据库版本必须大于9.5,因为实现的语句由9.5版本推出),其他与mysql一致。
提示:在使用自增操作是最好不要自增主键或者唯一键,可能会引起错误。
相关文章推荐
- ASP也使用ORM,给ASP上所有的SQL注入画上句号
- 仿orm自动生成分页SQL分享
- Go语言入门教程之Arrays、Slices、Maps、Range操作简明总结
- GO语言异常处理机制panic和recover分析
- go语言执行windows下命令行的方法
- Go语言计算两个经度和纬度之间距离的方法
- Go语言排序与接口实例分析
- Go语言导出内容到Excel的方法
- go语言实现sqrt的方法
- Go语言MessageBox用法实例
- Go语言判断指定文件是否存在的方法
- 深入理解:单一入口、MVC、ORM、CURD、ActiveRecord概念
- go语言制作的zip压缩程序
- go语言channel实现多核并行化运行的方法
- Go语言MD5加密用法实例
- go语言使用scp的方法实例分析
- Go语言中的switch用法实例分析
- go语言检测文件是否存在的方法
- Go语言里的结构体文法实例分析
- Go语言结构体定义和使用方法