{"id":37135406,"url":"https://github.com/mei-rune/gobatis","last_synced_at":"2026-01-14T15:47:32.673Z","repository":{"id":52889843,"uuid":"132417341","full_name":"mei-rune/GoBatis","owner":"mei-rune","description":"An easy ORM tool for Golang, support MyBatis-Like XML template SQL","archived":false,"fork":false,"pushed_at":"2026-01-12T07:56:51.000Z","size":1907,"stargazers_count":120,"open_issues_count":1,"forks_count":17,"subscribers_count":7,"default_branch":"master","last_synced_at":"2026-01-12T17:52:06.217Z","etag":null,"topics":["golang","mybatis","orm","orm-framework"],"latest_commit_sha":null,"homepage":"https://mei-rune.github.io/GoBatis","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mei-rune.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-05-07T06:33:18.000Z","updated_at":"2026-01-12T07:56:55.000Z","dependencies_parsed_at":"2023-11-24T02:04:09.650Z","dependency_job_id":"88b03936-0c35-4998-b842-2685d7c208e2","html_url":"https://github.com/mei-rune/GoBatis","commit_stats":{"total_commits":792,"total_committers":1,"mean_commits":792.0,"dds":0.0,"last_synced_commit":"48c6d36106f383f170120fbb682249adc254e97c"},"previous_names":["runner-mei/gobatis","runner-mei/gobaties"],"tags_count":57,"template":false,"template_full_name":null,"purl":"pkg:github/mei-rune/GoBatis","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mei-rune%2FGoBatis","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mei-rune%2FGoBatis/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mei-rune%2FGoBatis/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mei-rune%2FGoBatis/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mei-rune","download_url":"https://codeload.github.com/mei-rune/GoBatis/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mei-rune%2FGoBatis/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28424863,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T15:24:48.085Z","status":"ssl_error","status_checked_at":"2026-01-14T15:23:41.940Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["golang","mybatis","orm","orm-framework"],"created_at":"2026-01-14T15:47:31.785Z","updated_at":"2026-01-14T15:47:32.641Z","avatar_url":"https://github.com/mei-rune.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GoBatis\n\n[![GoDoc](https://godoc.org/github.com/mei-rune/GoBatis?status.svg)](https://godoc.org/github.com/mei-rune/GoBatis)\n[![Travis Build Status](https://travis-ci.org/mei-rune/GoBatis.svg?branch=master)](https://travis-ci.org/mei-rune/GoBatis)\n[![GitHub Actions](https://github.com/mei-rune/GoBatis/actions/workflows/test.yml/badge.svg)](https://github.com/mei-rune/GoBatis/actions)\n![GitHub tag (latest SemVer)](https://img.shields.io/github/tag/mei-rune/GoBatis.svg)\n[![Coverage Status](https://coveralls.io/repos/github/mei-rune/GoBatis/badge.svg?branch=master)](https://coveralls.io/github/mei-rune/GoBatis?branch=master)\n[![Appveyor Build status](https://ci.appveyor.com/api/projects/status/hmg1mecib5j46r55?svg=true)](https://ci.appveyor.com/project/mei-rune/gobatis)\n\n\n## [中文文档](https://mei-rune.github.io/GoBatis)\n\n## Introduction\n\nAn easy ORM tool for Golang, support MyBatis-Like XML template SQL\n\n## 待完成的任务\n1. 对象继承的实现\n2. 延迟加载或加密字段(或特殊处理)的实现\n     有泛型了，可以尝试下 \n     ````go\n     type Lazy[T any] struct {\n        value T\n        session SqlSession\n        sqlstr string\n     }\n     func (l *Lazy[T]) Read() T {\n         session.Query()\n     }\n\n     // 加密字段(或特殊处理)\n     type Passworder struct {\n        value string\n     }\n     func (p *Passworder) Scan(interface{}) error {\n         xxxxx\n     }\n     func (p *Passworder) Value() driver.Value {\n         xxxxx\n     }\n\n     \n     type Record struct {\n     TableName struct{}    `db:records`\n     Blob   Lazy[[]byte]   `db:\"blob\"`\n     Password Passworder   `db:\"password\"`\n     }\n\n     ``````\n\n3. 返回大量数据记录时用泛型来改进\n   ````go\n   type Results[T any] struct  {}\n   func (rs *Results) Next() bool {}\n   func (rs *Results) Read(value *T) error {}\n   ````\n\n## 已知 bug\n\n1. 当 sql 中含有 xml 标签时 \u003ccode\u003e\u0026lt; \u003c/code\u003e 号需要转义为 \u003ccode\u003e\u0026amp;lt; \u003c/code\u003e，而不含 xml 标签时\u003ccode\u003e\u0026amp;lt; \u003c/code\u003e 又不转义为 \u003ccode\u003e\u0026lt; \u003c/code\u003e, 这很不一致。\n   最近我改进了一个像 mybatis 一样用 gt, gte，lt 和 lte 代替 \u003e,\u003e=, \u003c 和 \u003c=, 如\n\n     a \u003e 8 写成 a gt 8\n   \n     a \u003e= 8 写成 a gte 8\n\n     a \u003c 8 写成 a lt 8\n\n     a \u003c= 8 写成 a lte 8\n\n2. 达梦数据库实现 upsert 时无法返回 insert id (达梦数据库的问题)。\n\n\n## 和 MyBatis 的区别\n\nGoBatis 就是对 MyBatis 的简单模仿。 但有下列不同\n\n### 1. 动态 sql 语句的格式\n\n     我实现一个和  mybatis 类似的 if, chose, foreach, trim, set 和 where 之类的 xml 基本实现，同时也支持 go template 来生成 sql。\n\n#### 1.1 另外我们不支持 ${xxx}, 但是我提供了一个更安全的 \u003cprint fmt=\"%s\" value=\"b\" inStr=\"true\" /\u003e 来替换它\n\n     当  inStr=\"true\" 时我会检查 value 的值中是不是有 引号之类的字符，防止 sql 注入\n     \n     当    inStr=\"false\" 时我会检查 value 的值中是不是有 and 或  or 之类的逻辑表达式，防止 sql 注入\n\n#### 1.2 我为 if 标签 增加了 else 支持， 用法为 \u003cif\u003e xx \u003celse /\u003e xxx \u003c/if\u003e\n\n### 2. 自动生成 sql 语句\n\nMyBatis 是不会自动生成 sql 语句的， 我觉得能像大部份的 orm 一样能生成 sql 的话，可以省很多工作\n     请见 [SQL 自动生成](https://mei-rune.github.io/GoBatis/#/sql_genrate)\n\n\n## 基本思路\n1. 用户定义结构和接口\n2. 在接口的方法上定义 sql （可以在 xml 中或方法的注释中）\n3. 用工具生成接口的实现\n4. 创建接口的实例并使用它\n\n## Roadmap\n1. 升级 go1.14 后 goparser 特别慢，准备用 goparser2 替换\n2. 将 xml 相关代码移到 xml 子目录\n3. 将 sql 生成工具 builder 相关代码移到 sql 子目录\n\n## Usage\n\n注意， gobatis 也支持 xml, 请见 example_xml 目录\n\n1. install `gobatis` tools.\n\n    `go get -u -v github.com/runner-mei/GoBatis/cmd/gobatis`\n\n\n2. Define a struct, interface and comment methods with SQLs and Variables, then write a directive `//go:generate gobatis user.go`.\n\n````go\n//go:generate gobatis user.go\npackage example\n\nimport (\n  \"time\"\n)\n\ntype AuthUser struct {\n  ID        int64      `json:\"id\"`\n  Username  string     `json:\"username\"`\n  Phone     string     `json:\"phone\"`\n  Address   *string    `json:\"address\"`\n  Status    uint8      `json:\"status\"`\n  BirthDay  *time.Time `json:\"birth_day\"`\n  CreatedAt time.Time  `json:\"created_at\"`\n  UpdatedAt time.Time  `json:\"updated_at\"`\n}\n\ntype UserDao interface {\n  // @postgres insert into auth_users(username, phone, address, status, birth_day, created_at, updated_at)\n  // values (#{username},#{phone},#{address},#{status},#{birth_day},CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) returning id\n  //\n  // @default insert into auth_users(username, phone, address, status, birth_day, created_at, updated_at)\n  // values (#{username},#{phone},#{address},#{status},#{birth_day},CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)\n  Insert(u *AuthUser) (int64, error)\n}\n\n````\n\n3. After that, run `go generate ./...` ， user.gobatis.go is generated\n\n````go\n// Please don't edit this file!\npackage example\n\nimport (\n  \"errors\"\n\n  gobatis \"github.com/runner-mei/GoBatis\"\n)\n\nfunc init() {\n  gobatis.Init(func(ctx *gobatis.InitContext) error {\n    { //// UserDao.Insert\n      if _, exists := ctx.Statements[\"UserDao.Insert\"]; !exists {\n        sqlStr := \"insert into auth_users(username, phone, address, status, birth_day, created_at, updated_at)\\r\\n values (#{username},#{phone},#{address},#{status},#{birth_day},CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)\"\n        switch ctx.Dialect {\n        case gobatis.NewDialect(\"mssql\"):\n          sqlStr = \"insert into auth_users(username, phone, address, status, birth_day, created_at, updated_at)\\r\\n output inserted.id\\r\\n values (#{username},#{phone},#{address},#{status},#{birth_day},CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)\"\n        case gobatis.NewDialect(\"postgres\"):\n          sqlStr = \"insert into auth_users(username, phone, address, status, birth_day, created_at, updated_at)\\r\\n values (#{username},#{phone},#{address},#{status},#{birth_day},CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) returning id\"\n        }\n        stmt, err := gobatis.NewMapppedStatement(ctx, \"UserDao.Insert\",\n          gobatis.StatementTypeInsert,\n          gobatis.ResultStruct,\n          sqlStr)\n        if err != nil {\n          return err\n        }\n        ctx.Statements[\"UserDao.Insert\"] = stmt\n      }\n    }\n  })\n}\n\nfunc NewUserDao(session gobatis.SqlSession) UserDao {\n  return \u0026UserDaoImpl{session: session}\n}\n\ntype UserDaoImpl struct {\n  session gobatis.SqlSession\n}\n\nfunc (impl *UserDaoImpl) Insert(u *AuthUser) (int64, error) {\n  return impl.session.Insert(\"UserDao.Insert\",\n    []string{\n      \"u\",\n    },\n    []interface{}{\n      u,\n    })\n}\n\n...\n\n````\n\n4. use UserDao\n\n````go\n  factory, err := gobatis.New(\u0026gobatis.Config{\n    DbCompatibility: true,\n    DriverName: tests.TestDrv,\n    DataSource: tests.GetTestConnURL(),\n    // XMLPaths: []string{\"example/test.xml\"},\n    })\n    \n  userDao := NewUserDao(factory.SessionReference())\n  id, err := userDao.Insert(\u0026insertUser)\n  if err != nil {\n    fmt.Println(err)\n    return\n  }\n  fmt.Println(\"insert success!\")\n\n  u, err := userDao.Get(id)\n  if err != nil {\n    fmt.Println(err)\n    return\n  }\n  fmt.Println(\"fetch user from database!\")\n\n  _, err = userDao.Delete(id)\n  if err != nil {\n    fmt.Println(err)\n    return\n  }\n  fmt.Println(\"delete success!\")\n````\n\n\n## 注意\nGoBatis 是基于 [osm](https://github.com/yinshuwei/osm) 的基础上修改来的，goparser 则是在 [light](https://github.com/arstd/light) 的基础上修改来的, reflectx 则从 [sqlx](https://github.com/jmoiron/sqlx) 拷贝过来的\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmei-rune%2Fgobatis","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmei-rune%2Fgobatis","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmei-rune%2Fgobatis/lists"}