【GORM框架】ORM介绍、GORM简单连接和高级配置详解

在这里插入图片描述

  • 博主简介:努力学习的大一在校计算机专业学生,热爱学习和创作。目前在学习和分享:数据结构、Go,Java等相关知识。
  • 博主主页: @是瑶瑶子啦
  • 所属专栏: GORM框架学习
  • 近期目标:写好专栏的每一篇文章

在这里插入图片描述

目录

  • 一、简介
    • 1.1:什么是ORM
    • 1.2:ORM的好处
    • 1.3:ORM缺点
  • 二、连接
    • 2.1:简单连接
    • 2.2:高级配置
      • 2.2.1:跳过默认事务
      • 2.2.2:命名策略

一、简介

1.1:什么是ORM

ORM的全称是:Object Relational Mapping(对象关系映射)

其中

  • 对象:指的是程序中对象/实例(在Go程序中就是结构体实例)
  • 关系:指的是关系型数据库(如Mysql)
  • 映射:也就是指程序中的对象、实例在数据库中的映射(这个实例映射到数据库中是某个实例)
    【GORM框架】ORM介绍、GORM简单连接和高级配置详解_第1张图片

结合上图再简单来说:

  • 一个类/结构体,对应数据库的一张表
  • 类/结构体的实例化,对应这张表的一条记录

1.2:ORM的好处

为什么要用到ORM呢?
将类的信息和实例,直接存储到数据库,手写SQL语句,不是也能进行操作吗?

的确可以,但是存在以下问题:

  1. 对象的属性名往往和数据表中的字段不一致,开发人员编写SQL语句要小心谨慎,一一核对,保证彼此互相对应
  2. SQL语句报错的提示信息不准确,排错难度大
  3. 不同数据库sql语句不完全相同
  4. sql注入问题1

相比,使用ORM,我们想要操作某个对象(这里对它进行操作,其实也连同它在数据中映射的数据也要被操作)。如果我们能用操作对象的方法,去操作数据库,那岂不是开发效率大大提升,没错!

1.3:ORM缺点

  1. 使用ORM技术,至少需要掌握一种ORM框架
    • python:SQLAlchemy,DjangoORM
    • Java:Hibernate, Mybatis
    • Golang:GORM
  2. ORM的底层是计算机自动帮我们生成对应的SQl语句,这会消耗计算机资源,对程序性能有影响
  3. 复杂数据库操作,ORM难以处理
  4. SQL语句自动生成的过程不能进行人工干预,灵活性差(开发人员无法定制一些特殊的SQL语句)

二、连接

先新创建一个Go项目

打开命令行,下载驱动和框架

go get gorm.io/driver/mysql
go get gorm.io/gorm

【GORM框架】ORM介绍、GORM简单连接和高级配置详解_第2张图片
新建一个go文件,演示连接操作

2.1:简单连接

package main

