blog icon indicating copy to clipboard operation
blog copied to clipboard

动手写ORM框架 - GeeORM第四天 链式操作与更新删除 | 极客兔兔

Open geektutu opened this issue 4 years ago • 13 comments

https://geektutu.com/post/geeorm-day4.html

7天用 Go语言/golang 从零实现 ORM 框架 GeeORM 教程(7 days implement golang object relational mapping framework from scratch tutorial),动手写 ORM 框架,参照 gorm, xorm 的实现。通过链式(chain)操作,支持查询条件(where, order by, limit 等)的叠加;实现记录的更新(update)、删除(delete)和统计(count)功能。

geektutu avatar Mar 08 '20 17:03 geektutu

膜拜大佬

xiaoxfan avatar Apr 14 '20 08:04 xiaoxfan

膜拜大佬

@xiaoxfan 哈哈,感谢认可,希望对你有帮助~

geektutu avatar Jan 11 '21 12:01 geektutu

链式调用太精巧了,Find, Delete,Update 等都是调用置后的。PS 这里的 SQL 语句合法性没有做限制,需要用户自己把握

boyl avatar Feb 03 '21 03:02 boyl

这里是为了省代码吗,感觉可读性太差了。。。

s.clause.Set(clause.WHERE, append(append(vars, desc), args...)...)

haochen233 avatar Mar 22 '21 06:03 haochen233

这种链式调用不会导致SQL注入吗?

wardseptember avatar May 08 '21 11:05 wardseptember

func TestSession_DeleteAndCount(t *testing.T) {
	s := testRecordInit(t)
	affected, _ := s.Where("Name = ?", "Tom").Delete()
	count, _ := s.Count()

	if affected != 1 || count != 1 {
		t.Fatal("failed to delete or count")
	}
}

这里应该是count != 0逻辑才对,affected, _ := s.Where("Name = ?", "Tom").Delete()这个链式调用把clause.WHERE也Set了会导致后面s.Count()的时候把clause.WHERE条件也加进去,也就是SELECT count(*) FROM User WHERE Name = ? [Tom]。显然是 count 的值应该是 0 才对。

或者是否在clause.go 里面加一个 clear() 方法,在 Build 返回之前都调用一下?

zagreos avatar Jun 22 '21 06:06 zagreos

@SeanChan0901

func TestSession_DeleteAndCount(t *testing.T) {
	s := testRecordInit(t)
	affected, _ := s.Where("Name = ?", "Tom").Delete()
	count, _ := s.Count()

	if affected != 1 || count != 1 {
		t.Fatal("failed to delete or count")
	}
}

这里应该是count != 0逻辑才对,affected, _ := s.Where("Name = ?", "Tom").Delete()这个链式调用把clause.WHERE也Set了会导致后面s.Count()的时候把clause.WHERE条件也加进去,也就是SELECT count(*) FROM User WHERE Name = ? [Tom]。显然是 count 的值应该是 0 才对。

或者是否在clause.go 里面加一个 clear() 方法,在 Build 返回之前都调用一下?

xiaoheng14 avatar Aug 16 '21 18:08 xiaoheng14

s.Raw().Exec()中的方法Exec有clear的了。

xiaoheng14 avatar Aug 16 '21 18:08 xiaoheng14

lz可以拍个视频,手敲代码理解太累了

DurantVivado avatar Jan 11 '22 08:01 DurantVivado

func TestSession_DeleteAndCount(t *testing.T) {
	s := testRecordInit(t)
	affected, _ := s.Where("Name = ?", "Tom").Delete()
	count, _ := s.Count()

	if affected != 1 || count != 1 {
		t.Fatal("failed to delete or count")
	}
}

这里执行两个sql语句,难道不需要清空s.clause里面的内容吗?我执行的话会出错,因为Count里面还用上了Where子句。

我在clause.Build函数里面添加一个清除操作,才能不会报错。作者是在其它地方添加了操作吗?

func (c *Clause)Build(orders ...Type)(string,[]interface{})  {
	......
	defer func() {
		c.sql=nil
		c.sqlVars=nil
	}()
	.....
}

lcxc-lcxc avatar May 24 '22 18:05 lcxc-lcxc

@lcxc-lcxc

func TestSession_DeleteAndCount(t *testing.T) {
	s := testRecordInit(t)
	affected, _ := s.Where("Name = ?", "Tom").Delete()
	count, _ := s.Count()

	if affected != 1 || count != 1 {
		t.Fatal("failed to delete or count")
	}
}

这里执行两个sql语句,难道不需要清空s.clause里面的内容吗?我执行的话会出错,因为Count里面还用上了Where子句。

我在clause.Build函数里面添加一个清除操作,才能不会报错。作者是在其它地方添加了操作吗?

func (c *Clause)Build(orders ...Type)(string,[]interface{})  {
	......
	defer func() {
		c.sql=nil
		c.sqlVars=nil
	}()
	.....
}

确实需要手动clear一下

niconical avatar Jul 18 '22 12:07 niconical

@xiaoheng14 s.Raw().Exec()中的方法Exec有clear的了。

那个clear清空的是stringBuilder中缓存的sql语句,而不是子句中的各个条件

ShiMaRing avatar Jul 28 '22 05:07 ShiMaRing

@haochen233 这里是为了省代码吗,感觉可读性太差了。。。

s.clause.Set(clause.WHERE, append(append(vars, desc), args...)...)

只是提供了一种思路,让初学者入门而已。配合着debug调试就好了。真正使用ORM不会这么繁琐的。例如调用laravel的时候都是高度封装成->where(field,value)的形式

lv997 avatar Jan 11 '24 02:01 lv997