xorm基础学习
- 为什么要学习xorm
- 原本的JDBC操作数据库已经满足我们的所有需求了,但是我们还要提出一个概念叫做:orm(Object-Relation Mapping),一种对象与关系型数据库之间的映射,也可以说将对象持久化到磁盘。通过这样的技术能够将减少代码、便于理解和操作数据库、是数据访问层和数据库层清晰分界、而且能够提高服务器的性能
package main
import (
"log"
"os"
"github.com/go-xorm/xorm"
"xorm.io/core"
_ "github.com/lib/pq"
)
var engine *xorm.Engine
func init() {
log.SetFlags(log.Ldate | log.Lshortfile)
var err error
connStr := "postgres://postgres:ysm@121388@localhost/experiment?sslmode=disable"
engine, err = xorm.NewEngine("postgres", connStr)
if err != nil {
log.Println(err)
}
log.Println("开启postgres数据成功")
f, err := os.OpenFile("sql.log", os.O_APPEND|os.O_CREATE|os.O_RDWR, 0666)
if err != nil {
log.Println(err)
return
}
engine.SetLogger(xorm.NewSimpleLogger(f))
engine.Logger().SetLevel(core.LOG_DEBUG)
engine.ShowSQL(true)
// 设置命名规则,遵从驼峰规则,但是对特殊词支持的更好,使得ID翻译为id而不是i_d, 但是创建表的格式好奇怪啊 select 语句会变成SELECT "ID", "Content", "Version", "UpdateTime", "CreateTime" FROM public."TPhoto";
// engine.SetMapper(core.SameMapper{})
}
// TPhoto 创建图片表
type TPhoto struct {
Id int64 `xorm:"pk notnull unique autoincr"`
Content string `xorm:"notnull"`
Version int64 `xorm:"version"`
UpdateTime int64 `xorm:"updated"`
CreateTime int64 `xorm:"created"`
Name string `xorm:"varchar notnull"`
}
// ShowAllTables 显示所有的table
func ShowAllTables() {
info, err := engine.DBMetas()
if err != nil {
log.Println(err)
return
}
for _, v := range info {
log.Println(v.Name)
}
}
// createTable 创建表
func createTable() {
tPhoto := &TPhoto{}
// 创建表
isExist, err := engine.IsTableExist("t_photo")
if err != nil {
log.Println(err)
return
}
if !isExist {
err := engine.CreateTables(tPhoto)
if err != nil {
log.Println(err)
}
}
// 结构体和表一致,当结构体改变的时候,也能够根据结构体的内容修改表的结构
err = engine.Sync2(tPhoto)
if err != nil {
log.Println(err)
}
}
// createTableSQL 原生的创建表的方式
func createTableSQL() {
SQL := "create table t_small_photo(id int primary key,name varchar)"
isExit, err := engine.IsTableExist("t_small_photo")
if err != nil {
log.Println(err)
return
}
if isExit {
log.Println("t_small_photo已经存在")
}
_, err = engine.Exec(SQL)
if err != nil {
log.Println(err)
return
}
isExit, err = engine.IsTableExist("t_small_photo")
if err != nil {
log.Println(err)
return
}
if isExit {
log.Println("t_small_photo存在")
}
}
// dropTable 删除表
func dropTable() {
tPhoto := &TPhoto{}
// 判断指定表是否存在
isExist, err := engine.IsTableExist("t_photo")
if err != nil {
log.Println(err)
return
}
if !isExist {
// 删除指定的表
err := engine.DropTables(tPhoto)
if err != nil {
log.Println(err)
}
}
}
// insertData 插入数据库,会根据不同的结构体的名字找到表,进行相应数据的修改
func insertData() {
// 插入一条数据
tPhoto := &TPhoto{Content: "content1", Name: "name1"}
_, err := engine.Insert(tPhoto)
if err != nil {
log.Println(err)
return
}
// 插入多条数据
tPhotos := []*TPhoto{
{Content: "content2", Name: "name2"},
{Content: "content3", Name: "name3"},
{Content: "content4", Name: "name4"},
{Content: "content5", Name: "name5"},
}
_, err = engine.Insert(&tPhotos)
if err != nil {
log.Println(err)
}
}
// insertDataSQL 插入数据库,使用SQL方式
func insertDataSQL() {
// 这样不会自动生成 插入时间和修改时间
SQL := "insert into t_photo (content,name) values($1,$2)"
_, err := engine.Exec(SQL, "content7", "name7")
if err != nil {
log.Println(err)
return
}
}
// selectData 查询数据
func selectData() {
/*
Get 查询一条信息 参数不是map(json格式) 也不是数组
Find 查询很多条数据 参数是map(json格式) 或者是 数据
*/
// 查询第一条数据 select * from 表 limit 1
tPhoto := &TPhoto{}
isHas, err := engine.Get(tPhoto)
if err != nil {
log.Println(err)
return
}
log.Println(isHas)
log.Println(tPhoto)
// 毫无差别的查询 select * from 表
tPhotos := make([]TPhoto, 0)
err = engine.Find(&tPhotos)
if err != nil {
log.Println(err)
return
}
log.Println(tPhotos)
// 按条件查找 获取任一条数据 就是根据结构体的名字和表的名字相对应了 select * from t_photo where content='content' and name='name',理解起来就是跟sql中条件的表述一样
tPhotos1 := make([]TPhoto, 0)
err = engine.Where("content = ?", "content1").And("name =?", "name1").Find(&tPhotos1)
if err != nil {
log.Println(err)
return
}
log.Println(tPhotos1)
// 指定查询的数据
tPhtot1 := &TPhoto{}
isHas, err = engine.Select("id,content,name").Where("id = ?", 1).Get(tPhtot1)
if err != nil {
log.Println(err)
return
}
if isHas {
log.Println(tPhtot1)
}
}
// count 统计
func count() {
tPhtot1 := &TPhoto{}
num,err := engine.Where("id = ?", 1).Count(tPhtot1)
if err!=nil{
log.Println(err)
return
}
log.Println(num)
}
// updateData 修改数据
func updateData(){
// 原来是乐观锁带来的小坑,因为使用version标记在修改的时候,update的内容必须包含version
tPhtot1 := &TPhoto{Content:"content12",Name: "name12",Version: 1}
affect,err := engine.Where("id = ?",1).Cols("content,name").Update(tPhtot1)
if err!=nil{
log.Println(err)
return
}
log.Println("affect:",affect)
tPhotos := make([]TPhoto,0)
err = engine.Where("id = ?",1).Find(&tPhotos)
if err!=nil{
log.Println(err)
return
}
log.Println(tPhotos)
}
func main() {
log.Println("学习log")
// 显示所有的表
// ShowAllTables()
// createTableSQL()
// createTable()
// insertData()
// insertDataSQL()
// selectData()
// count()
updateData()
}
注意:当在创建表的对象中有version标记的时候,即是有乐观锁的时候,在update的时候,需要带上version的内容