一、什么是ORM
- ORM概念:
- ORM全称是 Object Relational Mapping(对象关系映射),其主要作用是在编程中,把面向对象的概念跟数据库中表的概念对相起来
- 举例来说就是,我们定义一个对象,那就对应着一张表,这个对象的实例,就对应着表中的一条记录
- 为什么需要ORM
- 业务中执行sql的时候,需要我们有足够的sql语句基础、需要我们懂得不同数据的sql
- 对于数据来说,最重要最常用的是表;表中有列,orm就是将一张表映射成一个类,表中的列映射成类中的一个类
- 对java和python这种面向对象的语音来说,orm映射没有问题;但是对go语言而言表映射成struct,但是列在go中如何映射呢? -> 列可以映射成struct中的类型,比如int -> int;但是仍然有另外一个问题,数据库中的列具备很好的描述性,但是go的struct有tag
二、常用的orm
- orm选择:不需要纠结应该选择哪一个orm框架,选择以个star数量最高的一定不会错,而且实际上熟悉了一个orm,其他orm的迁移成本是很低的
三、orm的优缺点
- 优点
- 提高了开发效率
- 屏蔽sql细节;可以自动对实体Entity对象与数据库中的Table进行字段与属性的映射;不用直接SQL编码
- 屏蔽各种数据库之间的差异
- 缺点
- orm会牺牲程序的执行效率和固定思维模式
- 太过依赖orm会导致sql理解不够
- 对于固定的orm依赖过重,导致切换到其他的orm代价高
- 如何看待orm和sql之间的关系
- sql为主,orm为辅
- orm主要目的是为了增加代码可维护性和开发效率
四、gorm快速入门
1 - docker启动之前已经安装好的mysql容器
- docker查看容器id:
docker ps -a
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/45d6789ae8c20ae0d878874eef5b2190.png)
- docker停止容器:
docker stop ID
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/d72af4da2d5c4b25974d5e68df9da629.png)
- docker启动容器:
docker start ID
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/3f8b69a9cd3d615af5a5f5b7a6346818.png)
2 - 使用数据库连接工具创建数据库
- 数据库创建
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/8bc073beab0509d638fb4b92a0d51930.png)
3 - 连接mysql
- 需要注意的2个点
- import的需要同步下载
- 密码、IP地址、数据库名需要自行修改
package main
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
func main() {
dsn := "root:XXXX@tcp(192.168.124.51:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"
_, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic(err)
}
}
五、快速体验go-migrate功能
package main
import (
"database/sql"
"log"
"os"
"time"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
type Product struct {
gorm.Model
Code string
Price uint
}
func main() {
dsn := "root:xxxx@tcp(192.168.124.51:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags),
logger.Config{
SlowThreshold: time.Second,
LogLevel: logger.Info,
Colorful: true,
},
)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: newLogger,
})
if err != nil {
panic(err)
}
_ = db.AutoMigrate(&Product{})
}
- 运行上述代码后,我们可以看到已经自动添加了products表:并且控制台输出了执行的sql语句日志
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/fefe10e631871d46734f762680de9914.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/9e3d61b609618f1f0d148221cb696a09.png)
六、基础CRUD
1 - 逻辑删除
- 可以查看执行的sql语句:可以发现
db.Delete(&product, 1)
并不是使用delete,而是使用逻辑删除update掉
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/ed855594b1d170c93d8c3c7a92ed081e.png)
package main
import (
"log"
"os"
"time"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
type Product struct {
gorm.Model
Code string
Price uint
}
func main() {
dsn := "root:xxxx@tcp(192.168.124.51:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags),
logger.Config{
SlowThreshold: time.Second,
LogLevel: logger.Info,
Colorful: true,
},
)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: newLogger,
})
if err != nil {
panic(err)
}
_ = db.AutoMigrate(&Product{})
db.Create(&Product{Code: "D42", Price: 100})
var product Product
db.First(&product, 1)
db.First(&product, "code = ?", "D42")
db.Model(&product).Update("Price", 200)
db.Model(&product).Updates(Product{Price: 200, Code: "F42"})
db.Delete(&product, 1)
}
2 - NullString的使用
- 当我们update零值的情况:
db.Model(&product).Updates(Product{Price: 200, Code: ""}) // 仅更新非零值字段
- 零值
- string的零值:空字符串
""
- uint的零值:0
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/9113a418bc2b4ce7df2480019fd36e3d.png)
- 将code类型修改为sql.NullString
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/9aba2e9a85c665e880ef9391a454cc80.png)
package main
import (
"database/sql"
"log"
"os"
"time"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
type Product struct {
gorm.Model
Code sql.NullString
Price uint
}
func main() {
dsn := "root:xxx@tcp(192.168.124.51:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags),
logger.Config{
SlowThreshold: time.Second,
LogLevel: logger.Info,
Colorful: true,
},
)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: newLogger,
})
if err != nil {
panic(err)
}
_ = db.AutoMigrate(&Product{})
db.Create(&Product{Code: sql.NullString{String: "D42", Valid: true}, Price: 100})
var product Product
db.First(&product, 1)
db.First(&product, "code = ?", "D42")
db.Model(&product).Update("Price", 200)
db.Model(&product).Updates(Product{Price: 200, Code: sql.NullString{String: "", Valid: true}})
db.Delete(&product, 1)
}