Implementasi PHP Laravel ORM, konsisten dengan dokumentasi resmi laravel https://laravel.com/docs/10.x/queries.
Ini dibagi menjadi gaya Go (penggunaan pengikatan struktur struktur) dan gaya PHP (penggunaan struktur peta).
Untuk penggunaan gaya PHP, Anda dapat menggunakan dokumentasi pembuat kueri laravel sebagai referensi, dan mencoba mencapai restorasi 1:1.
Ini masih dalam tahap beta, harap gunakan dengan hati-hati karena tidak diberi tag, ini hanya dapat diperkenalkan menggunakan go mod.
# go.mod
require github.com/gohouse/gorose/v3 master
pergi penggunaan gaya
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 )
}
Penggunaan gaya PHP dan kueri penggunaan gaya Go adalah sebagai berikut perbandingan 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 )
Kedua penggunaan di atas memiliki hasil yang sama. Terlihat bahwa kecuali perbedaan pengikatan pada model tabel, metode lain juga umum digunakan.
Koneksi database tunggal dapat digunakan secara langsung dengan cara yang sama seperti antarmuka resmi
var rose = gorose . Open ( "mysql" , "root:123456@tcp(localhost:3306)/test?charset=utf8mb4&parseTime=true" )
Bisa juga digunakan
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 )
Atau gunakan cluster pemisahan baca-tulis untuk secara otomatis memaksa data dibaca dari database tulis dalam suatu transaksi.
var rose = gorose . Open (
gorose. ConfigCluster {
WriteConf : []gorose. Config {
conf1 ,
conf2 ,
},
ReadConf : []gorose. Config {
conf3 ,
conf4 ,
}
},
)
Saat ini dukungan untuk 5 database di atas telah diterapkan. Untuk database umum, Anda hanya perlu menambahkan lebih banyak antarmuka gorose/driver/dialect.IDialect
. Untuk database non-universal, selama antarmuka gorose/driver.IDidrive diterapkan, database apa pun dapat didukung secara teori. Termasuk redis, mongo, dll., semua operasi rantai ORM dapat diimplementasikan melalui antarmuka ini. Semua operasi rantai ORM ada di gorose/builder.Context
, dan data asli dapat diperoleh secara langsung.
// 全自动事务, 有错误会自动回滚, 无错误会自动提交
// 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 ()
Saat memasukkan dan memperbarui data, jika Anda menggunakan model struct sebagai objek data, nilai tipe nol diabaikan secara default. Jika Anda ingin memaksakan penulisan, Anda dapat memasukkan kolom yang perlu dipaksa untuk ditulis mulai dari parameter kedua, seperti:
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 }))
Jika tidak ada kondisi dimana, field dengan pk yang ditentukan dalam tag akan secara otomatis ditambahkan sebagai kondisi, seperti: db:"id,pk"
. Karena pk ditentukan, jika nilai id bukan 0, maka id akan diperbarui sebagai kondisi kunci utama.
Pembaruan referensi
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 ()
Di gorose.As(UserInfo{}, "b")
, user_info
mengambil 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 ()
Jika parameter kedua dari Join
adalah builder.IJoinOn
, ini setara dengan penggunaan JoinOn
(parameter kedua memiliki pengingat tipe yang kuat, yang memudahkan untuk perintah cepat 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 ()
Ketiga penggunaan di atas setara
// 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 setara dengan 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 )
})
Dua penggunaan di atas setara
Subkueri dapat digunakan di Tabel, Dimana, dan Gabung.
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 ()
Digunakan di Tabel, Dimana, Gabung
db ().
Table ( sub , "a" ).
Join ( gorose . As ( sub2 , "b" ), "a.id" , "=" , "b.user_id" )).
WhereIn ( "a.id" , sub3 ).
Get ()
Digunakan di 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 )
Kembalikan dua kolom data ke dalam peta, kolom pertama adalah nilai dan kolom kedua adalah kunci
// select id,name from users
db (). Table ( "users" ). Pluck ( "name" , "id" )
// 返回 map[<id>]<name>, 实际得到 map[int64]string{1: "张三", 2: "李四"}
Mengembalikan kolom data ke dalam array
// select id,name from users
db (). Table ( "users" ). List ( "id" )
// 返回 []<id>, 实际得到 []int64{1,2,3}
Gunakan bidang struktur sebagai bidang pilihan. Gunakan nilai bidang struktur sebagai kondisi di mana. Hasil kueri terikat pada struktur, mendukung satu atau beberapa bidang.
// 查询一条数据
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 )
Ini hanya digunakan sebagai bidang struktur pengikatan untuk hasil kueri. Ini tidak digunakan sebagai bidang dan ketentuan kueri. Ini sering digunakan untuk pengikatan kueri bidang gabungan atau yang ditentukan secara manual.
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 )
Nama tampilan bidang kueri harus sama dengan nama struktur tag bidang (db), jika tidak, jumlah bidang yang tidak akan ditetapkan bisa berbeda.
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 )
Secara default, level slog debug dari perpustakaan resmi digunakan. Jika Anda tidak ingin menampilkan log sql, Anda hanya perlu mengatur level slog ke atas debug, seperti: Info, Warn, Error
type User struct {
Id int64 `db:"id,pk"`
Sex * int8 `db:"sex"` // 使用指针可以绑定 null 值
Age sql. NullInt64 `db:"age"` // 使用sql.NullInt64 可以绑定 null 值
}
tugas penunjuk
var sex = int8 ( 1 )
var user = User { Id : 1 , Sex : & sex }
// 或者,快捷用法
var user = User { Id : 1 , Sex : gorose . Ptr ( int8 ( 1 ))}
penugasan sql.Null*
var age = sql. NullInt64 { Int64 : 18 , Valid : true }
sql.Null* digunakan
if age . Valid {
fmt . Println ( age . Int64 )
}
Terlihat masih agak merepotkan untuk menangani null. Oleh karena itu, disarankan untuk tidak mengizinkan null saat mendesain tabel. Nilai default diberikan, dan sebagian besar nilai default hanya sesuai dengan ketik nilai nol go.
Meja
Memilih
Pilih Mentah
TambahkanPilih
Bergabung
GrupOleh
Memiliki
Memiliki Mentah
AtauMemiliki
AtauMemilikiMentah
Dipesan Oleh
Membatasi
Mengimbangi
Di mana
Dimana Mentah
Atau Dimana
Atau Dimana Mentah
Dimana Antara
Atau Dimana Antara
DimanaTidakDiantara
AtauDi ManaTidakDiantara
Dimana
AtauDi Mana
DimanaTidakDi
AtauDi ManaTidakDi
DimanaNull
Atau DimanaNull
WhereNotNull
AtauWhereNotNull
DimanaSuka
Atau Dimana Seperti
DimanaTidakSuka
Atau Dimana Tidak Suka
Dimana Ada
DimanaTidak Ada
DimanaTidak
Mendapatkan
Pertama
Menemukan
Menyisipkan
Memperbarui
Menghapus
Maks
Minimal
Jumlah
Rata-rata
Menghitung
SisipkanGetId
Masukkan
Sisipkan Atau Abaikan
Ada
Tidak Ada
Memetik
Daftar
Nilai
Paginasi
Kenaikan
Pengurangan
KenaikanSetiap
PenurunanSetiap
Memotong
Serikat
PersatuanSemua
Kunci Bersama
KunciUntuk Pembaruan
Mengganti
Halaman
Sql Terakhir
DimanaPembangun
Atau WhereBuilder
DimanaSub
Atau DimanaSub
Dimana Bersarang
Atau Dimana Bersarang
Ke
Mengikat
Daftar Ke
Memetik Ke
NilaiKe
SumTo
MaxTo
PersatuanKe
PersatuanSemuaKe