gorm框架
连接
需要下载mysql的驱动
go get gorm.io/driver/mysql
go get gorm.io/gorm
约定
- 主键:GORM 使用一个名为ID 的字段作为每个模型的默认主键。
- 表名:默认情况下,GORM 将结构体名称转换为 snake_case 并为表名加上复数形式。 例如,一个 User 结构体在数据库中的表名变为 users 。
- 列名:GORM 自动将结构体字段名称转换为 snake_case 作为数据库中的列名。
- 时间戳字段:GORM使用字段 CreatedAt 和 UpdatedAt 来自动跟踪记录的创建和更新时间。
简单连接
username := "root" //账号
password := "325523" //密码
host := "127.0.0.1" //数据库地址,可以是Ip或者域名
port := 3306 //数据库端口
Dbname := "gorm" //数据库名
timeout := "10s" //连接超时,10秒// root:325523@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), &gorm.Config{//SkipDefaultTransaction: true, //设置跳过默认事务NamingStrategy: schema.NamingStrategy{TablePrefix: "f_", //表名前缀SingularTable: true, //是否单数表名NoLowerCase: true, //是否不要小写转换},
})if err != nil {panic("连接数据库失败, error=" + err.Error())
}
//连接成功
//gorm.DB是GORM库中的一个结构体,用于表示数据库连接,可以在整个程序中访问和操作数据库
fmt.Println(db)
高级配置
跳过默认事务
为了确保数据一致性,GORM 会在事务里执行写入操作(创建、更新、删除)。如果没有这方面的要求,您可以在初始化时禁用它,这样可以获得60%的性能提升
db, err := gorm.Open(mysql.Open("gorm.db"), &gorm.Config{SkipDefaultTransaction: true,
})
命名策略
gorm采用的命名策略是,表名是蛇形复数,字段名是蛇形单数(蛇形命名:单词之间采用下划线分割,单词全小写)
type Student struct {Name stringAge intMyStudent string
}
gorm会为我们这样生成表结构
CREATE TABLE `students` (`name` longtext,`age` bigint,`my_student` longtext)
我们也可以修改这些策略
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{NamingStrategy: schema.NamingStrategy{TablePrefix: "f_", // 表名前缀SingularTable: false, // 关闭单数表名NoLowerCase: false, // 是否不要小写转换(false代表否,表示要小写转换,将大写转换为小写)},
})//生成的表
CREATE TABLE `f_students` (`Name` longtext,`Age` bigint,`MyStudent` longtext)
显示日志
gorm的默认日志是只打印错误和慢SQL
可以自己设置
var mysqlLogger logger.Interface
// 要显示的日志等级
mysqlLogger = logger.Default.LogMode(logger.Info)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{Logger: mysqlLogger,
})
如果你想自定义日志的显示
那么可以使用如下代码
newLogger := logger.New(log.New(os.Stdout, "\r\n", log.LstdFlags), // (日志输出的目标,前缀和日志包含的内容)logger.Config{SlowThreshold: time.Second, // 慢 SQL 阈值LogLevel: logger.Info, // 日志级别IgnoreRecordNotFoundError: true, // 忽略ErrRecordNotFound(记录未找到)错误Colorful: true, // 使用彩色打印},
)db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{Logger: newLogger,
})
部分展示日志
var student Student
session := DB.Session(&gorm.Session{Logger: newLogger,
})
session.First(&student)
// SELECT * FROM `students` ORDER BY `students`.`name` LIMIT 1
如果只想某些语句显示日志
DB.Debug().First(&model)
模型定义
在GORM中模型(Models)通常是正常定义的结构体、基本的go类型或它们的指针。 同时也支持sql.Scanner及driver.Valuer接口(interfaces)。
gorm.Model
为了方便模型定义,GORM内置了一个gorm.Model结构体。gorm.Model是一个包含了ID, CreatedAt, UpdatedAt, DeletedAt四个字段的Golang结构体。
// gorm.Model 定义(go语言内置)
type Model struct {ID uint `gorm:"primary_key"`CreatedAt time.Time // 初次创建记录的时间UpdatedAt time.Time // 每次更新记录的时间DeletedAt *time.Time // 删除该记录的时间
}
- ID :每个记录的唯一标识符(主键)。
- CreatedAt :在创建记录时自动设置为当前时间。
- UpdatedAt:每当记录更新时,自动更新为当前时间。
- DeletedAt:用于软删除(将记录标记为已删除,而实际上并未从数据库中删除)。
你可以将它嵌入到你自己的结构体模型中:
// 将 `ID`, `CreatedAt`, `UpdatedAt`, `DeletedAt`字段注入到`User`模型中
type User struct {gorm.ModelName string
}
模型定义示例
type User struct {gorm.Model Name stringAge sql.NullInt64Birthday *time.TimeEmail string `gorm:"type:varchar(100);unique_index"`Role string `gorm:"size:255"` // 设置字段大小为255MemberNumber *string `gorm:"unique;not null"` // 设置会员号(member number)唯一并且不为空Num int `gorm:"AUTO_INCREMENT"` // 设置 num 为自增类型Address string `gorm:"index:addr"` // 给address字段创建名为addr的索引IgnoreMe int `gorm:"-"` // 忽略本字段
}
结构体标记(tags)
使用结构体声明模型时,标记(tags)是可选项。gorm支持以下标记:
支持的结构体标记(Struct tags)
Column | 指定列名 |
Type | 指定列数据类型 |
Size | 指定列大小, 默认值255 |
PRIMARY_KEY | 将列指定为主键 |
UNIQUE | 将列指定为唯一 |
DEFAULT | 指定列默认值 |
PRECISION | 指定列精度 |
NOT NULL | 将列指定为非 NULL |
AUTO_INCREMENT | 指定列是否为自增类型 |
INDEX | 创建具有或不带名称的索引, 如果多个索引同名则创建复合索引 |
UNIQUE_INDEX | 和INDEX 类似,只不过创建的是唯一索引 |
EMBEDDED | 将结构设置为嵌入 |
EMBEDDED_PREFIX | 设置嵌入结构的前缀 |
- | 忽略此字段 |
关联相关标记(tags)
MANY2MANY | 指定连接表 |
FOREIGNKEY | 设置外键 |
ASSOCIATION_FOREIGNKEY | 设置关联外键 |
POLYMORPHIC | 指定多态类型 |
POLYMORPHIC_VALUE | 指定多态值 |
JOINTABLE_FOREIGNKEY | 指定连接表的外键 |
ASSOCIATION_JOINTABLE_FOREIGNKEY | 指定连接表的关联外键 |
SAVE_ASSOCIATIONS | 是否自动完成 save 的相关操作 |
ASSOCIATION_AUTOUPDATE | 是否自动完成 update 的相关操作 |
ASSOCIATION_AUTOCREATE | 是否自动完成 create 的相关操作 |
ASSOCIATION_SAVE_REFERENCE | 是否自动完成引用的 save 的相关操作 |
PRELOAD | 是否自动完成预加载的相关操作 |
模型是标准的 struct,由 Go 的基本数据类型、实现了 Scanner 和 Valuer 接口的自定义类型及其指针或别名组成
定义一张表
type Student struct {ID uint // gorm会默认使用ID字段作为主键Name stringEmail *string // 使用指针是为了存空值
}
小写属性是不会生成字段的
自动生成表结构
// 可以放多个
DB.AutoMigrate(&Student{})
AutoMigrate的逻辑是只新增,不删除,不修改(类型不修改,大小会修改)
例如将字段名Name修改为Name1,进行迁移,会多出一个name1的字段(原本name字段不会被删除)
AutoMigrate 方法的核心逻辑如下:
- 新增字段:如果模型中添加了新的字段,AutoMigrate 会在数据库表中相应地新增这些字段。
- 不删除字段:如果模型中删除了某个字段,AutoMigrate 不会删除数据库中的这个字段。这样可以避免数据丢失。
- 不修改字段类型:虽然可以通过 AutoMigrate 来调整字段的大小或其他属性,但一般来说,字段的类型是不被修改的。如果需要修改字段类型,通常需要手动执行相应的 SQL 语句
修改大小
我们可以使用gorm的标签进行修改
有两种方式
Name string `gorm:"type:varchar(12)"`
Name string `gorm:"size:2"`
字段标签
type 定义字段类型
size 定义字段大小
column 自定义列名
primaryKey 将列定义为主键
unique 将列定义为唯一键
default 定义列的默认值
not null 不可为空
embedded 嵌套字段
embeddedPrefix 嵌套字段前缀
comment 注释
多个标签之前用 ; 连接
type StudentInfo struct {Email *string `gorm:"size:32"` // 使用指针是为了存空值Addr string `gorm:"column:y_addr;size:16"`Gender bool `gorm:"default:true"`
}
type Student struct {Name string `gorm:"type:varchar(12);not null;comment:用户名"`UUID string `gorm:"primaryKey;unique;comment:主键"`Info StudentInfo `gorm:"embedded;embeddedPrefix:s_"`
}// 建表语句
CREATE TABLE `students` (`name` varchar(12) NOT NULL COMMENT '用户名',`uuid` varchar(191) UNIQUE COMMENT '主键',`s_email` varchar(32),`s_y_addr` varchar(16),`s_gender` boolean DEFAULT true,PRIMARY KEY (`uuid`)
)
单表操作
表结构
type Student struct {ID uint `gorm:"size:3"`Name string `gorm:"size:8"`Age int `gorm:"size:3"`Gender boolEmail *string `gorm:"size:32"` //指针类型,可以传nil值
}
选定/忽略字段
Select选定字段
Omit忽略字段
增加(Create)
忽略零值
单条插入
email := "xxx@qq.com"
// 创建记录
student := Student{Name: "枫枫",Age: 21,Gender: true,Email: &email,
}
DB.Create(&student)
fmt.Printf("%#v\n", student)
// main.Student{ID:0x2, Name:"zhangsan", Age:23, Gender:false, Email:(*string)(0x11d40980)}
// 由于我们传递的是一个指针,调用完Create之后,student这个对象上面就有该记录的信息了,如创建的id
有两个地方需要注意
- 指针类型是为了更好的存nil类型,但是传值的时候,也记得传指针
- Create接收的是一个指针,而不是值
批量插入
Create方法还可以用于插入多条记录
var studentList []Student
for i := 0; i < 100; i++ {studentList = append(studentList, Student{Name: fmt.Sprintf("机器人%d号", i+1),Age: 21,Gender: true,Email: &email,})
}
DB.Create(&studentList)
既可以使用结构体或map来创建,当使用map来创建时,钩子方法不会执行,关联不会被保存且不会回写主键
注意
可以通过 tag 定义字段的默认值,比如:
type User struct {ID int64Name string `gorm:"default:'小王子'"`Age int64
}
通过tag定义字段的默认值,在创建记录时候生成的 SQL 语句会排除没有值或值为零值的字段。 在将记录插入到数据库后,Gorm会从数据库加载那些字段的默认值。
举个例子:
var user = User{Name: "", Age: 99}
db.Create(&user)
上面代码实际执行的SQL语句是INSERT INTO users("age") values('99');,排除了零值字段Name,而在数据库中这一条数据会使用设置的默认值"小王子"作为Name字段的值。
所有字段的零值都不会保存到数据库内,但会使用他们的默认值。 如果想避免这种情况,可以考虑使用指针或实现 Scanner/Valuer接口,比如:
使用指针方式实现零值存入数据库
// 使用指针
type User struct {ID int64Name *string `gorm:"default:'小王子'"`Age int64
}
user := User{Name: new(string), Age: 18))}
db.Create(&user) // 此时数据库中该条记录name字段的值就是''
使用Scanner/Valuer接口方式实现零值存入数据库
// 使用 Scanner/Valuer
type User struct {ID int64Name sql.NullString `gorm:"default:'小王子'"` // sql.NullString 实现了Scanner/Valuer接口Age int64
}
user := User{Name: sql.NullString{"", true}, Age:18}
db.Create(&user) // 此时数据库中该条记录name字段的值就是''
查询
单条查询(Take)
根据顺序查询
var student Student
DB.Take(&student) //查找表中一条匹配的记录,并将其封装到student中,方法返回一个错误
// SELECT * FROM `students` LIMIT 1DB.First(&student) //查询第一条匹配的数据(主键升序)并将其封装到student中,没有找到时不会返回错误,而是将结果设置为该结构体类型的零值
// SELECT * FROM `students` ORDER BY `students`.`id` LIMIT 1DB.Last(&student) //查询表中最后一条匹配的数据(主键降序)并将其封装到student中,没有找到时不会返回错误,而是将结果设置为该结构体类型的零值
// SELECT * FROM `students` ORDER BY `students`.`id` DESC LIMIT 1
First 和 Last 方法会按主键排序找到第一条记录和最后一条记录 (分别)。 只有在目标 struct 是指针或者通过 db.Model() 指定 model 时,该方法才有效。如果相关 model 没有定义主键,那么将按 model 的第一个字段进行排序
Model()方法是一个非常重要的函数,它用于指定后续数据库操作所针对的模型(Model)。这个方法通常用于告诉GORM你想要对哪个模型进行操作,特别是在执行更新(Update)、删除(Delete)等操作时,你需要明确指出操作的目标模型。
- 不影响原始记录:使用Model()方法时,你不需要传入具体的实例,而只需要传入模型的类型。这意味着GORM不会自动加载任何记录,而是根据你提供的模型类型来确定操作的目标。
- 链式操作:Model()方法返回的是一个*gorm.DB对象,这意味着你可以将它与其他GORM方法链式调用,如Where()、Updates()、Update()、Delete()等。
根据主键查询
var student Student
DB.Take(&student, 2)//查询主键id是2的
fmt.Println(student)student = Student{} // 重新赋值
DB.Take(&student, "4")//查询主键id是"4"(字符串)的
fmt.Println(student)
Take的第二个参数,默认会根据主键查询,可以是字符串,可以是数字
根据其他条件查询
使用?作为占位符,将查询的内容放入?
var student Student
DB.Take(&student, "name = ?", "机器人27号")
fmt.Println(student)SELECT * FROM `students` WHERE name = '机器人27号' LIMIT 1
使用?可以有效的防止sql注入,它的原理就是将参数全部转义,将"机器人27号"识别为字符串,去掉双引号用单引号包围,替换掉?占位符
var student []Student
//不会出现sql注入
DB.Take(&student, "name = ?", "机器人27号' or 1=1;#")
//SELECT * FROM `students` WHERE name = '机器人27号' or 1=1;#' LIMIT 1 //会出现sql注入
DB.Take(&student,fmt.sprintf("name = '%s'","机器人27号' or 1=1;#'))
//SELECT * FROM `students` WHERE name = '机器人27号' or 1=1;#' LIMIT 1
根据struct查询
会忽略零值
var student Student // 只能有一个主键值 student.ID = 2 //student.Name = "枫枫" DB.Take(&student) fmt.Println(student)
多条查询(Find)
1.使用Find()方法
先将所有符合条件的记录都加载到studentList切片中,再进行更新操作(先查询再更新)。
对单个对象使用Find而不带limit,db.Find(&user)将会查询整个表并且只返回第一个对象。
2.使用Model()方法
直接在数据库层面进行条件筛选和更新,不需要将所有记录加载到内存中。这在处理大量数据时更为高效,因为它只涉及一次数据库操作。
根据顺序查询
var studentList []Student
DB.Find(&studentList)//查询所有数据并将其封装到studentList
for _, student := range studentList {fmt.Println(student)
}// 由于email是指针类型,所以看不到实际的内容
// 但是序列化之后,会转换为我们可以看得懂的方式
var studentList []Student
DB.Find(&studentList)
for _, student := range studentList {data, _ := json.Marshal(student)fmt.Println(string(data))
}
根据主键列表查询
var studentList []Student
DB.Find(&studentList, []int{1, 3, 5, 7})
DB.Find(&studentList, 1, 3, 5, 7) // 二者效果相同
fmt.Println(studentList)
根据其他条件查询
DB.Find(&studentList, "name in ?", []string{"枫枫", "zhangsan"})
获取结果
1.获取查询的记录数量(受影响的行数)
count := DB.Find(&studentList).RowsAffected
2.是否查询失败,返回错误信息
err := DB.Find(&studentList).Error
查询失败有:查询为空,查询条件错误,sql语法错误
可以使用判断
var student Student
err := DB.Take(&student, "xx").Error
switch err {
case gorm.ErrRecordNotFound:fmt.Println("没有找到")
default:fmt.Println("sql错误")
}
更新
更新的前提的先查询到记录
保存所有字段(更新单条记录)(Save)
- 不要将 Save 和 Model一同使用, 这是未定义的行为
- 保存是一个组合函数。 如果保存值不包含主键,它将执行 Create,否则它将执行 Update (包含所有字段)。
它会保存所有字段,即使零值也会更新(不会忽略零值)
var student Student
DB.Take(&student)//先查询到记录才能更新
student.Age = 23
// 全字段更新
DB.Save(&student)
// UPDATE `students` SET `name`='枫枫',`age`=23,`gender`=true,`email`='xxx@qq.com' WHERE `id` = 1//零值也会更新
DB.Take(&student)//先查询到记录才能更新
student.Age = 0
// 全字段更新
DB.Save(&student)
// UPDATE `students` SET `name`='枫枫',`age`=0,`gender`=true,`email`='xxx@qq.com' WHERE `id` = 1
可以使用select选择要更新的字段
var student Student
DB.Take(&student)//先查询到记录
student.Name = "xiaoming"
student.Age = 21
// 更新指定字段(只更新age,不更新name),Select中传入表中字段名
DB.Select("age").Save(&student)
// UPDATE `students` SET `age`=21 WHERE `id` = 1
更新多条记录
更新单个字段(Update)
Update()方法
- 更新单个字段,只接受两个参数:字段名和一个值
- 忽略零值字段,只更新非零值字段(如果传入的是该字段类型的零值,该字段不会被更新)
给所有年龄21的学生,都更新一下邮箱
var studentList []Student
//以下两种效果一样,效率不同
DB.Find(&studentList, "age = ?", 21).Update("email", "is21@qq.com")
DB.Model(&Student{}).Where("age = ?", 21).Update("email", "is21@qq.com")
// UPDATE `students` SET `email`='is22@qq.com' WHERE age = 21
更新多个字段(Updates)
Updates方法
- 一次性更新多个字段,接受一个结构体作为参数,包含要更新的字段和它们的新值
- 忽略零值字段,只更新非零值字段(如果传入的是该字段类型的零值,该字段不会被更新)
email := "xxx@qq.com"
DB.Model(&Student{}).Where("age = ?", 21).Updates(Student{Email: &email,Gender: false, // Gender属性设为零值(bool类型),这个不会更新
})
// 只有email属性会被更新
// UPDATE `students` SET `email`='xxx@qq.com' WHERE age = 21
用select选中特定字段可以更新零值
email := "xxx1@qq.com"
//使用Select方法指定要更新的字段,即使是零值也会被更新
DB.Model(&Student{}).Where("age = ?", 21).Select("gender", "email").Updates(Student{Email: &email,Gender: false, //设置为零值也会被更新
})
// UPDATE `students` SET `gender`=false,`email`='xxx1@qq.com' WHERE age = 21
用map也可以更新零值
DB.Model(&Student{}).Where("age = ?", 21).Updates(map[string]any{"email": &email,"gender": false, //使用map,即使是零值也会被更新
})
删除(Delete)
删除一条记录
删除一条记录时,删除对象需要指定主键,否则会触发 批量删除,例如:
// email 的 ID 是 `10`
db.Delete(&email)
// DELETE from emails where id = 10;// 带额外条件的删除
db.Where("name = ?", "jinzhu").Delete(&email)
// DELETE from emails where id = 10 AND name = "jinzhu";
根据主键删除
GORM 允许通过主键(可以是复合主键)和内联条件来删除对象
db.Delete(&User{}, 10)
// DELETE FROM users WHERE id = 10;db.Delete(&User{}, "10")
// DELETE FROM users WHERE id = 10;db.Delete(&users, []int{1,2,3})
// DELETE FROM users WHERE id IN (1,2,3)
批量删除
如果指定的值不包括主属性,那么 GORM 会执行批量删除,它将删除所有匹配的记录
db.Where("email LIKE ?", "%jinzhu%").Delete(&Email{})
// DELETE from emails where email LIKE "%jinzhu%";db.Delete(&Email{}, "email LIKE ?", "%jinzhu%")
// DELETE from emails where email LIKE "%jinzhu%";
Hook钩子函数
对象生命周期
Hook 是在创建、查询、更新、删除等操作之前、之后调用的函数。
如果您已经为模型定义了指定的方法,它会在创建、更新、查询、删除时自动被调用。如果任何回调返回错误,GORM 将停止后续的操作并回滚事务。
钩子方法的函数签名应该是 func(*gorm.DB) error
创建对象
创建时可用的 hook
// 开始事务
BeforeSave
BeforeCreate
// 关联前的 save
// 插入记录至 db
// 关联后的 save
AfterCreate
AfterSave
// 提交或回滚事务
代码示例:
func (u *User) BeforeCreate(tx *gorm.DB) (err error) {u.UUID = uuid.New()if !u.IsValid() {err = errors.New("can't save invalid data")}return
}func (u *User) AfterCreate(tx *gorm.DB) (err error) {if u.ID == 1 {tx.Model(u).Update("role", "admin")}return
}
注意 在 GORM 中保存、删除操作会默认运行在事务上, 因此在事务完成之前该事务中所作的更改是不可见的,如果您的钩子返回了任何错误,则修改将被回滚。
func (u *User) AfterCreate(tx *gorm.DB) (err error) {if !u.IsValid() {return errors.New("rollback invalid user")}return nil
}
更新对象
// 开始事务
BeforeSave
BeforeUpdate
// 关联前的 save
// 更新 db
// 关联后的 save
AfterUpdate
AfterSave
// 提交或回滚事务
func (u *User) BeforeUpdate(tx *gorm.DB) (err error) {if u.readonly() {err = errors.New("read only user")}return
}// 在同一个事务中更新数据
func (u *User) AfterUpdate(tx *gorm.DB) (err error) {if u.Confirmed {tx.Model(&Address{}).Where("user_id = ?", u.ID).Update("verfied", true)}return
}
删除对象
删除时可用的 hook
// 开始事务
BeforeDelete
// 删除 db 中的数据
AfterDelete
// 提交或回滚事务
代码示例:
// 在同一个事务中更新数据
func (u *User) AfterDelete(tx *gorm.DB) (err error) {if u.Confirmed {tx.Model(&Address{}).Where("user_id = ?", u.ID).Update("invalid", false)}return
}
查询对象
查询时可用的 hook
// 从 db 中加载数据
// Preloading (eager loading)
AfterFind
代码示例:
func (u *User) AfterFind(tx *gorm.DB) (err error) {if u.MemberShip == "" {u.MemberShip = "user"}return
}
修改当前操作
func (u *User) BeforeCreate(tx *gorm.DB) error {// 通过 tx.Statement 修改当前操作,例如:tx.Statement.Select("Name", "Age")tx.Statement.AddClause(clause.OnConflict{DoNothing: true})
//向当前的数据库操作添加了一个冲突处理条款,指定如果尝试插入的记录与现有记录发生冲突(例如,违反了唯一性约束),则不执行任何操作
//这个设置通常用于INSERT 操作,以处理可能的重复插入。// tx 是带有 `NewDB` 选项的新会话模式 // 基于 tx 的操作会在同一个事务中,但不会带上任何当前的条件err := tx.First(&role, "name = ?", user.Role).Error// SELECT * FROM roles WHERE name = "admin"// ...return err
}
这段代码的主要作用是在创建 User 记录之前,先查询一个与 User 相关的角色信息,并处理可能的数据库冲突。这个查询操作的结果(是否成功)将决定 BeforeCreate 钩子函数的返回值,从而可能影响 User 记录的创建过程。
相关文章:
gorm框架
连接 需要下载mysql的驱动 go get gorm.io/driver/mysql go get gorm.io/gorm 约定 主键:GORM 使用一个名为ID 的字段作为每个模型的默认主键。表名:默认情况下,GORM 将结构体名称转换为 snake_case 并为表名加上复数形式。 例如…...
免费送源码:Java+Springboot+MySQL Springboot多租户博客网站的设计 计算机毕业设计原创定制
Springboot多租户博客网站的设计 摘 要 博客网站是当今网络的热点,博客技术的出现使得每个人可以零成本、零维护地创建自己的网络媒体,Blog站点所形成的网状结构促成了不同于以往社区的Blog文化,Blog技术缔造了“博客”文化。本文课题研究的“…...
【ASR技术】WhisperX安装使用
介绍 WhisperX 是一个开源的自动语音识别(ASR)项目,由 m-bain 开发。该项目基于 OpenAI 的 Whisper 模型,通过引入批量推理、强制音素对齐和语音活动检测等技术。提供快速自动语音识别(large-v2 为 70 倍实时…...
【计算机网络】协议定制
一、结构化数据传输流程 这里涉及协议定制、序列化/反序列化的知识 对于序列化和反序列化,有现成的解决方案:①json ②probuff ③xml 二、理解发送接收函数 我们调用的所有发送/接收函数,根本就不是把数据发送到网络中!本质都是…...
【SQL】mysql常用命令
为方便查询,特整理MySQL常用命令。 约定:$后为Shell环境命令,>后为MySQL命令。 1 常用命令 第一步,连接数据库。 $ mysql -u root -p # 进入MySQL bin目录后执行,回车后输入密码连接。# 常用参数&…...
阿里云引领智算集群网络架构的新一轮变革
阿里云引领智算集群网络架构的新一轮变革 云布道师 11 月 8 日~ 10 日在江苏张家港召开的 CCF ChinaNet(即中国网络大会)上,众多院士、教授和业界技术领袖齐聚一堂,畅谈网络未来的发展方向,聚焦智算集群网络的创新变…...
几何合理的分片段感知的3D分子生成 FragGen - 评测
FragGen 来源于 2024 年 3 月 25 日 预印本的文章,文章题目是 Deep Geometry Handling and Fragment-wise Molecular 3D Graph Generation, 作者是 Odin Zhang,侯廷军,浙江大学药学院。FragGen 是一个基于分子片段的 3D 分子生成模…...
Python爬虫下载新闻,Flask展现新闻(2)
上篇讲了用Python从新闻网站上下载新闻,本篇讲用Flask展现新闻。关于Flask安装网上好多教程,不赘述。下面主要讲 HTML-Flask-数据 的关系。 简洁版 如图,页面简单,主要显示新闻标题。 分页,使用最简单的分页技术&…...
监控易监测对象及指标之:全面监控华为FusionInsight服务
随着大数据技术的广泛应用,华为FusionInsight以其卓越的性能和稳定性,成为了众多企业处理和分析海量数据的首选平台。然而,为了确保FusionInsight服务的持续稳定运行,对其进行全面监控至关重要。本文基于监控易工具,对…...
SQL面试题——蚂蚁SQL面试题 会话分组问题
会话分组问题 这里的分组不是简单的分组,而是会话的分组。 比如说,进入一个网站以后,可以连续的点击很多个页面,后台会记录用户的行为日志; 如果T日上午连续点击几个页面后退出了网站,直到第二天的下午才再次进入网站,单单从时间线上来看,昨天退出的那条日志跟今天进…...
nfs服务器--RHCE
一,简介 NFS(Network File System,网络文件系统)是FreeBSD支持的文件系统中的一种,它允许网络中的计 算机(不同的计算机、不同的操作系统)之间通过TCP/IP网络共享资源,主要在unix系…...
React--》如何高效管理前端环境变量:开发与生产环境配置详解
在前端开发中,如何让项目在不同环境下表现得更为灵活与高效,是每个开发者必须面对的挑战,从开发阶段的调试到生产环境的优化,环境变量配置无疑是其中的关键。 env配置文件:通常用于管理项目的环境变量,环境…...
Javascript高级—函数柯西化
函数柯西化(经典面试题) // 实现一个add方法,使计算结果能够满足如下预期: add(1)(2)(3) 6; add(1, 2, 3)(4) 10; add(1)(2)(3)(4)(5) 15;function add() {// 第一次执行时,定义一个数组专门用来存储所有的参数var…...
Sql进阶:字段中包含CSV,如何通过Sql解析CSV成多行多列?
Sql进阶 一、问题描述二、解决思路<一>、拆成多行<二>、拆成多列 三、代码实现 一、问题描述 Oracle数据库中某个字段value是CLOB类型,存的是csv格式的数据,如下所示 classnovalue1name,age,sex,… ‘李世民’,20,‘M’,…’ ‘李治’,18,‘M’,… ‘武则天’,16…...
linux之调度管理(5)-实时调度器
一、概述 在Linux内核中,实时进程总是比普通进程的优先级要高,实时进程的调度是由Real Time Scheduler(RT调度器)来管理,而普通进程由CFS调度器来管理。 实时进程支持的调度策略为:SCHED_FIFO和SCHED_RR。 SCHED_FIFOÿ…...
mybatis-plus: mapper-locations: “classpath*:/mapper/**/*.xml“配置!!!解释
和mybatis一样的道理!!!!如果不指定这个配置,通常要求 XML 映射文件和 Mapper 接口的包名和结构相同!!!! 如果没有配置 mapper-locations,通常文件结构应遵循…...
nacos-operator在k8s集群上部署nacos-server2.4.3版本踩坑实录
文章目录 操作步骤1. 拉取仓库代码2. 安装nacos-operator3. 安装nacos-server 坑点一坑点二nacos-ui页面访问同一集群环境下微服务连接nacos地址配置待办参考文档 操作步骤 1. 拉取仓库代码 (这一步主要用到代码中的相关yml文件,稍加修改用于部署容器&…...
面试篇-项目管理
⼀、构建管理 项目为什么选择Maven构建? 选择Maven进行项目构建有以下几个主要原因: 1. 依赖管理:Maven 提供了强大的依赖管理功能,可以自动下载项目所需的第三方库和依赖,并且可以管理这些依赖的版本、范围等信息。这简化了项…...
数仓建设之Oracle常见语法学习
1. 字符串截取 select substr(AAA-BBB, 1, instr(AAA-BBB, -, -1) - 1) 值 from dual; --AAA select substr(AAA-BBB, instr(AAA-BBB, -, -1) 1) 值 from dual; --BBB2. 帆软报表有参数SQL select a.agency_code, a.agency_name, a.agency_typefrom dw.dim_ta_subred_agency…...
物联网智能技术的深入探讨与案例分析
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
python语言基础-5 进阶语法-5.2 装饰器-5.2.2 简单装饰器
声明:本内容非盈利性质,也不支持任何组织或个人将其用作盈利用途。本内容来源于参考书或网站,会尽量附上原文链接,并鼓励大家看原文。侵删。 5.2.2 简单装饰器 装饰器的形式就是一个闭包,下面是一个简单的定义并使用…...
TransFormer--解码器:带掩码的多头注意力层
TransFormer--解码器:带掩码的多头注意力层 以英法翻译任务为例,假设训练数据集样本如下表所示。 原句目标翻译I am goodJe vais bienGood morningBonjourThank you very muchMerci beaucoup 上表所示的数据集由两部分组成:原句和目标句。在…...
【ArcGIS微课1000例】0130:图层组详解与使用
文章目录 一、图层组概述二、创建图层组三、在图层组中管理图层四、对话框中图层组的列表一、图层组概述 图层组包含其他图层。图层组有助于对地图中相关类型的图层进行组织,并且可用于定义高级绘制选项。例如,假设在地图上有两个图层分别用于表示铁路和高速公路。您可将这些…...
Linux中配置ntp服务
NTP:是Network Time Protocol的缩写又 称网络时间协议,是用来使计算机时间同步化的一种协议,用来同步网络中各主机的时 间,在linux系统中早期使用ntp来实现,后来使用chrony来实现。Chrony 应用本身已经有 几年了&#…...
微服务day10-Redis面试篇
Redis主从 搭建主从集群 建立集群时主节点会生成同一的replicationID,交给各个从节点。 集群中的缓冲区是一个环型数组,即若从节点宕机时间过长,可能导致命令被覆盖。 主从集群优化 哨兵原理 哨兵是一个集群来确保哨兵不出现问题。 服务状态监控 选举…...
STL序列式容器之list
相较于vector的连续性空间,list相对比较复杂;list内部使用了双向环形链表的方式对数据进行存储;list在增加元素时,采用了精准的方式分配一片空间对数据及附加指针等信息进行存储; list节点定义如下 template<clas…...
docker:基于Dockerfile镜像制作完整案例
目录 摘要目录结构介绍起始目录package目录target目录sh目录init.sh脚本start.sh脚本stop.sh脚本restart.sh脚本 config目录 步骤1、编写dockerfilescript.sh脚本 2、构件镜像查看镜像 3、保存镜像到本地服务器4、复制镜像文件到指定目录,并执行init.sh脚本5、查看挂…...
微信小程序自定义顶部导航栏(适配各种机型)
效果图 1.pages.js,需要自定义导航栏的页面设置"navigationStyle": "custom" 2.App.vue,获取设备高度及胶囊位置 onLaunch: function () {// 系统信息const systemInfo uni.getSystemInfoSync()// 胶囊按钮位置信息const menuButtonInfo uni.…...
sslSocketFactory not supported on JDK 9+
clientBuilder.sslSocketFactory(SSLSocketFactory) not supported on JDK 9 at okhttp3.internal.platform.Jdk9Platform.trustManager(Jdk9Platform.kt:61) at okhttp3.OkHttpClient$Builder.sslSocketFactory(OkHttpClient.kt:751) at 1.升版本4.9.3以上 2、加个函数获取X…...
[Codesys]常用功能块应用分享-BMOV功能块功能介绍及其使用实例说明
官方说明 功能说明 参数 类型 功能 pbyDataSrcPOINTER TO BYTE指向源数组指针uiSizeUINT要移动数据的BYTE数pbyDataDesPOINTER TO BYTE指向目标数组指针 实例应用-ST IF SYSTEM_CLOCK.AlwaysTrue THENCASE iAutoState OF0: //读写完成信号在下次读写信号的上升沿或复位信号…...
温州做网站哪家公司好/seo流量
一、光盘挂载镜像配置yum源1、挂载光盘镜像mount /dev/cdrom /media #将光盘系统文件挂载到 /media文件夹下2、配置光盘yum源 repo配置文件cd /etc/yum.repo.d #切换到yum配置文件目录mkdir repos_bak #创建repos配置文件备份文件夹mv *.repo repos_bak #将…...
中山市建设局网站/如何进行网站性能优化?
我不是Facebook也不是Pinterest 粉丝,所以当朋友Orli发给我 Pinvolve的链接时,我很惊奇,它把 Facebook的动态更新以Pinterest式风格呈现出来,我很喜欢这个。在我眼里它提供了更好地方式来浏览世界上最大的社交网络,即使…...
wordpress调用图片/搜狗官方网站
什么是Service Locator 模式? 服务定位模式(Service Locator Pattern)是一种软件开发中的设计模式,通过应用强大的抽象层,可对涉及尝试获取一个服务的过程进行封装。该模式使用一个称为"Service Locator"的中…...
建设网站的技术手段/哈尔滨网络推广优化
在子类继承父类中,一般有一行super的语句,需要记住三种使用方法: 1、super.变量/对象名; 使用这种方法可以直接访问父类中的变量或对象,进行修改赋值等操作 2、super.方法名(); 直接访问并调用父类中的…...
厦门专业建站系统制作公司/北京做网站推广
本节书摘来华章计算机《电路分析导论(原书第12版)》一书中的第2章 ,第2.4节,(美) Robert L.Boylestad 著 陈希有 张新燕 李冠林 等译更多章节内容可以访问云栖社区“华章计算机”公众号查看。 2.4 电流…...
如何设公司产品购物网站/网站建设公司地址在哪
2019独角兽企业重金招聘Python工程师标准>>> 官方地址:http://jquery.malsup.com/block/ 需要使用的js 引入jquery包 引入插件包JQuery BlockUI(官方下载相应的js) demo 1.直接弹出提示话语 <!DOCTYPE html PUBLIC "-//W…...