目录
ORM
-
ORM:Object Relational Mapping —— 对象关系映射。
-
作用:
-
通过操作结构体对象,来达到操作数据库表的目的。
-
通过结构体对象,来生成数据库表。
-
-
优点:
-
SQL有可能 比较复杂。(Oracle --- 子查询 -- 嵌套)ORM 操作数据库,不需要使用 SQL
-
不同开发者,书写的 SQL 语句执行效率不同。
-
-
go语言支持的 ORM:
-
gORM:JasperXu's 笔记本
-
xORM
-
MySQL
-
确认mysql服务,启动:
ps xua | grep mysql
-
检查mysql服务状态 systemctl status mysql.service
-
连接MySQL数据库: mysql -u root -p
-
查看数据库:show databases;
-
删除数据库:drop database t1; t1 代表库名。
-
选择数据库、查看表:use 数据库名; show tables;
-
删除表 drop table 表名;
-
创建数据库: create database test charset=utf8;
-
创建一个用来赋予权限的账户(例如 root_sql)
CREATE USER 'root_sql'@'localhost' IDENTIFIED BY 'yourpasswd'; GRANT ALL PRIVILEGES ON *.* TO 'root_sql'@'localhost' WITH GRANT OPTION; FLUSH PRIVILEGES;
注意:命令加分号
GROM操作MySQL数据库
建立连接和创建表
代码
package main
import (
"fmt"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
_ "github.com/jinzhu/gorm/dialects/sqlite"
)
// 创建全局结构体
type Student struct {
Id int //[在grom中Id字段]成为默认的主键,自增长 --- 主键索引,查询速度快
Name string
Age int
}
func main() {
// 连接数据库 --- 格式: 用户名:密码@协议(IP:port)/数据库名
conn, err := gorm.Open("mysql", "tian:password@tcp(127.0.0.1:3306)/test")
if err != nil {
fmt.Println("grom.Open err:", err)
return
}
defer conn.Close()
conn.SingularTable(true) // 不要复数表名
// 借助 grom 创建数据库表
fmt.Println(conn.AutoMigrate(new(Student)).Error) // 执行创建过程打印结果
}
结果
tian@ubuntu:~$ sudo service mysql start
tian@ubuntu:~$ mysql -u tian -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 8.0.27-0ubuntu0.20.04.1 (Ubuntu)Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test |
+--------------------+
5 rows in set (0.01 sec)mysql> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -ADatabase changed
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| students |
+----------------+
1 row in set (0.01 sec)mysql> desc students;
+-------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(255) | YES | | NULL | |
| age | int | YES | | NULL | |
+-------+--------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| student |
| students |
+----------------+
2 rows in set (0.02 sec)mysql> desc student;
+-------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(255) | YES | | NULL | |
| age | int | YES | | NULL | |
+-------+--------------+------+-----+---------+----------------+
3 rows in set (0.02 sec)mysql>
gorm 插入数据
func InsertData() {
// 先创建数据 --- 创建对象
var stu Student
stu.Name = "zhangsan"
stu.Age = 18
// 插入(创建)数据
fmt.Println(GlobalConn.Create(&stu).Error) //注意 &
}
mysql> select * from student;
Empty set (0.00 sec)mysql> select * from student;
+----+----------+------+
| id | name | age |
+----+----------+------+
| 1 | zhangsan | 18 |
+----+----------+------+
1 row in set (0.00 sec)
grom 查询数据
查询
// 获取第一条记录,按主键排序
db.First(&user)
SELECT * FROM users ORDER BY id LIMIT 1;
// 获取最后一条记录,按主键排序
db.Last(&user)
SELECT * FROM users ORDER BY id DESC LIMIT 1;
// 获取所有记录
db.Find(&users)
SELECT * FROM users;
// 使用主键获取记录
db.First(&user, 10)
SELECT * FROM users WHERE id = 10;
Select
db.Select("name, age").Find(&users)
SELECT name, age FROM users;
db.Select([]string{"name", "age"}).Find(&users)
SELECT name, age FROM users;
db.Table("users").Select("COALESCE(age,?)", 42).Rows()
SELECT COALESCE(age,'42') FROM users;
WHERE子句
// 获取第一个匹配记录
db.Where("name = ?", "jinzhu").First(&user)
SELECT * FROM users WHERE name = 'jinzhu' limit 1;
// 获取所有匹配记录
db.Where("name = ?", "jinzhu").Find(&users)
SELECT * FROM users WHERE name = 'jinzhu';
db.Where("name <> ?", "jinzhu").Find(&users)
// IN
db.Where("name in (?)", []string{"jinzhu", "jinzhu 2"}).Find(&users)
// LIKE
db.Where("name LIKE ?", "%jin%").Find(&users)
// AND
db.Where("name = ? AND age >= ?", "jinzhu", "22").Find(&users)
// Time
db.Where("updated_at > ?", lastWeek).Find(&users)
db.Where("created_at BETWEEN ? AND ?", lastWeek, today).Find(&users)
func SearchData() {
// 查询第一条
//var stu Student
GlobalConn.First(&stu) //查询第一条的全部信息
//GlobalConn.Select("name, age").First(&stu) // 只是查询第一条 name age
//
//fmt.Println(stu)
查询多条
//var stus []Student
//GlobalConn.Find(&stus)
GlobalConn.Select("name, age").Find(&stus) //Find()查询多条 name age
//fmt.Println(stus)
// WHERE 字句
var stus []Student
// GlobalConn.Select("name, age").Where("name = ?", "list").Find(&stus)//查询姓名为list 的 name age
// GlobalConn.Select("name, age").Where("name = ?", "list").Where("age = ?", 28).Find(&stus)
GlobalConn.Select("name, age").Where("name = ? and age = ?", "list", 28).Find(&stus)
fmt.Println(stus)
}
grom 更新数据
-
Save(): 根据主键更新。 如果数据没有指定主键,不更新 ,变为 “插入”操作。
-
Update(): 更新一个字段。
-
Updates(): 更新多个字段。
func UpdateDate() {
Model(new(Student): 指定更新 “student” 表
Where("name = ?", "zhaoliu"): 指定过滤条件。
Update("name", "lisi").Error):指定 把 “list” 更新成 “zhaoliu”
//fmt.Println(GlobalConn.Model(new(Student)).
// Where("name = ?", "list").
// Update("name", "zhaoliu").Error)
使用`map`更新多个属性,只会更新这些更改的字段
//db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})
// UPDATE users SET name='hello', age=18, actived=false, updated_at='2013-11-17 21:34:10' WHERE id=111;
fmt.Println(GlobalConn.Model(new(Student)).
Where("name = ?", "zhaoliu").
Updates(map[string]interface{}{"name": "wangwu", "age": 50}).Error)
}
grom删除数据
物理删除。真正的执行 Delete。
逻辑删除。不真正删。不执行Delete。
-
创建表时,在表中添加一个 “删除字段” 。当需要删除时,更新 “删除字段”, 更新为 :true
-
查询时,不查询 “删除字段” 为 null 的值。
更改 struct
/*
type Model struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time `sql:"index"`
}
*/
type Student struct {
gorm.Model // golang中,匿名成员 --- 继承!
Name string
Age int
}
软删除
如果模型有DeletedAt
字段,它将自动获得软删除功能! 那么在调用Delete
时不会从数据库中永久删除,而是只将字段DeletedAt
的值设置为当前时间。
func DeleteData() {
fmt.Println(GlobalConn.Where("name = ?", "zhangsan").Delete(new(Student)).Error)
}
删除后 deleted_at 值为删除时间,反复删除,时间也是第一次的时间
软查询封装在gorm中,SQL语句中查询可以查到,go代码中查不到。
通过go函数查询
GlobalConn.Find(&stu)
想 查询 “软删除”的数据:
GlobalConn.Unscoped().Find(&stu)
想实现 物理删除
// --- 借助 Unscoped() 执行删除。
GlobalConn.Unscoped().Where("name = ?", "lisi").Delete(new(Student))
GORM设置表属性
修改表字段
结论:
- 修改表属性,只能在第一次建表的时候,有效!
- 或者给表增加新字段的时候,有效!
- 其他场景,修改表属性 ,在 gorm 操作中,无效!
// 创建全局结构体
type Student struct {
Id int //[在grom中Id字段]成为默认的主键,自增长 --- 主键索引,查询速度快
Name string `gorm:"size:100;default:'xiaoming'"` // string -- varcha 默认大小255.可以在创建表时,指定表的大小。默认值 xiaoming
Age int
Class int `gorm:"not null"`
}