{"id":13714439,"url":"https://github.com/somethingpluto/sorm","last_synced_at":"2025-05-07T01:34:08.260Z","repository":{"id":189696095,"uuid":"582005677","full_name":"somethingpluto/sorm","owner":"somethingpluto","description":"从 0.5 到 1 开发go orm框架 ，🍍🍍基于go语言官方提供的数据库操作API，进行二次封装，实现ORM框架的基本功能。本框架计划实现功能:🚩 1.根据结构体创建数据库 🚩2.通过函数API自由组合生成SQL语句 🚩3.实现API之间的链式调用 🚩4.数据库操作hook实现 🚩5.数据库事务","archived":false,"fork":false,"pushed_at":"2023-01-01T02:40:40.000Z","size":60,"stargazers_count":3,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-05-23T04:46:16.458Z","etag":null,"topics":["go","go-orm","orm"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/somethingpluto.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2022-12-25T09:11:15.000Z","updated_at":"2023-07-07T15:56:26.000Z","dependencies_parsed_at":"2023-08-21T12:07:28.398Z","dependency_job_id":null,"html_url":"https://github.com/somethingpluto/sorm","commit_stats":null,"previous_names":["somethingpluto/sorm"],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/somethingpluto%2Fsorm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/somethingpluto%2Fsorm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/somethingpluto%2Fsorm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/somethingpluto%2Fsorm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/somethingpluto","download_url":"https://codeload.github.com/somethingpluto/sorm/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224551283,"owners_count":17330117,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","go-orm","orm"],"created_at":"2024-08-02T23:01:59.512Z","updated_at":"2024-11-14T01:31:16.223Z","avatar_url":"https://github.com/somethingpluto.png","language":"Go","funding_links":[],"categories":["Repositories"],"sub_categories":[],"readme":"# SORM\n\n## 简介✨✨✨✨✨✨\n\n​\t\tsorm是一款基于go数据库操作包的orm框架，此项目并非完全的orm框架项目。而更像是一个开发日记，记录每次框架更新迭代的过程，版本号以v开发，例如 v0,v1,v2。\n\n使用日记方式进行框架开发，旨在 😁\n\n1. 加强对数据库系统了解，go语言与数据库交互     \n2. 向大家记录开发框架全过程，供大家使用\n3. 为大家提供pr机会，本人目前的技术水准应该还有待提高，欢迎大家指出🤠\n4. 体验处理issue，与pr\n5. 在实际的框架开发中，增强自己对go语言的理解\n\n## 当前支持功能\n\n1. 数据库的连接\n2. SQL语句的执行\n3. 结构体解析为schema\n4. 根据结构体创建数据表\n5. 表的删除与是否存在检查\n\n6. CRUD语句的生成与实现\n7. 关键词之间的链式调用\n8. 钩子的实现\n9. 事务实现\n\n## 版本功能更新记录🚧🚧\n\n### v1: 2022.12.25 🥽\n\n\u003e 1. ORM中logger开发，实现logger分级以及彩色打印\n\u003e 1. session会话实现，sql语句的生成与执行，单条记录查询，多条记录查询\n\u003e 1. 数据库连接\n\n### v2: 2022.12.26 🐱‍🏍\n\n\u003e 1. 不同类型数据库的适配\n\u003e 1. mysql数据类型与go数据类型映射\n\u003e 1. 数据库表模式的定义\n\u003e 1. 数据库表相关操作，创建，删除，是否存在\n\n### v3: 2022.12.29 🍿\n\n\u003e 1.不同关键词字句的生成\n\u003e\n\u003e 2.CURD对应SQL语句的生成与执行\n\u003e\n\u003e 3.关键词之间实现链式调用\n\n### v4: 2023.01.01🙆‍♂️\n\n\u003e 1.钩子的实现\n\u003e\n\u003e 2.事务调用\n\n## 功能实例\n\n### 1.根据结构体创建数据表\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t_ \"github.com/go-sql-driver/mysql\"\n\t\"sorm\"\n)\n\ntype User struct {\n\tName string `sorm:\"PRIMARY KEY\"`\n\tAge  int\n}\n\nfunc main() {\n\tdsn := \"root:root@tcp(127.0.0.0:3306)/sorm\"\n\tengine, _ := sorm.NewEngine(\"mysql\", dsn)\n\tdefer engine.Close()\n\n\ts := engine.NewSession()\n\terr := s.Model(\u0026User{}).CreateTable()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tfmt.Println(s.RefTable().Name, \"创建成功\")\n\tfmt.Printf(\"字段: %s\", s.RefTable().FieldNames)\n}\n```\n\n![image-20221228165543750](https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/1770/image-20221228165543750.png)\n\n![image-20221228165613917](https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/1770/image-20221228165613917.png)\n\n### 2.向表中插入数据INSERT\n\n```go\npackage main\n\nimport (\n   \"fmt\"\n   _ \"github.com/go-sql-driver/mysql\"\n   \"sorm\"\n)\n\ntype User struct {\n   Name string `sorm:\"PRIMARY KEY\"`\n   Age  int\n}\n\nfunc main() {\n\tdsn := \"root:root@tcp(127.0.0.0:3306)/sorm\"\n   engine, _ := sorm.NewEngine(\"mysql\", dsn)\n   defer engine.Close()\n\n   s := engine.NewSession().Model(\u0026User{})\n   user1 := User{\n      Name: \"张三\",\n      Age:  18,\n   }\n   user2 := User{\n      Name: \"李四\",\n      Age:  19,\n   }\n   user3 := User{\n      Name: \"王五\",\n      Age:  18,\n   }\n   result, err := s.Insert(user1, user2, user3)\n   if err != nil {\n      panic(err)\n   }\n   fmt.Println(\"插入数据条数:\", result)\n}\n```\n\n![image-20221228170404636](https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/1770/image-20221228170404636.png)\n\n![image-20221228170450116](https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/1770/image-20221228170450116.png)\n\n### 3.条件搜索FIND\n\n```go\npackage main\n\nimport (\n   \"fmt\"\n   _ \"github.com/go-sql-driver/mysql\"\n   \"sorm\"\n)\n\ntype User struct {\n   Name string `sorm:\"PRIMARY KEY\"`\n   Age  int\n}\n\nfunc main() {\n\tdsn := \"root:root@tcp(127.0.0.0:3306)/sorm\"\n   engine, _ := sorm.NewEngine(\"mysql\", dsn)\n   defer engine.Close()\n   var users []User\n   session := engine.NewSession().Model(\u0026User{})\n   fmt.Println(\"-----where限制\")\n   session.Where(\"Age = ?\", \"18\").Find(\u0026users)\n   for _, user := range users {\n      fmt.Printf(\"%v\\n\", user)\n   }\n   users = []User{}\n   fmt.Println(\"-----order限制\")\n   session.Where(\"Age = ?\", \"18\").Order(\"Name desc\").Find(\u0026users)\n   for _, user := range users {\n      fmt.Printf(\"%v\\n\", user)\n   }\n   users = []User{}\n\n   fmt.Println(\"-----limit限制\")\n   session.Where(\"Age = ?\", \"18\").Order(\"Name desc\").Limit(1).Find(\u0026users)\n   for _, user := range users {\n      fmt.Printf(\"%v\\n\", user)\n   }\n   users = []User{}\n\n   fmt.Println(\"-----offset限制\")\n   session.Where(\"Age = ?\", \"18\").Order(\"Name desc\").Limit(1).Offset(1).Find(\u0026users)\n   for _, user := range users {\n      fmt.Printf(\"%v\\n\", user)\n   }\n\n}\n```\n\n![image-20221228171622769](https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/1770/image-20221228171622769.png)\n\n### 4.INSERT语句\n\n```go\nfunc TestInsertSQLBuild(t *testing.T) {\n   user1 := User{\n      Name: \"张三\",\n      Age:  18,\n   }\n   user2 := User{\n      Name: \"李四\",\n      Age:  19,\n   }\n   session := Engine.NewSession().Model(\u0026User{})\n   insert, err := session.Insert(user1, user2)\n   if err != nil {\n      t.Error(err)\n   }\n   fmt.Println(insert)\n}\n```\n\n![image-20221228141529106](https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/1770/image-20221228141529106.png)\n\n![image-20221228142334524](https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/1770/image-20221228142334524.png)\n\n### 5.FIND语句\n\n```go\nfunc TestFindSQLBuild(t *testing.T) {\n   session := Engine.NewSession().Model(\u0026User{})\n   var users []User\n   err := session.Where(\"Age =?\", 18).Order(\"Age desc\").Limit(2).Offset(0).Find(\u0026users)\n   if err != nil {\n      t.Error(err)\n   }\n   for _, user := range users {\n      fmt.Printf(\"%v\\n\", user)\n   }\n}\n```\n\n### 6.UPDATE语句\n\n```go\nfunc TestUpdateSQLBuild(t *testing.T) {\n   session := Engine.NewSession().Model(\u0026User{})\n   result, err := session.Where(\"Age =?\", 20).Update(\"Name\", \"ccccc\")\n   if err != nil {\n      t.Error(err)\n   }\n   fmt.Println(result)\n}\n```\n\n![image-20221229112233342](https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/1770/image-20221229112233342.png)\n\n![image-20221229112256212](https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/1770/image-20221229112256212.png)\n\n### 7.DELETE语句\n\n```go\nfunc TestDeleteSQLBuild(t *testing.T) {\n   session := Engine.NewSession().Model(\u0026User{})\n   result, err := session.Where(\"Age = ?\", 20).Delete()\n   if err != nil {\n      t.Error(err)\n   }\n   fmt.Println(result)\n}\n```\n\n![image-20221229112803620](https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/1770/image-20221229112803620.png)\n\n### 8.钩子的使用\n\n```go\npackage test\n\nimport (\n   \"fmt\"\n   \"sorm/log\"\n   \"sorm/session\"\n   \"testing\"\n)\n\ntype Teacher struct {\n   Name string `sorm:\"PRIMARY KEY\"`\n   Age  int\n}\n\nfunc (teacher *Teacher) BeforeInsert(s *session.Session) error {\n   log.Info(\"BEFORE INSERT\")\n   return nil\n}\n\nfunc (teacher *Teacher) AfterInsert(s *session.Session) error {\n   log.Info(\"AFTER INSERT\")\n   return nil\n}\n\nfunc TestInsertHooks(t *testing.T) {\n   s := Engine.NewSession().Model(\u0026Teacher{})\n   err := s.DropTable()\n   if err != nil {\n      t.Error(err)\n   }\n   err = s.CreateTable()\n   if err != nil {\n      t.Error(err)\n   }\n   result, err := s.Insert(\u0026Teacher{\n      Name: \"张三\",\n      Age:  10,\n   }, \u0026Teacher{\n      Name: \"李四\",\n      Age:  20,\n   })\n   if err != nil {\n      t.Error(err)\n   }\n   fmt.Println(result)\n}\n```\n\n​\t\tTeacher结构体绑定的钩子很简单，就是打印两条语句，如果想干点其它操作的话可以通过传入的session来完成\t\n\n![image-20230101102425898](https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/1770/image-20230101102425898.png)\n\n### 9.事务使用\n\n### \n\n```go\nimport (\n   \"fmt\"\n   _ \"github.com/go-sql-driver/mysql\"\n   \"sorm\"\n   \"sorm/session\"\n)\n\ntype User struct {\n   Name string `sorm:\"PRIMARY KEY\"`\n   Age  int\n}\n\nfunc main() {\n   dsn := \"root:root@tcp(127.0.0.1:3306)/sorm\"\n   engine, _ := sorm.NewEngine(\"mysql\", dsn)\n   defer engine.Close()\n   user := User{\n      Name: \"ccc\",\n      Age:  1,\n   }\n   s := engine.NewSession().Model(\u0026User{})\n   fmt.Println(\"事务第一次调用\")\n   // 1.第一次插入user\n   _, err := s.Transaction(func(s *session.Session) (result interface{}, err error) {\n      _, err = s.Insert(\u0026user)\n      return\n   })\n   fmt.Println(\"事务第二次调用\")\n   // 2.第二次插入user\n   _, err = s.Transaction(func(s *session.Session) (result interface{}, err error) {\n      _, err = s.Insert(\u0026user)\n      return\n   })\n   if err != nil {\n      fmt.Println(err)\n   }\n}\n```\n\n![image-20230101100900172](https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/1770/image-20230101100900172.png)\n\n## 开发日记\n\n### \u003ca href=\"https://www.yuque.com/c_pluto/rsz2ys/gnydi1edhi6k7af1?singleDoc# 《Go_SORM开发日记(一)—SQL生成》\"\u003e🚗Go_SORM开发日记(一)—SQL生成\u003c/a\u003e\n\n### \u003ca href=\"https://www.yuque.com/c_pluto/rsz2ys/qx33m4iuyzeyl5no?singleDoc# 《Go_SORM开发日记(二)—不同数据库之间差异屏蔽》\"\u003e🚓Go_SORM开发日记(二)—结构体解析成为表\u003c/a\u003e\n\n### \u003ca href=\"https://www.yuque.com/c_pluto/rsz2ys/sp28lohra8yxhr45?singleDoc# 《3.Go_SORM开发日记(三)—不同关键词字句的生成》\"\u003e🚕Go_SORM开发日记(三)—不同关键词字句的生成\u003c/a\u003e\n\n### \u003ca href=\"https://www.yuque.com/c_pluto/rsz2ys/yvvs2lvgqk3h9n2h?singleDoc# 《4.Go_SROM开发日记(四)—钩子与事务》\"\u003e🚌Go_SORM开发日记(四)—钩子和事务实现\u003c/a\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsomethingpluto%2Fsorm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsomethingpluto%2Fsorm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsomethingpluto%2Fsorm/lists"}