Go-Implementierung von PHP Laravel ORM, im Einklang mit der offiziellen Laravel-Dokumentation https://laravel.com/docs/10.x/queries.
Es ist in den Go-Stil (Verwendung der Strukturstrukturbindung) und den PHP-Stil (Verwendung der Kartenstruktur) unterteilt.
Für die Verwendung im PHP-Stil können Sie die Dokumentation des Laravel Query Builder als Referenz verwenden und versuchen, eine 1:1-Wiederherstellung zu erreichen.
Es befindet sich noch im Beta-Stadium. Bitte verwenden Sie es mit Vorsicht, da es nicht mit Tags versehen ist und nur mit dem Go-Mod eingeführt werden kann.
# go.mod
require github.com/gohouse/gorose/v3 master
Go-Style-Nutzung
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 )
}
Die Verwendung des PHP-Stils und die Abfrage der Verwendung des Go-Stils lauten wie folgt im SQL-Vergleich:
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 )
Die beiden oben genannten Verwendungen führen zu den gleichen Ergebnissen. Es ist ersichtlich, dass mit Ausnahme der unterschiedlichen Bindung an das Tabellenmodell andere Methoden üblich sind.
Eine einzelne Datenbankverbindung kann direkt wie die offizielle Schnittstelle verwendet werden
var rose = gorose . Open ( "mysql" , "root:123456@tcp(localhost:3306)/test?charset=utf8mb4&parseTime=true" )
Kann auch verwendet werden
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 )
Oder verwenden Sie einen Cluster zur Lese-Schreib-Trennung, um innerhalb einer Transaktion automatisch das Lesen von Daten aus der Schreibdatenbank zu erzwingen.
var rose = gorose . Open (
gorose. ConfigCluster {
WriteConf : []gorose. Config {
conf1 ,
conf2 ,
},
ReadConf : []gorose. Config {
conf3 ,
conf4 ,
}
},
)
Derzeit ist die Unterstützung für die oben genannten 5 Datenbanken implementiert. Für nicht-universelle Datenbanken müssen Sie nur weitere gorose/driver/dialect.IDialect
Schnittstellen hinzufügen. Theoretisch kann jede Datenbank unterstützt werden, einschließlich Redis, Mongo usw. Alle ORM-Kettenoperationen können über diese gorose/builder.Context
implementiert werden und die Originaldaten können direkt abgerufen werden.
// 全自动事务, 有错误会自动回滚, 无错误会自动提交
// 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 ()
Wenn Sie beim Einfügen und Aktualisieren von Daten das Strukturmodell als Datenobjekt verwenden, wird der Wert vom Typ Null standardmäßig ignoriert. Wenn Sie das Schreiben erzwingen möchten, können Sie die Felder, deren Schreiben erzwungen werden muss, beginnend mit übergeben zweiter Parameter, wie zum Beispiel:
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 }))
Wenn keine Where-Bedingung vorhanden ist, wird das Feld mit dem im Tag angegebenen pk automatisch als Bedingung hinzugefügt, z. B.: db:"id,pk"
Da pk angegeben ist, ist die ID ungleich 0 wird als Primärschlüsselbedingung aktualisiert.
Referenzaktualisierung
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 ()
In gorose.As(UserInfo{}, "b")
nimmt user_info
den 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 ()
Wenn der zweite Parameter von Join
builder.IJoinOn
ist, entspricht dies JoinOn
(der zweite Parameter verfügt über eine starke Typerinnerung, was für IDE-Schnellaufforderungen praktisch ist).
// 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 ()
Die oben genannten drei Verwendungen sind gleichwertig
// 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 )
})
Where Here entspricht 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 )
})
Die beiden oben genannten Verwendungen sind gleichwertig
Unterabfragen können in Table, Where und Join verwendet werden.
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 ()
Wird in Tabelle, Wo, Beitreten verwendet
db ().
Table ( sub , "a" ).
Join ( gorose . As ( sub2 , "b" ), "a.id" , "=" , "b.user_id" )).
WhereIn ( "a.id" , sub3 ).
Get ()
Wird in Union, UnionAll verwendet
db ().
Table ( "users" ).
Union ( sub ).
Get ()
var sub2222 = db (). Table ( "user" ). Where (). OrWhere ()
var to [] User
db ().
Table ( "users" ).
UnionAll ( sub , sub2222 ).
To ( & to )
Geben Sie zwei Datenspalten in eine Karte zurück, die erste Spalte ist der Wert und die zweite Spalte ist der Schlüssel
// select id,name from users
db (). Table ( "users" ). Pluck ( "name" , "id" )
// 返回 map[<id>]<name>, 实际得到 map[int64]string{1: "张三", 2: "李四"}
Gibt eine Datenspalte in ein Array zurück
// select id,name from users
db (). Table ( "users" ). List ( "id" )
// 返回 []<id>, 实际得到 []int64{1,2,3}
Verwenden Sie das Strukturfeld als Auswahlfeld. Verwenden Sie den Strukturfeldwert als Where-Bedingung. Das Abfrageergebnis ist an die Struktur gebunden und unterstützt ein oder mehrere Felder.
// 查询一条数据
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 )
Es wird nur als Bindungsstrukturfeld für Abfrageergebnisse verwendet. Es wird häufig für Verknüpfungen oder manuell angegebene Feldabfragebindungen verwendet.
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 )
Der Anzeigename des Abfragefelds muss mit dem Feld-Tag-Namen (DB) der Struktur übereinstimmen, andernfalls kann die Anzahl der Felder, die nicht zugewiesen werden, unterschiedlich sein.
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 )
Standardmäßig wird die Slog-Debug-Ebene der offiziellen Bibliothek verwendet. Wenn Sie das SQL-Protokoll nicht anzeigen möchten, müssen Sie die Slog-Ebene nur auf über Debug setzen, z. B.: Info, Warn, Fehler
type User struct {
Id int64 `db:"id,pk"`
Sex * int8 `db:"sex"` // 使用指针可以绑定 null 值
Age sql. NullInt64 `db:"age"` // 使用sql.NullInt64 可以绑定 null 值
}
Zeigerzuweisung
var sex = int8 ( 1 )
var user = User { Id : 1 , Sex : & sex }
// 或者,快捷用法
var user = User { Id : 1 , Sex : gorose . Ptr ( int8 ( 1 ))}
sql.Null*-Zuweisung
var age = sql. NullInt64 { Int64 : 18 , Valid : true }
sql.Null* verwenden
if age . Valid {
fmt . Println ( age . Int64 )
}
Es ist ersichtlich, dass der Umgang mit Null immer noch etwas mühsam ist. Daher wird empfohlen, beim Entwerfen der Tabelle keine Standardwerte zuzulassen, und die meisten Standardwerte können einfach dem entsprechen Geben Sie den Nullwert von go ein.
Tisch
Wählen
Wählen Sie Raw aus
AddSelect
Verbinden
GroupBy
Haben
Raw haben
OderHaben
OderHavingRaw
OrderBy
Limit
Versatz
Wo
WhereRaw
OderWo
OderWhereRaw
WhereBetween
OderWhereBetween
WhereNotBetween
OderWhereNotBetween
Worin
OderWhereIn
WhereNotIn
OderWhereNotIn
WhereNull
OrWhereNull
WhereNotNull
OrWhereNotNull
WhereLike
OderWoGefällt mir
WhereNotLike
OderWhereNotLike
WhereExists
WhereNotExists
Wo nicht
Erhalten
Erste
Finden
Einfügen
Aktualisieren
Löschen
Max
Min
Summe
Durchschn
Zählen
InsertGetId
Upsert
EinfügenOrIgnorieren
Existiert
Existiert nicht
Zupfen
Liste
Wert
Paginieren
Inkrement
Dekrementieren
Inkrementieren
Dekrementieren
Kürzen
Union
UnionAll
SharedLock
LockForUpdate
Ersetzen
Seite
LastSql
WhereBuilder
OderWhereBuilder
WhereSub
OderWoSub
Wo verschachtelt
OderWhereNested
Zu
Binden
ListTo
ZupfenZu
ValueTo
SumTo
MaxTo
UnionTo
UnionAllTo