import (
	"fmt"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

var DB *gorm.DB

func init() {
	username := "root"     //账号
	password := "55667788" //密码
	host := "127.0.0.1"    //数据库地址,可以是Ip或者域名(这里用的就是localhost,是一个回送地址,值本地机
	port := 3306           //数据库端口
	Dbname := "testdb"     //数据库名
	timeout := "10s"       //连接超时,10秒

	// root:root@tcp(127.0.0.1:3306)/gorm?
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local&timeout=%s", username, password, host, port, Dbname, timeout)
	//连接MYSQL, 获得DB类型实例,用于后面的数据库读写操作。
	db, err := gorm.Open(mysql.Open(dsn))
	if err != nil {
		panic("连接数据库失败, error=" + err.Error())
	}
	// 连接成功
	fmt.Println(db)
	//把其DB类型实例赋给定义好的全局变量
	DB = db
}

func main() {
	fmt.Println(DB)
}

2.2:高级配置

2.2.1:跳过默认事务

为了确保数据一致性,GORM 会在事务里执行写入操作(创建、更新、删除)。如果没有这方面的要求,您可以在初始化时禁用它,这样可以获得60%的性能提升

可以看一下gorm.Open()源码:


// Open initialize db session based on dialector
func Open(dialector Dialector, opts ...Option) (db *DB, err error) {
	config := &Config{}

	sort.Slice(opts, func(i, j int) bool {
		_, isConfig := opts[i].(*Config)
		_, isConfig2 := opts[j].(*Config)
		return isConfig && !isConfig2
	})

	for _, opt := range opts {
		if opt != nil {
			if applyErr := opt.Apply(config); applyErr != nil {
				return nil, applyErr
			}
			defer func(opt Option) {
				if errr := opt.AfterInitialize(db); errr != nil {
					err = errr
				}
			}(opt)
		}
	}

	if d, ok := dialector.(interface{ Apply(*Config) error }); ok {
		if err = d.Apply(config); err != nil {
			return
		}
	}

	if config.NamingStrategy == nil {
		config.NamingStrategy = schema.NamingStrategy{}
	}

	if config.Logger == nil {
		config.Logger = logger.Default
	}

	if config.NowFunc == nil {
		config.NowFunc = func() time.Time { return time.Now().Local() }
	}

	if dialector != nil {
		config.Dialector = dialector
	}

	if config.Plugins == nil {
		config.Plugins = map[string]Plugin{}
	}

	if config.cacheStore == nil {
		config.cacheStore = &sync.Map{}
	}

	db = &DB{Config: config, clone: 1}

	db.callbacks = initializeCallbacks(db)

	if config.ClauseBuilders == nil {
		config.ClauseBuilders = map[string]clause.ClauseBuilder{}
	}

	if config.Dialector != nil {
		err = config.Dialector.Initialize(db)
	}

	preparedStmt := &PreparedStmtDB{
		ConnPool:    db.ConnPool,
		Stmts:       make(map[string]*Stmt),
		Mux:         &sync.RWMutex{},
		PreparedSQL: make([]string, 0, 100),
	}
	db.cacheStore.Store(preparedStmtDBKey, preparedStmt)

	if config.PrepareStmt {
		db.ConnPool = preparedStmt
	}

	db.Statement = &Statement{
		DB:       db,
		ConnPool: db.ConnPool,
		Context:  context.Background(),
		Clauses:  map[string]clause.Clause{},
	}

	if err == nil && !config.DisableAutomaticPing {
		if pinger, ok := db.ConnPool.(interface{ Ping() error }); ok {
			err = pinger.Ping()
		}
	}

	if err != nil {
		config.Logger.Error(context.Background(), "failed to initialize database, got error %v", err)
	}

	return
}

可以看到第二个参数是一个可变参数,可以传入相关配置option

这里我们传入:

&gorm.Config{
  SkipDefaultTransaction: true,
}

所以连接数据库语句可以写成:

db, err := gorm.Open(mysql.Open("gorm.db"), &gorm.Config{
  SkipDefaultTransaction: true,
})

2.2.2:命名策略

  • Go与数据库之间的对应关系
    在这里插入图片描述
  • 建表->定义结构体
package main

import (
	"fmt"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

var DB *gorm.DB

func init() {
	username := "root"     //账号
	password := "55667788" //密码
	host := "127.0.0.1"    //数据库地址,可以是Ip或者域名(这里用的就是localhost,是一个回送地址,值本地机
	port := 3306           //数据库端口
	Dbname := "testdb"     //数据库名
	timeout := "10s"       //连接超时,10秒

	// root:root@tcp(127.0.0.1:3306)/gorm?
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local&timeout=%s", username, password, host, port, Dbname, timeout)
	//连接MYSQL, 获得DB类型实例,用于后面的数据库读写操作。
	db, err := gorm.Open(mysql.Open(dsn))
	if err != nil {
		panic("连接数据库失败, error=" + err.Error())
	}
	// 连接成功
	fmt.Println(db)
	//把其DB类型实例赋给定义好的全局变量
	DB = db
}

// 1)定义一个结构体(在该数据库中创建一张表
type Student struct {
	ID   uint
	Name string
	Age  int
}

func main() {
	//2)将该结构体指针传进去
	DB.AutoMigrate(&Student{})
}

gorm会根据以上建表操作,生成以下语句:

CREATE TABLE `students` (`name` longtext,`age` bigint,`my_student` longtext)
  • 命名策略:

    • 表名是蛇形复数
    • 表名是蛇形复数
  • 当然我们可以修改gorm的这种命名策略:

db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
  NamingStrategy: schema.NamingStrategy{
    TablePrefix:   "f_",  // 表名前缀
    SingularTable: false, // 单数表名
    NoLowerCase:   false, // 关闭小写转换
  },
})

但是以上建表方法有点麻烦,还可以用goland自带的可视化数据库管理工具进行建表等操作,如下

  • 建表

先在Goland软件中,进行数据库连接:
【GORM框架】ORM介绍、GORM简单连接和高级配置详解_第3张图片
可视化查看表结构:
【GORM框架】ORM介绍、GORM简单连接和高级配置详解_第4张图片
选中表,右键单击,modify
【GORM框架】ORM介绍、GORM简单连接和高级配置详解_第5张图片


本文参考:http://docs.fengfengzhidao.com/#/docs/gorm%E6%96%87%E6%A1%A3/1.%E8%BF%9E%E6%8E%A5‘

欢迎在评论区交流和留下你的想法和建议

如果对你有用,还请:评论+点赞+⭐收藏+➕关注

在这里插入图片描述

  • Java岛冒险记【从小白到大佬之路】
  • LeetCode每日一题–进击大厂
  • 算法
  • C/C++
  • Go语言核心编程
  • [数据结构](https://mp.csdn.net/mp_blog/manage/column/allColum

  1. SQL注入是一种安全漏洞,它发生在应用程序使用用户输入数据构造SQL查询语句时,未能正确过滤和转义用户输入数据的情况下。攻击者可以通过在输入数据中注入恶意代码,来改变SQL查询的含义,从而执行未经授权的操作,如删除或修改数据库中的数据,或者绕过身份验证等。
    SQL注入攻击通常发生在Web应用程序中,攻击者可以通过输入恶意的SQL代码来利用该漏洞,从而访问或篡改应用程序的数据库。攻击者可以通过各种方式进行SQL注入攻击,例如在输入字符串中注入SQL代码,使用特殊字符绕过输入验证,修改查询参数等。
    为了防止SQL注入攻击,应用程序应该尽可能使用参数化查询、预编译语句、输入验证和转义等技术来过滤和处理用户输入的数据。例如,使用参数化查询可以在构造SQL查询语句时,将输入数据作为参数传递给查询,从而避免了注入攻击。此外,应用程序还应该定期审计代码,以发现和修复潜在的SQL注入漏洞。 ↩︎

你可能感兴趣的:(GORM框架学习,数据库,mybatis,java,golang,gorm)