Xorm
xorm是一个简单而强大的Go语言ORM库,通过它可以使数据库操作非常简便。本库是基于原版xorm的定制增强版本,为xorm提供类似ibatis的配置文件及动态SQL支持,支持AcitveRecord操作
Install / Use
/learn @xormplus/XormREADME
xorm
xorm是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作非常简便。
说明
- 本库是基于原版 <b>xorm</b>:https://github.com/go-xorm/xorm 的定制增强版本,由于本定制版有第三方库依赖(原版xorm无任何第三方库依赖),原版xorm要保持对第三方库零依赖特性,所以只好单独开了本Github库。
- 本库的相关定制功能是为了解决更简单的进行复杂SQL调用和一些特殊业务需求场景而开发的。
- 本定制版ORM相关核心功能和原版保持一致,会跟随原版xorm更新。
- 定制功能采用针对原版弱侵入性代码实现。
特性
- 支持Struct和数据库表之间的灵活映射,并支持自动同步
- 事务支持,支持嵌套事务(支持类JAVA Spring的事务传播机制)
- 同时支持原始SQL语句和ORM操作的混合执行
- 使用连写来简化调用
- 支持使用Id, In, Where, Limit, Join, Having, Table, Sql, Cols等函数和结构体等方式作为条件
- 支持级联加载Struct
- 支持类ibatis方式配置SQL语句(支持xml配置文件、json配置文件、xsql配置文件,支持pongo2、jet、html/template模板和自定义实现配置多种方式)
- 支持动态SQL功能
- 支持一次批量混合执行多个CRUD操作,并返回多个结果集
- 支持数据库查询结果直接返回Json字符串和xml字符串
- 支持SqlMap配置文件和SqlTemplate模板密文存储和解析
- 支持缓存
- 支持主从数据库(Main/Subordinate)数据库读写分离
- 支持根据数据库自动生成xorm的结构体
- 支持记录版本(即乐观锁)
- 支持查询结果集导出csv、tsv、xml、json、xlsx、yaml、html功能
- 支持SQL Builder github.com/go-xorm/builder
- 上下文缓存支持
驱动支持
目前支持的Go数据库驱动和对应的数据库如下:
- Mysql: github.com/go-sql-driver/mysql
- MyMysql: github.com/ziutek/mymysql
- Postgres: github.com/lib/pq
- Tidb: github.com/pingcap/tidb
- SQLite: github.com/mattn/go-sqlite3
- MsSql: github.com/denisenkom/go-mssqldb
- Oracle: github.com/mattn/go-oci8 (试验性支持)
安装
使用go工具进行安装:
go get -u github.com/xormplus/xorm
文档
传送门:本定制版《xorm操作指南》
快速开始
- 第一步创建引擎,driverName, dataSourceName和database/sql接口相同
//xorm原版标准方式创建引擎
engine, err := xorm.NewEngine(driverName, dataSourceName)
//您也可以针对特定数据库及数据库驱动使用类似下面的快捷方式创建引擎
engine, err = xorm.NewPostgreSQL(dataSourceName)
engine, err = xorm.NewSqlite3(dataSourceName)
- 创建引擎,且需要使用类ibatis方式配置SQL语句,参考如下方式
var err error
engine, err = xorm.NewPostgreSQL("postgres://postgres:root@localhost:5432/testdb?sslmode=disable")
if err != nil {
t.Fatal(err)
}
/*--------------------------------------------------------------------------------------------------
1、使用RegisterSqlMap()注册SqlMap配置
2、RegisterSqlTemplate()方法注册SSqlTemplate模板配置
3、SqlMap配置文件总根目录和SqlTemplate模板配置文件总根目录可为同一目录
--------------------------------------------------------------------------------------------------*/
//注册SqlMap配置,可选功能,如应用中无需使用SqlMap,可无需初始化
//此处使用xml格式的配置,配置文件根目录为"./sql/oracle",配置文件后缀为".xml"
err = x.RegisterSqlMap(xorm.Xml("./sql/oracle", ".xml"))
if err != nil {
t.Fatal(err)
}
//注册动态SQL模板配置,可选功能,如应用中无需使用SqlTemplate,可无需初始化
//此处注册动态SQL模板配置,使用Pongo2模板引擎,配置文件根目录为"./sql/oracle",配置文件后缀为".stpl"
err = x.RegisterSqlTemplate(xorm.Pongo2("./sql/oracle", ".stpl"))
if err != nil {
t.Fatal(err)
}
//开启SqlMap配置文件和SqlTemplate配置文件更新监控功能,将配置文件更新内容实时更新到内存,如无需要可以不调用该方法
err = engine.StartFSWatcher()
if err != nil {
t.Fatal(err)
}
-
<b>db.RegisterSqlMap()过程</b>
- 使用RegisterSqlMap()方法指定SqlMap配置文件文件格式,配置文件总根目录,配置文件后缀名,RegisterSqlMap()方法按指定目录遍历所配置的目录及其子目录下的所有xml配置文件(<a href="https://github.com/xormplus/xorm/blob/master/test/sql/oracle/studygolang.xml">配置文件样例</a>)或json配置文件(<a href="https://github.com/xormplus/xorm/blob/master/test/sql/oracle/test.json">配置文件样例</a>)
- 解析所有配置SqlMap的xml配置文件或json配置文件
- xml配置文件中sql标签的id属性值作为SqlMap的key,如有重名id,则后加载的覆盖之前加载的配置sql条目
- json配置文件中key值作为SqlMap的key,如有重名key,则后加载的覆盖之前加载的配置sql条目
- json配置文件中key和xml配置文件中sql标签的id属性值有相互重名的,则后加载的覆盖之前加载的配置sql条目
- 配置文件中sql配置会读入内存并缓存
- 由于SqlTemplate模板能完成更多复杂组装和特殊场景需求等强大功能,故SqlMap的xml或json只提供这种极简配置方式,非ibatis的OGNL的表达式实现方式
-
<b>db.RegisterSqlTemplate()过程</b>
- 使用RegisterSqlTemplate()方法指定SqlTemplate模板的模板引擎(支持pongo2、jet、html/template3种模板引擎,但只能选用一种,不能同时混用),配置文件总根目录,配置文件后缀名,RegisterSqlTemplate()方法按指定目录遍历所配置的目录及其子目录及其子目录下的所有stpl模板文件(<a href="https://github.com/xormplus/xorm/blob/master/test/sql/oracle/select.example.stpl">模板文件样例</a>)
- 使用指定模板引擎解析stpl模板文件
- stpl模板文件名作为SqlTemplate存储的key(不包含目录路径),如有不同路径下出现同名文件,则后加载的覆盖之前加载的配置模板内容
- stpl模板内容会读入内存并缓存
-
支持最原始的SQL语句查询
/*-------------------------------------------------------------------------------------
* 第1种方式:返回的结果类型为 []map[string][]byte
-------------------------------------------------------------------------------------*/
sql_1_1 := "select * from user"
results, err := engine.QueryBytes(sql_1_1)
//SqlMapClient和SqlTemplateClient传参方式类同如下2种,具体参见第6种方式和第7种方式
sql_1_2 := "select id,userid,title,createdatetime,content from Article where id=?"
results, err := db.SQL(sql_1_2, 2).QueryBytes()
sql_1_3 := "select id,userid,title,createdatetime,content from Article where id=?id"
paramMap_1_3 := map[string]interface{}{"id": 2}
results, err := db.SQL(sql_1_3, ¶mMap_1_3).QueryBytes()
/*-------------------------------------------------------------------------------------
* 第2种方式:返回的结果类型为 []map[string]string
-------------------------------------------------------------------------------------*/
sql_2_1 := "select * from user"
results, err := engine.QueryString(sql_2_1)
//SqlMapClient和SqlTemplateClient传参方式类同如下2种,具体参见第6种方式和第7种方式
sql_2_2 := "select id,userid,title,createdatetime,content from Article where id=?"
results, err := db.SQL(sql_2_2, 2).QueryString()
sql_2_3 := "select id,userid,title,createdatetime,content from Article where id=?id"
paramMap_2_3 := map[string]interface{}{"id": 2}
results, err := db.SQL(sql_2_3, ¶mMap_2_3).QueryString()
/*-------------------------------------------------------------------------------------
* 第3种方式:返回的结果类型为 []map[string]xorm.Value
-------------------------------------------------------------------------------------*/
//xorm.Value类型本质是[]byte,具有一系列类型转换函数
sql_2_1 := "select * from user"
results, err := engine.QueryValue(sql_2_1)
//SqlMapClient和SqlTemplateClient传参方式类同如下2种,具体参见第6种方式和第7种方式
sql_2_2 := "select id,userid,title,createdatetime,content from Article where id=?"
results, err := db.SQL(sql_2_2, 2).QueryValue()
title := results[0]["title"].String()
sql_2_3 := "select id,userid,title,createdatetime,content from Article where id=?id"
paramMap_2_3 := map[string]interface{}{"id": 2}
results, err := db.SQL(sql_2_3, ¶mMap_2_3).QueryValue()
/*-------------------------------------------------------------------------------------
* 第4种方式:返回的结果类型为 xorm.Result
-------------------------------------------------------------------------------------*/
//xorm.Value类型本质是[]byte,具有一系列类型转换函数
sql_2_1 := "select * from user"
results, err := engine.QueryResult(sql_2_1).List()
//SqlMapClient和SqlTemplateClient传参方式类同如下2种,具体参见第6种方式和第7种方式
sql_2_2 := "select id,userid,title,createdatetime,content from Article where id=?"
result, err := db.SQL(sql_2_2, 2).QueryResult().List()
title := result[0]["createdatetime"].Time("2006-01-02T15:04:05.999Z")
content := result[0]["content"].NullString()
sql_2_3 := "select id,userid,title,createdatetime,content from Article where id=?id"
paramMap_2_3 := map[string]interface{}{"id": 2}
results, err := db.SQL(sql_2_3, ¶mMap_2_3).QueryResult().List()
/*-------------------------------------------------------------------------------------
* 第5种方式:返回的结果类型为 []map[string]interface{}
-------------------------------------------------------------------------------------*/
sql_3_1 := "select * from user"
results, err := engine.QueryInterface(sql_3_1)
//SqlMapClient和SqlTemplateClient传参方式类同如下2种,具体参见第6种方式和第7种方式
sql_3_2 := "select id,userid,title,createdatetime,content from Article where id=?"
results, err := db.SQL(sql_3_2, 2).QueryInterface()
sql_3_3 := "select id,userid,title,createdatetime,content from Article where id=?id"
paramMap_3_3 := map[string]interface{}{"id": 2}
results, err := db.SQL(sql_3_3, ¶mMap_3_3).QueryInterface()
//Query方法返回的是一个ResultMap对象,它有List(),Count(),ListPage(),Json(),Xml()
//Xml(),XmlIndent(),SaveAsCSV(),SaveAsTSV(),SaveAsHTML(),SaveAsXML(),SaveAsXMLWithTagNamePrefixIndent(),
//SaveAsYAML(),SaveAsJSON(),SaveAsXLSX()系列实用函数
sql_3_4 := "select * from user"
//List()方法返回查询的全部结果集,类型为[]map[string]interface{}
results, err := engine.Sql(sql_3_4).Query().List()
//当然也支持这种方法,将数据库中的时间字段格式化,时间字段对应的golang数据类型为time.Time
//当然你也可以在数据库中先使用函数将时间类型的字段格式化成字符串,这里只是提供另外一种方式
//该方式会将所有时间类型的字段都格式化,所以请依据您的实际需求按需使用
results, err := engine.Sql(sql_3_4).QueryWithDateFormat("20060102").List()
sql_3_5 := "select * from user where id = ? and age = ?"
results, err := engine.Sql(sql_3_5, 7, 17).Query().List()
sql_3_6 := "select * from user where id = ?id and age = ?age"
paramMap_3_6 := map[string]interface{}{"id": 7, "age": 17}
results, err := engine.Sql(sql_3_6, ¶mMap_3_6).Query().List()
//此Query()方法返回对象还支持ListPage()方法和Count()方法,这两个方法都是针对数据库查询出来后的结果集进行操作
//此Query()方法返回对象还支持Xml()方法、XmlIndent()方法和Json()方法,相关内容请阅读之后的章节
//ListPage()方法并非数据库分页方法,只是针对数据库查询出来后的结果集[]map[string]interface{}对象取部分切片
//例如以下例子,是取结果集的第1条到第50条记录
results, err := engine.Sql(sql_3_5, 7, 17).Query().ListPage(1,50)
//例如以下例子,是取结果集的第13条到第28条记录
results, err := engine.Sql(sql_3_5, 7, 17).Query().ListPage(13,28)
//此Count()方法也并非使用数据库count函数查询数据库某条件下的记录数,只是针对Sql语句对数据库查询出来后的结果集[]map[string]interface{}对象的数量
//此Count()方法也并非Engine对象和Session对象下的Count()方法,使用时请区分场景
count, err := engine.Sql(sql_3_5, 7, 17).Query().Count()
/*-------------------------------------------------------------------------------------
第6种方式:执行SqlMap配置文件中的Sql语句,返回的结果类型为 []map[string]interface{}
-------------------------------------------------------------------------------------*/
sql_id_4_1 := "sql_4_1" //配置文件中sql标签的id属性,SqlMap的key
results, err := engine.SqlMapClient(sql_id_4_1).Query().List()
sql_id_4_2 := "sql_4_2"
results, err := engine.SqlMapClient(sql_id_4_2, 7, 17).Query().List()
sql_id_4_3 := "sql_4_3"
paramMap_4_3 := map[string]interface{}{"id": 7, "na
