Implementação Go do PHP Laravel ORM, consistente com a documentação oficial do laravel https://laravel.com/docs/10.x/queries.
Ele é dividido em estilo Go (uso de ligação de estrutura de estrutura) e estilo PHP (uso de estrutura de mapa).
Para uso no estilo PHP, você pode usar a documentação do construtor de consultas laravel como referência e tentar obter uma restauração 1:1.
Ainda está em fase beta, use-o com cuidado, pois não está marcado, só pode ser introduzido usando go mod.
# go.mod
require github.com/gohouse/gorose/v3 master
vá de uso de estilo
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 )
}
O uso do estilo PHP e a consulta de uso do estilo Go são os seguintes: comparação 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 )
Os dois usos acima têm os mesmos resultados. Pode-se observar que, exceto pela diferença na ligação ao modelo de tabela, outros métodos são comuns.
A conexão única com o banco de dados pode ser usada diretamente da mesma forma que a interface oficial
var rose = gorose . Open ( "mysql" , "root:123456@tcp(localhost:3306)/test?charset=utf8mb4&parseTime=true" )
Também pode ser usado
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 )
Ou use um cluster de separação leitura-gravação para forçar automaticamente a leitura dos dados do banco de dados de gravação em uma transação.
var rose = gorose . Open (
gorose. ConfigCluster {
WriteConf : []gorose. Config {
conf1 ,
conf2 ,
},
ReadConf : []gorose. Config {
conf3 ,
conf4 ,
}
},
)
Atualmente, o suporte para os 5 bancos de dados acima foi implementado. Para bancos de dados gerais, você só precisa adicionar mais interfaces gorose/driver/dialect.IDialect
. Para bancos de dados não universais, desde que a interface gorose/driver.IDriver seja implementada. qualquer banco de dados pode ser teoricamente suportado. Incluindo redis, mongo, etc., todas as operações da cadeia ORM podem ser implementadas por meio desta interface. Todas as operações da cadeia ORM estão em gorose/builder.Context
e os dados originais podem ser obtidos diretamente.
// 全自动事务, 有错误会自动回滚, 无错误会自动提交
// 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 ()
Ao inserir e atualizar dados, se você usar o modelo struct como objeto de dados, o valor do tipo zero será ignorado por padrão. Se você quiser forçar a escrita, você pode passar os campos que precisam ser escritos a partir do. segundo parâmetro, como:
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 }))
Se não houver condição where, o campo com pk especificado na tag será adicionado automaticamente como uma condição, como: db:"id,pk"
. será atualizado como a condição da chave primária.
Atualização de referência
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 ()
Em gorose.As(UserInfo{}, "b")
, user_info
usa o 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 ()
Quando o segundo parâmetro de Join
é builder.IJoinOn
, é equivalente ao uso de JoinOn
(o segundo parâmetro tem um lembrete de tipo forte, o que é conveniente para prompts rápidos do 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 ()
Os três usos acima são equivalentes
// 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 )
})
Onde aqui é equivalente a 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 )
})
Os dois usos acima são equivalentes
Subconsultas podem ser usadas em Tabela, Onde e Junção.
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 ()
Usado em tabela, onde, juntar
db ().
Table ( sub , "a" ).
Join ( gorose . As ( sub2 , "b" ), "a.id" , "=" , "b.user_id" )).
WhereIn ( "a.id" , sub3 ).
Get ()
Usado em 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 )
Retorne duas colunas de dados em um mapa, a primeira coluna é o valor e a segunda coluna é a chave
// select id,name from users
db (). Table ( "users" ). Pluck ( "name" , "id" )
// 返回 map[<id>]<name>, 实际得到 map[int64]string{1: "张三", 2: "李四"}
Retornar uma coluna de dados em um array
// select id,name from users
db (). Table ( "users" ). List ( "id" )
// 返回 []<id>, 实际得到 []int64{1,2,3}
Use o campo de estrutura como o campo de seleção Use o valor do campo de estrutura como a condição onde O resultado da consulta está vinculado à estrutura, suportando um ou mais campos.
// 查询一条数据
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 )
Ele é usado apenas como um campo de estrutura de ligação para resultados de consulta. Não é usado como campos e condições de consulta. Geralmente é usado para ligação de consulta de campo especificado manualmente.
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 )
O nome de exibição do campo de consulta deve ser igual ao nome da tag de campo (db) da estrutura, caso contrário o número de campos que não serão atribuídos pode ser diferente.
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 )
Por padrão, o nível de depuração do slog da biblioteca oficial é usado. Se você não deseja exibir o log sql, você só precisa definir o nível do slog para depuração acima, como: Info, Warn, Error.
type User struct {
Id int64 `db:"id,pk"`
Sex * int8 `db:"sex"` // 使用指针可以绑定 null 值
Age sql. NullInt64 `db:"age"` // 使用sql.NullInt64 可以绑定 null 值
}
atribuição de ponteiro
var sex = int8 ( 1 )
var user = User { Id : 1 , Sex : & sex }
// 或者,快捷用法
var user = User { Id : 1 , Sex : gorose . Ptr ( int8 ( 1 ))}
atribuição sql.Null*
var age = sql. NullInt64 { Int64 : 18 , Valid : true }
sql.Null* uso
if age . Valid {
fmt . Println ( age . Int64 )
}
Percebe-se que ainda é um pouco problemático lidar com nulo. Portanto, é recomendável que ao projetar a tabela, apenas não permita nulo, a maioria dos valores padrão podem corresponder apenas ao valor padrão. digite o valor zero de go.
Mesa
Selecione
Selecione Raw
AdicionarSelecionar
Juntar
Agrupar por
Tendo
Tendo Raw
Ou tendo
OuHavingRaw
Encomendar por
Limite
Desvio
Onde
OndeRaw
OuOnde
OuOndeRaw
Onde entre
OuOndeEntre
OndeNãoEntre
OuOndeNãoEntre
Em que
OuOndeIn
Onde não está
OuOndeNãoIn
OndeNulo
OuOndeNulo
OndeNotNull
OrWhereNotNull
OndeComo
OuOndeLike
OndeNãoGosto
OuOndeNãoLike
Onde existe
OndeNãoExiste
Onde não
Pegar
Primeiro
Encontrar
Inserir
Atualizar
Excluir
Máx.
Mínimo
Soma
Média
Contar
InserirGetId
Upsert
Inserir ou ignorar
Existe
Não existe
Arranque
Lista
Valor
Paginar
Incremento
Diminuir
IncrementEach
DecrementEach
Truncar
União
UniãoTodos
SharedLock
LockForUpdate
Substituir
Página
ÚltimoSql
OndeConstrutor
OrWhereBuilder
OndeSub
OuOndeSub
Onde aninhado
OuOndeAninhado
Para
Vincular
Listar para
Arrancar para
ValorPara
SomaTo
MaxTo
UniãoPara
UniãoAllTo