Vaya a la implementación de PHP Laravel ORM, de acuerdo con la documentación oficial de Laravel https://laravel.com/docs/10.x/queries.
Se divide en estilo Go (uso de enlace de estructura de estructura) y estilo PHP (uso de estructura de mapa).
Para el uso del estilo PHP, puede utilizar la documentación del generador de consultas laravel como referencia e intentar lograr una restauración 1:1.
Todavía se encuentra en la etapa beta, utilícelo con precaución. Dado que no está etiquetado, solo se puede introducir usando go mod.
# go.mod
require github.com/gohouse/gorose/v3 master
ir al uso del 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 )
}
El uso del estilo PHP y la consulta de uso del estilo Go son la siguiente comparación de 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 )
Los dos usos anteriores tienen los mismos resultados. Se puede ver que, excepto por la diferencia en la vinculación al modelo de tabla, otros métodos son comunes.
La conexión de base de datos única se puede utilizar directamente de la misma manera que la interfaz oficial.
var rose = gorose . Open ( "mysql" , "root:123456@tcp(localhost:3306)/test?charset=utf8mb4&parseTime=true" )
También se puede utilizar
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 )
O utilice un clúster de separación de lectura y escritura para forzar automáticamente la lectura de datos de la base de datos de escritura dentro de una transacción.
var rose = gorose . Open (
gorose. ConfigCluster {
WriteConf : []gorose. Config {
conf1 ,
conf2 ,
},
ReadConf : []gorose. Config {
conf3 ,
conf4 ,
}
},
)
Actualmente, se ha implementado soporte para las 5 bases de datos anteriores. Para bases de datos generales, solo necesita agregar más interfaces gorose/driver/dialect.IDialect
. Para bases de datos no universales, siempre que se implemente la interfaz gorose/driver.IDriver. En teoría, cualquier base de datos puede ser compatible, incluidas redis, mongo, etc., todas las operaciones de la cadena ORM se pueden implementar a través de esta interfaz. Todas las operaciones de la cadena ORM están en gorose/builder.Context
y los datos originales se pueden obtener directamente.
// 全自动事务, 有错误会自动回滚, 无错误会自动提交
// 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 ()
Al insertar y actualizar datos, si utiliza el modelo de estructura como objeto de datos, el valor de tipo cero se ignora de forma predeterminada. Si desea forzar la escritura, puede pasar los campos que deben forzarse a escribirse comenzando desde el. segundo parámetro, como por ejemplo:
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 }))
Si no hay ninguna condición donde, el campo con pk especificado en la etiqueta se agregará automáticamente como condición, como por ejemplo: db:"id,pk"
Debido a que se especifica pk, si el valor de id no es 0, el id. se actualizará como condición de clave principal.
Actualización de referencia
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 ()
En gorose.As(UserInfo{}, "b")
, user_info
toma el 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 ()
Cuando el segundo parámetro de Join
es builder.IJoinOn
, es equivalente al uso JoinOn
(el segundo parámetro tiene un recordatorio de tipo fuerte, que es conveniente para las indicaciones rápidas del 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 ()
Los tres usos anteriores son 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 )
})
Donde aquí es 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 )
})
Los dos usos anteriores son equivalentes.
Las subconsultas se pueden utilizar en Tabla, Dónde y Unirse.
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 ()
Utilizado en tabla, dónde, unirse
db ().
Table ( sub , "a" ).
Join ( gorose . As ( sub2 , "b" ), "a.id" , "=" , "b.user_id" )).
WhereIn ( "a.id" , sub3 ).
Get ()
Utilizado en Unión, UniónTodos
db ().
Table ( "users" ).
Union ( sub ).
Get ()
var sub2222 = db (). Table ( "user" ). Where (). OrWhere ()
var to [] User
db ().
Table ( "users" ).
UnionAll ( sub , sub2222 ).
To ( & to )
Devuelve dos columnas de datos en un mapa, la primera columna es el valor y la segunda columna es la clave
// select id,name from users
db (). Table ( "users" ). Pluck ( "name" , "id" )
// 返回 map[<id>]<name>, 实际得到 map[int64]string{1: "张三", 2: "李四"}
Devolver una columna de datos en una matriz
// select id,name from users
db (). Table ( "users" ). List ( "id" )
// 返回 []<id>, 实际得到 []int64{1,2,3}
Utilice el campo de estructura como campo de selección. Utilice el valor del campo de estructura como condición donde. El resultado de la consulta está vinculado a la estructura y admite uno o más 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 )
Solo se usa como campo de estructura vinculante para resultados de consultas. No se usa como campos y condiciones de consulta. A menudo se usa para unir o vincular consultas de campos especificados 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 )
El nombre para mostrar del campo de consulta debe ser el mismo que el nombre de la etiqueta de campo (db) de la estructura; de lo contrario, la cantidad de campos que no se asignarán puede 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 )
De forma predeterminada, se utiliza el nivel de depuración de trabajo de la biblioteca oficial. Si no desea mostrar el registro de SQL, solo necesita configurar el nivel de trabajo de trabajo en el nivel de depuración anterior, como por ejemplo: Información, Advertencia, Error.
type User struct {
Id int64 `db:"id,pk"`
Sex * int8 `db:"sex"` // 使用指针可以绑定 null 值
Age sql. NullInt64 `db:"age"` // 使用sql.NullInt64 可以绑定 null 值
}
asignación de puntero
var sex = int8 ( 1 )
var user = User { Id : 1 , Sex : & sex }
// 或者,快捷用法
var user = User { Id : 1 , Sex : gorose . Ptr ( int8 ( 1 ))}
asignación sql.Null*
var age = sql. NullInt64 { Int64 : 18 , Valid : true }
uso de sql.Null*
if age . Valid {
fmt . Println ( age . Int64 )
}
Se puede ver que todavía es un poco problemático tratar con nulos. Por lo tanto, se recomienda no permitir nulos al diseñar la tabla. Se dan valores predeterminados, y la mayoría de los valores predeterminados pueden corresponder simplemente. escriba el valor cero de go.
Mesa
Seleccionar
SeleccionarSin procesar
AgregarSeleccionar
Unirse
Agrupar por
Teniendo
Tener crudo
o tener
O tener crudo
Ordenar por
Límite
Compensar
Dónde
donde crudo
o donde
O donde crudo
donde entre
O donde entre
Donde no hay entre
O donde no hay entre
Donde
o donde en
Donde no en
O donde no está
DondeNulo
O dondeNull
Donde no es nulo
O donde no es nulo
dondecomo
O donde como
donde no me gusta
O donde no me gusta
Donde existe
Donde no existe
donde no
Conseguir
Primero
Encontrar
Insertar
Actualizar
Borrar
máx.
mín.
Suma
promedio
Contar
InsertarGetId
insertar
Insertar o ignorar
existe
No existe
Arrancar
Lista
Valor
Paginar
Incremento
Decremento
Incrementar cada uno
DisminuirCada uno
Truncar
Unión
UniónTodos
Bloqueo compartido
Bloquear para actualizar
Reemplazar
Página
ÚltimoSql
DondeConstructor
ODondeConstructor
Donde Sub
ODóndeSub
DondeAnidado
O donde anidado
A
Unir
Lista a
Arrancar para
Valor a
suma a
MaxTo
unióna
UniónTodosA