PHP Laravel ORM の Go 実装。laravel 公式ドキュメント https://laravel.com/docs/10.x/queries と一致します。
Go スタイル (構造体バインディングの使用) と PHP スタイル (マップ構造の使用) に分かれています。
PHP スタイルの使用方法については、laravel クエリ ビルダーのドキュメントを参考にして、1:1 復元を実現してみてください。
まだベータ版ですので、タグが付いていないためgo modでしか導入できませんのでご注意ください。
# go.mod
require github.com/gohouse/gorose/v3 master
go スタイルの使用法
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 )
}
PHP スタイルの使用法と Go スタイルの使用法クエリの 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 )
上記 2 つの使用法は同じ結果になりますが、テーブル モデルへのバインドの違いを除けば、他の方法は共通であることがわかります。
単一のデータベース接続は、公式インターフェイスと同じ方法で直接使用できます。
var rose = gorose . Open ( "mysql" , "root:123456@tcp(localhost:3306)/test?charset=utf8mb4&parseTime=true" )
も使用できます
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 )
または、読み取り/書き込み分離クラスターを使用して、トランザクション内で書き込みデータベースからのデータの読み取りを自動的に強制します。
var rose = gorose . Open (
gorose. ConfigCluster {
WriteConf : []gorose. Config {
conf1 ,
conf2 ,
},
ReadConf : []gorose. Config {
conf3 ,
conf4 ,
}
},
)
現在、上記の 5 つのデータベースのサポートが実装されています。一般的なデータベースの場合は、gorose/driver.IDriver インターフェイスが実装されている限り、 gorose/driver/dialect.IDialect
インターフェイスを追加するだけです。理論的には、redis、mongo などのあらゆるデータベースをサポートでき、すべての ORM チェーン操作はgorose/builder.Context
で実装でき、元のデータを直接取得できます。
// 全自动事务, 有错误会自动回滚, 无错误会自动提交
// 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 ()
データの挿入および更新時に、構造体モデルをデータ オブジェクトとして使用する場合、タイプ 0 の値はデフォルトで無視されます。強制的に書き込みを行う場合は、強制的に書き込む必要があるフィールドを先頭から渡すことができます。 2 番目のパラメータ:
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 }))
where 条件がない場合は、 db:"id,pk"
のように、タグに pk が指定されているフィールドが条件として自動的に追加されます。pk が指定されているため、id の値が 0 でない場合は、id が返されます。が主キー条件として更新されます。
リファレンス更新
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 ()
gorose.As(UserInfo{}, "b")
では、 user_info
エイリアス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 ()
Join
の 2 番目のパラメーターがbuilder.IJoinOn
の場合、これはJoinOn
使用法と同等です (2 番目のパラメーターには強力な型リマインダーがあり、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 ()
上記 3 つの使用法は同等です
// 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 は 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 )
})
上記 2 つの用法は同等です
サブクエリは、Table、Where、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 ()
Table、Where、Join で使用
db ().
Table ( sub , "a" ).
Join ( gorose . As ( sub2 , "b" ), "a.id" , "=" , "b.user_id" )).
WhereIn ( "a.id" , sub3 ).
Get ()
ユニオン、ユニオンオールで使用
db ().
Table ( "users" ).
Union ( sub ).
Get ()
var sub2222 = db (). Table ( "user" ). Where (). OrWhere ()
var to [] User
db ().
Table ( "users" ).
UnionAll ( sub , sub2222 ).
To ( & to )
2 つの列のデータをマップに返します。最初の列は値、2 番目の列はキーです。
// select id,name from users
db (). Table ( "users" ). Pluck ( "name" , "id" )
// 返回 map[<id>]<name>, 实际得到 map[int64]string{1: "张三", 2: "李四"}
データの列を配列に返します
// select id,name from users
db (). Table ( "users" ). List ( "id" )
// 返回 []<id>, 实际得到 []int64{1,2,3}
構造体フィールドを選択フィールドとして使用します。構造体フィールドの値を Where 条件として使用します。クエリ結果は構造体にバインドされ、1 つ以上のフィールドをサポートします。
// 查询一条数据
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 )
これは、クエリ結果のバインディング構造フィールドとしてのみ使用され、結合または手動で指定されたフィールド クエリ バインディングには使用されません。
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 )
クエリ フィールドの表示名は、構造のフィールド タグ (db) 名と同じである必要があります。そうでない場合、割り当てられないフィールドの数が異なる場合があります。
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 )
デフォルトでは、公式ライブラリの slog デバッグ レベルが使用されます。SQL ログを表示したくない場合は、slog レベルをデバッグ以上 (Info、Warn、Error など) に設定するだけです。
type User struct {
Id int64 `db:"id,pk"`
Sex * int8 `db:"sex"` // 使用指针可以绑定 null 值
Age sql. NullInt64 `db:"age"` // 使用sql.NullInt64 可以绑定 null 值
}
ポインタの割り当て
var sex = int8 ( 1 )
var user = User { Id : 1 , Sex : & sex }
// 或者,快捷用法
var user = User { Id : 1 , Sex : gorose . Ptr ( int8 ( 1 ))}
SQL.Null* 代入
var age = sql. NullInt64 { Int64 : 18 , Valid : true }
SQL.Null* の使用
if age . Valid {
fmt . Println ( age . Int64 )
}
null を扱うのはまだ少し面倒であることがわかります。そのため、テーブルを設計するときに null を許可しないことをお勧めします。デフォルト値のほとんどは、そのまま対応できます。 go の値としてゼロを入力します。
テーブル
選択
生を選択
追加選択
参加する
GroupBy
持っている
生を持つ
または持っている
または生を持っている
注文方法
限界
オフセット
どこ
どこで生
それともどこで
またはどこで生
どこの間
またはどこの間
間ではない場所
あるいは中間ではない場所
どこで
またはどこで
どこにないのか
それともどこではないのか
WhereNull
OrWhereNull
WhereNotNull
OrWhereNotNull
どこに似ていますか
またはどこに似ていますか
好きじゃないところ
またはそうでない場所
存在する場所
存在しない場所
どこにないのか
得る
初め
探す
入れる
アップデート
消去
マックス
分
和
平均
カウント
挿入GetId
アップサート
挿入または無視
存在する
存在しない
摘み取る
リスト
価値
ページ付け
インクリメント
デクリメント
各増分
それぞれをデクリメント
切り詰める
連合
ユニオンオール
共有ロック
LockForUpdate
交換する
ページ
最後のSQL
WhereBuilder
OrWhereビルダー
WhereSub
OrWhereSub
ネストされた場所
またはネストされた場所
に
バインド
リスト先
プラックトゥ
値の宛先
サムト
MaxTo
ユニオンへ
UnionAllTo