Go language gorm framework MySQL practice

gorm is an ORM framework written in Go language. Complete documentation, developer friendly, support mainstream databases.

I recently supplemented the knowledge of various basic frameworks and operation bases of Go language, and finally reached the database stage. When searching data, I basically recommended this framework, which shows its popularity. After constantly trying to practice, I summarized some experience and ways of use for beginners' reference.

When using the Java language before, I used two kinds of JDBC and mybatis. One is to operate the database locally, and the other is to use them in the Springboot project. Both of them are customarily based on MySQL statements, which are spelled at the operation level. However, there are almost no complete SQL statements in gorm framework, which are all through methods and parameters

go.mod

github.com/jinzhu/gorm v1.9.16

When you execute Go Mod Tidy, you will automatically add the required dependencies (this term may not be correct) to the mod file.

go.mod I'm not very familiar with now. I also finished copying ability launch + IDE prompt. Generally speaking, it's relatively smooth.

The dependencies in my code are as follows:

import (
 "fmt"
 "funtester/base"
 "funtester/futil"
 "github.com/jinzhu/gorm"
 _ "github.com/jinzhu/gorm/dialects/mysql"
 "log"
 "testing"
 "time"
)

initialization

The content of this Demo is basic. I can't use high-level Demo, and I can't use it at present. The demonstration is divided into two categories: initializing the connection and initializing the database. Because gorm has its own database initialization function, it will create the database table corresponding to the Model (this needs to be opened manually), so this is still commonly used in the test. If supplemented by the method of data initialization, it can basically meet the needs of our daily development and test services.

func init() {
 var err error
 drive, err = gorm.Open("mysql", "root:root123456@(localhost:3306)/funtester?charset=utf8&parseTime=true")
 if err != nil {
  fmt.Println(err)
  log.Fatalln("mysql conntect err")
 }
 drive.DB().SetMaxOpenConns(200)
 drive.DB().SetConnMaxLifetime(10 * time.Second)
 drive.DB().SetConnMaxIdleTime(10 * time.Second)
 drive.DB().SetMaxIdleConns(20)
 // Migrate schema
 drive.AutoMigrate(&Funtester{})
 //Note: AutoMigrate will create tables, missing foreign keys, constraints, columns and indexes, and will change the type of existing columns (if their size, precision and whether they are empty can be changed). Unused columns are not deleted to protect your data.
 //db.AutoMigrate(&User{}, &Product{}, &Order{})
 //drive. Set("gorm:table_options", "ENGINE=InnoDB"). Automigrate (& funtester {}) / / migration with parameters

}

Model

type Funtester struct {
 gorm.Model
 Name string
 Age  int
}

Here we share the table structure of MySQL database:

DROP TABLE IF EXISTS `funtesters`;
CREATE TABLE `funtesters` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `age` int unsigned DEFAULT NULL,
  `created_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `created_at` datetime DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,
  `deleted_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_funtesters_deleted_at` (`deleted_at`)
) ENGINE=InnoDB AUTO_INCREMENT=241861 DEFAULT CHARSET=utf8mb3;

SET FOREIGN_KEY_CHECKS = 1;

Here you should clearly see the logic when gorm initializes the database. Let's share gorm Model source code:

type Model struct {
 ID        uint `gorm:"primary_key"`
 CreatedAt time.Time
 UpdatedAt time.Time
 DeletedAt *time.Time `sql:"index"`
}

select

The following is a demonstration of the common syntax of select, which is divided into two parts: one is partial basis and the other is partial complexity (mainly multi query condition concatenation). It is obvious here that the idea of gorm splicing query conditions is to classify the query conditions, then write different conditions separately, and use gorm framework to splice SQL statements.

func TestSelect1(t *testing.T) {
 var f Funtester
 drive.First(&f, 34)//Default id
 last := drive.Last(&f, "age != 1")//Add condition
 fmt.Printf("Number of records queried %d "+base.LINE, last.RowsAffected)
 fmt.Println(f)
 take := drive.Take(&f) //Do not specify order
 fmt.Println(take.RowsAffected)
}
// TestSelect2
// @Description: common query and processing results
// @param t
func TestSelect2(t *testing.T) {
 var fs []Funtester
 var f Funtester
 drive.Where("id = ?", 45).First(&f)//Another way of writing
 //fmt.Println(f)
 find := drive.Where("name like ?", "fun%").Find(&fs).Limit(10).Order("id")//Concatenation of multiple query conditions
 rows, _ := find.Rows()//Get results
 defer rows.Close()
 for rows.Next() {
  var ff Funtester
  drive.ScanRows(rows, &ff)
  fmt.Println(ff.Age, ff.Name)
 }
 //Another way of writing
 var f1 Funtester
 drive.Where("name LIKE ?", "fun").Or("id = ?", 123).First(&f1)
 fmt.Println(f1)

}

update

With the foundation of select, it's easier to look at update.

// TestUpdate
// @Description: update
// @param t
func TestUpdate(t *testing.T) {
 drive.Model(&Funtester{}).Where("id = ?", 241860).Update("name", base.FunTester+"3")
}

insert

gorm official documents support batch insertion, but there is no relevant support in this dependency package. If you use the same dependency as me,

// TestInsert
// @Description: add
// @param t
func TestInsert(t *testing.T) {
 value := &Funtester{Name: "FunTester" + futil.RandomStr(10)}
 drive.Create(value)
 drive.Select("name", "age").Create(value) //Only the values of the name and age fields are created
 futil.Sleep(1)
 drive.Omit("age", "name").Create(&Funtester{Name: "fds",Age: 122})   //Filter the creation of age and name fields
 fs := []Funtester{{Name: "fs" + futil.RandomStr(10), Age: 12}, {Name: "fs" + futil.RandomStr(10), Age: 12}}
 drive.Create(&fs)//This operation is not supported here
}

delete

The deletion operation is the same as the above two operations.

func TestDelete(t *testing.T) {
 db := drive.Where("id = ?", 241859).Delete(&Funtester{})
 fmt.Println(db.RowsAffected)
}

SQL execution

Of course, gorm also supports the direct execution of SQL statements. One special is that the query results need to be parsed when executing query statements.

// TestSql
// @Description: execute SQL directly
// @param t
func TestSql(t *testing.T) {
 var funtester []Funtester
 scan := drive.Raw("select * from funtesters where id > 333 limit 10").Scan(&funtester)
 fmt.Println(scan.RowsAffected)
 fmt.Println(funtester)
}

Transaction & rollback

In the use of gorm advanced syntax, I think this is very practical and suitable for the execution of some test statements.

// TestRollBack
// @Description: transaction & rollback
// @param t
func TestRollBack(t *testing.T) {
 funtester := Funtester{Name: base.FunTester, Age: 32232}
 begin := drive.Begin()
 err := begin.Create(&funtester).Error
 if err != nil {
  begin.Rollback()
 }
 begin.Commit()

}

The basic use of gorm has been shared. Next time, share the practice of using gorm for performance testing.

Added by cdinca on Tue, 08 Feb 2022 10:00:24 +0200