Go implémentation de PHP Laravel ORM, conforme à la documentation officielle de laravel https://laravel.com/docs/10.x/queries.
Il est divisé en style Go (utilisation de la liaison de structure struct) et en style PHP (utilisation de la structure de carte).
Pour une utilisation de style PHP, vous pouvez utiliser la documentation du générateur de requêtes Laravel comme référence et essayer d'obtenir une restauration 1:1.
Il est encore en phase bêta, veuillez l'utiliser avec prudence. Puisqu'il n'est pas étiqueté, il ne peut être introduit qu'en utilisant le mod go.
# go.mod
require github.com/gohouse/gorose/v3 master
aller à l'utilisation du style
package main
import (
gorose "github.com/gohouse/gorose/v3"
// 引入mysql驱动
_ "github.com/go-sql-driver/mysql"
)
type User struct {
Id int64 `db:"id,pk"` // 这里的 pk 是指主键
Name string `db:"name"`
Email string `db:"email"`
// 定义表名字,等同于 func (User) TableName() string {return "users"}, 二选一即可
// TableName string `db:"users" json:"-"`
}
func ( User ) TableName () string {
return "users"
}
var rose = gorose . Open ( "mysql" , "root:123456@tcp(localhost:3306)/test?charset=utf8mb4&parseTime=true" )
func db () * gorose. Database {
return rose . NewDatabase ()
}
func main () {
// select id,name,email from users limit 1;
var user User
db (). To ( & user )
// insert into users (name,email) values ("test","[email protected]");
var user = User { Name : "test" , Email : "[email protected]" }}
db (). Insert ( & user )
// update users set name="test2" where id=1;
var user = User { Id : 1 , Name : "test2" }
db (). Update ( & user )
// delete from users where id=1;
var user = User { Id : 1 }
db (). Delete ( & user )
}
L'utilisation du style PHP et la requête d'utilisation du style Go sont les suivantes : comparaison SQL :
select id,name,email from users where id = 1 and name = " test "
// php 风格写法
user , err := db (). Table ( "users" ).
Select ( "id" , "name" , "email" ).
Where ( "id" , "=" , 1 ). Where ( "name" , "test" ).
First ()
// go 风格写法
var user = User { Id : 1 , Name : "test" }
err := db (). To ( & user )
Les deux utilisations ci-dessus ont les mêmes résultats. On peut voir qu'à l'exception de la différence de liaison au modèle de table, d'autres méthodes sont courantes.
La connexion à une seule base de données peut être utilisée directement de la même manière que l'interface officielle
var rose = gorose . Open ( "mysql" , "root:123456@tcp(localhost:3306)/test?charset=utf8mb4&parseTime=true" )
Peut également être utilisé
var conf1 = gorose. Config {
Driver : "mysql" ,
DSN : "root:123456@tcp(localhost:3306)/test?charset=utf8mb4&parseTime=true" ,
Prefix : "tb_" ,
Weight : 0 ,
MaxIdleConns : 0 ,
MaxOpenConns : 0 ,
ConnMaxLifetime : 0 ,
ConnMaxIdleTime : 0 ,
}
var rose = gorose . Open ( conf )
Vous pouvez également utiliser un cluster de séparation en lecture-écriture pour forcer automatiquement la lecture des données à partir de la base de données en écriture au sein d'une transaction.
var rose = gorose . Open (
gorose. ConfigCluster {
WriteConf : []gorose. Config {
conf1 ,
conf2 ,
},
ReadConf : []gorose. Config {
conf3 ,
conf4 ,
}
},
)
Actuellement, la prise en charge des 5 bases de données ci-dessus a été implémentée. Pour les bases de données générales, il vous suffit d'ajouter des interfaces gorose/driver/dialect.IDialect
pour les bases de données non universelles, tant que l'interface gorose/driver.IDriver est implémentée. n'importe quelle base de données peut être prise en charge en théorie. Y compris redis, mongo, etc., toutes les opérations de la chaîne ORM peuvent être implémentées via cette interface. Toutes les opérations de la chaîne ORM sont dans gorose/builder.Context
et les données originales peuvent être obtenues directement.
// 全自动事务, 有错误会自动回滚, 无错误会自动提交
// Transaction 方法可以接收多个操作, 同用一个 tx, 方便在不同方法内处理同一个事务
db (). Transaction ( func ( tx gorose. TxHandler ) error {
tx (). Insert ( & user )
tx (). Update ( & user )
tx (). To ( & user )
})
// 手动事务
tx = db (). Begin ()
tx (). Insert ( & user )
tx (). Update ( & user )
tx (). To ( & user )
tx (). Rollback ()
tx (). Commit ()
// 全自动嵌套事务
db (). Transaction ( func ( tx gorose. TxHandler ) error {
tx (). Insert ( & user )
...
// 自动子事务
tx (). Transaction ( func ( tx2 gorose. TxHandler ) error {
tx2 (). Update ( & user )
...
}
}
// 手动嵌套事务
var tx = db (). Begin ()
// 自动子事务
tx (). Begin () // 自动 savepoint 子事务
...
tx (). Rollback () // 自动回滚到上一个 savepoint
...
// 手动子事务
tx (). SavePoint ( "savepoint1" ) // 手动 savepoint 到 savepoint1(自定义名字)
...
tx (). RollbackTo ( "savepoint1" ) // 手动回滚到自定义的 savepoint
tx (). Commit ()
Lors de l'insertion et de la mise à jour de données, si vous utilisez le modèle struct comme objet de données, la valeur de type zéro est ignorée par défaut. Si vous souhaitez forcer l'écriture, vous pouvez transmettre les champs dont l'écriture doit être forcée à partir du. deuxième paramètre, tel que :
var user = User { Id : 1 , Name : "test" }
// 这里不会对 sex 做任何操作,
//update user set name="test" where id=1
db (). Update ( & user )
// 这里会强制将sex更改为0
//update user set name="test", sex=0 where id=1
db (). Update ( & user , "sex" )
// 等同于
db (). Table ( & user ). Where ( "id" , 1 ). Update ( map [ string ] any { "name" : "test" , "sex" : 0 }))
S'il n'y a pas de condition Where, le champ avec pk spécifié dans la balise sera automatiquement ajouté comme condition, par exemple : db:"id,pk"
. Parce que pk est spécifié, si la valeur de id n'est pas 0, l'identifiant. sera mis à jour en tant que condition de clé primaire.
Mise à jour de la référence
var user = User { Id : 1 }
db (). Delete ( & user )
// 等同于
db (). Table ( & user ). Where ( "id" , 1 ). Delete ()
// 要加上字段0值条件,只需要传入第二个字段,如:
// delete from users where id=1 and sex=0 and name=""
db (). Delete ( & user , "sex" , "name" )
db (). Table ( User {})
db (). Table ( "users" )
db (). Table ( User {}, "u" )
db (). Table ( "users" , "u" )
sub := db (). Table ( "users" ). Select ( "id" , "name" )
db (). Table ( sub ). Where ( "id" , ">" , 1 ). Get ()
type UserInfo struct {
UserId int64 `db:"user_id"`
TableName string `db:"user_info"`
}
db (). Table ( "users" ). Join ( UserInfo {}, "user.id" , "=" , "user_info.user_id" ). Get ()
// select * from users a inner join user_info b on a.id=b.user_id
db (). Table ( "users" , "u" ). Join ( gorose . As ( UserInfo {}, "b" ), "u.id" , "=" , "b.user_id" ). Get ()
// 等同于
db (). Table ( User {}, "u" ). Join ( gorose . As ( "user_info" , "b" ), "u.id" , "=" , "b.user_id" ). Get ()
Dans gorose.As(UserInfo{}, "b")
, user_info
prend l'alias b
db (). Table ( "users" ). Join ( UserInfo {}, func ( wh builder. IJoinOn ) {
wh . On ( "a.id" , "b.user_id" ). OrOn ( "a.sex" , "b.sex" )
}). Get ()
// 等同于
db (). Table ( "users" ). JoinOn ( UserInfo {}, func ( wh builder. IJoinOn ) {
wh . On ( "a.id" , "b.user_id" ). OrOn ( "a.sex" , "b.sex" )
}). Get ()
Lorsque le deuxième paramètre de Join
est builder.IJoinOn
, cela équivaut à JoinOn
(le deuxième paramètre a un rappel de type fort, ce qui est pratique pour les invites rapides de l'IDE)
// where id in (select user_id from user_info)
sub := db (). Table ( "user_info" ). Select ( "user_id" )
db (). Table ( User {}). Where ( "id" , "in" , sub ). Get ()
// where id in (select user_id from user_info)
db (). Table ( User {}). WhereSub ( "id" , "in" , func ( tx * builder. Context ) {
tx . Table ( "user_info" ). Select ( "user_id" )
}). Get ()
// where id in (select user_id from user_info)
sub := db (). Table ( "user_info" ). Select ( "user_id" )
db (). Table ( User {}). WhereBuilder ( "id" , "in" , sub ). Get ()
Les trois utilisations ci-dessus sont équivalentes
// where id>1 and (sex=1 or sex=2)
db (). Table ( User {}). Where ( "id" , ">" , 1 ). Where ( func ( wh builder. IWhere ) {
wh . Where ( "sex" , 1 ). OrWhere ( "sex" , 2 )
})
Où ici équivaut à WhereNested
// where id>1 and (sex=1 or sex=2)
db (). Table ( User {}). Where ( "id" , ">" , 1 ). WhereNested ( func ( wh builder. IWhere ) {
wh . Where ( "sex" , 1 ). OrWhere ( "sex" , 2 )
})
Les deux utilisations ci-dessus sont équivalentes
Les sous-requêtes peuvent être utilisées dans Table, Where et Join.
sub := db (). Table ( "user" ). Where (). OrWhere ()
sub2 := db (). Table ( "address" ). Select ( "user_id" ). Where (). OrWhere ()
sub3 := db (). Table ( "user_info" ). Select ( "user_id" ). Where (). OrWhere ()
Utilisé dans le tableau, où, rejoindre
db ().
Table ( sub , "a" ).
Join ( gorose . As ( sub2 , "b" ), "a.id" , "=" , "b.user_id" )).
WhereIn ( "a.id" , sub3 ).
Get ()
Utilisé dans Union, UnionAll
db ().
Table ( "users" ).
Union ( sub ).
Get ()
var sub2222 = db (). Table ( "user" ). Where (). OrWhere ()
var to [] User
db ().
Table ( "users" ).
UnionAll ( sub , sub2222 ).
To ( & to )
Renvoie deux colonnes de données dans une carte, la première colonne est la valeur et la deuxième colonne est la clé
// select id,name from users
db (). Table ( "users" ). Pluck ( "name" , "id" )
// 返回 map[<id>]<name>, 实际得到 map[int64]string{1: "张三", 2: "李四"}
Renvoie une colonne de données dans un tableau
// select id,name from users
db (). Table ( "users" ). List ( "id" )
// 返回 []<id>, 实际得到 []int64{1,2,3}
Utilisez le champ de structure comme champ de sélection. Utilisez la valeur du champ de structure comme condition Where. Le résultat de la requête est lié à la structure, prenant en charge un ou plusieurs champs.
// 查询一条数据
var user User
db (). To ( & user )
// 查询条件,一条数据
// select id,name,email from users where id=1
var user = User { Id : 1 }
db (). To ( & user )
// 查询多条数据
var users [] User
db (). To ( & users )
// 查询条件,多条数据
var users [] User
db (). Where ( "id" , ">" , 1 ). To ( & users )
Il est uniquement utilisé comme champ de structure de liaison pour les résultats de requête. Il n'est pas utilisé comme champs et conditions de requête. Il est souvent utilisé pour la liaison de requête de jointure ou de champ spécifié manuellement.
type Result struct {
Id int64 `db:"id"`
Aname string `db:"aname"`
Bname string `db:"bname"`
}
var res Result
// select a.id, a.name aname, b.name bname from a inner join b on a.id=b.aid where a.id>1
db (). Table ( "a" ). Join ( "b" , "a.id" , "b.aid" ). Select ( "a.id" , "a.name aname" , "b.name bname" ). Where ( "a.id" , ">" , 1 ). Bind ( & res )
Le nom d'affichage du champ de requête doit être le même que le nom de la balise de champ (db) de la structure, sinon le nombre de champs qui ne seront pas attribués peut être différent.
var list [] int
db (). Table ( "users" ). ListTo ( "age" , & list )
var pluck map [ int64 ] string
db (). Table ( "users" ). PluckTo ( "name" , "id" , & pluck )
var value int
db (). Table ( "users" ). ValueTo ( "age" , & value )
var sum int
db (). Table ( "users" ). SumTo ( "age" , & sum )
var max int
db (). Table ( "users" ). MaxTo ( "age" , & max )
var min int
db (). Table ( "users" ). MinTo ( "age" , & min )
Par défaut, le niveau de débogage du slog de la bibliothèque officielle est utilisé. Si vous ne souhaitez pas afficher le journal SQL, il vous suffit de définir le niveau du slog au-dessus du débogage, par exemple : Info, Warn, Error.
type User struct {
Id int64 `db:"id,pk"`
Sex * int8 `db:"sex"` // 使用指针可以绑定 null 值
Age sql. NullInt64 `db:"age"` // 使用sql.NullInt64 可以绑定 null 值
}
affectation du pointeur
var sex = int8 ( 1 )
var user = User { Id : 1 , Sex : & sex }
// 或者,快捷用法
var user = User { Id : 1 , Sex : gorose . Ptr ( int8 ( 1 ))}
affectation sql.Null*
var age = sql. NullInt64 { Int64 : 18 , Valid : true }
utilisation de sql.Null*
if age . Valid {
fmt . Println ( age . Int64 )
}
On peut voir qu'il est encore un peu difficile de gérer null. Par conséquent, il est recommandé de ne pas autoriser null lors de la conception du tableau. Les valeurs par défaut sont données, et la plupart des valeurs par défaut peuvent simplement correspondre à celles-ci. tapez la valeur zéro de go.
Tableau
Sélectionner
SélectionnerBrut
AjouterSélectionner
Rejoindre
GroupePar
Ayant
AvoirBrut
OuAvoir
OuAvoirCru
Commander par
Limite
Compenser
Où
OùBrut
OuOù
OuOùRaw
OùEntre
OuOùEntre
OùPasEntre
OuOùPasEntre
Où
OuOùDans
OùPasDans
OuOùPasDans
OùNull
OuOùNull
OùNotNull
OuOùNotNull
Où comme
OuOùLike
OùPasLike
OuOùPasComme
Où existe-t-il
Où n'existe pas
Où pas
Obtenir
D'abord
Trouver
Insérer
Mise à jour
Supprimer
Max.
Min.
Somme
Moy.
Compter
InsérerObtenirId
Insérer
InsérerOuIgnorer
Existe
N'existe pas
Cueillir
Liste
Valeur
Paginer
Incrément
Décrémenter
IncrémentChacun
DécrémenterChaque
Tronquer
Union
UnionTous
Verrouillage partagé
VerrouillerPourMiseàJour
Remplacer
Page
DernierSql
OùBuilder
OuOùBuilder
OùSub
OuOùSub
OùNesté
OuOùNesté
À
Lier
ListeÀ
PlumerÀ
ValeurÀ
SommeÀ
MaxTo
UnionÀ
UnionTousÀ