laravel 공식 문서 https://laravel.com/docs/10.x/queries와 일치하는 PHP Laravel ORM 구현을 진행하세요.
Go 스타일(구조체 구조 바인딩 사용)과 PHP 스타일(맵 구조 사용)로 구분됩니다.
PHP 스타일 사용의 경우 laravel 쿼리 빌더 문서를 참조하여 1:1 복원을 시도할 수 있습니다.
아직 베타 단계이므로 태그가 지정되어 있지 않으므로, go 모드를 통해서만 도입이 가능하므로 주의하여 사용하시기 바랍니다.
# 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 )
위의 두 가지 사용법은 동일한 결과를 가지며, 테이블 모델과의 바인딩 차이를 제외하고는 다른 방법이 공통적으로 사용됨을 알 수 있습니다.
단일 데이터베이스 연결을 공식 인터페이스와 동일한 방식으로 직접 사용할 수 있습니다.
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/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 값이 무시됩니다. 강제로 쓰기를 원하는 경우 강제로 써야 하는 필드를 다음부터 전달하면 됩니다. 두 번째 매개변수는 다음과 같습니다.
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 조건이 없으면 태그에 pk가 지정된 필드가 자동으로 조건으로 추가됩니다. 예: db:"id,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
의 두 번째 매개변수가 builder.IJoinOn
인 경우 JoinOn
사용법과 동일합니다(두 번째 매개변수에는 강력한 유형 알림이 있어 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 ()
위의 세 가지 사용법은 동일합니다.
// 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 )
})
여기서는 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 )
})
위의 두 가지 사용법은 동일합니다.
하위 쿼리는 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 ()
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 )
두 개의 데이터 열을 맵으로 반환합니다. 첫 번째 열은 값이고 두 번째 열은 키입니다.
// 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}
구조 필드를 선택 필드로 사용합니다. 쿼리 결과는 하나 이상의 필드를 지원하는 구조에 바인딩됩니다.
// 查询一条数据
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의 0 값을 입력합니다.
테이블
선택하다
SelectRaw
추가선택
가입하다
그룹화 기준
데
데원시
아니면 가지고
아니면 원시
주문 기준
한계
오프셋
어디
어디에원시
아니면어디
아니면어디로
어디에사이
아니면어디사이에
어디에 사이가 아닌가
아니면어디사이에있지않는가
어디에
아니면어디에서
어디가 아닌가?
또는WhereNotIn
어디에Null
또는WhereNull
WhereNotNull
또는WhereNotNull
어디처럼
아니면어디처럼
어디가 맘에 안드는지
아니면어디가좋지않은지
존재하는 곳
존재하지 않는 곳
어디가 아닌가
얻다
첫 번째
찾다
끼워 넣다
업데이트
삭제
맥스
최소
합집합
평균
세다
삽입GetId
Upsert
삽입또는무시
존재한다
존재하지 않는다
당기기
목록
값
페이지 매기기
증가
감소
증분각
감소각
자르기
노동 조합
유니온올
공유 잠금
업데이트용 잠금
바꾸다
페이지
마지막 SQL
WhereBuilder
OrWhereBuilder
WhereSub
아니면어디서브
어디에중첩됨
또는WhereNested
에게
묶다
목록으로
뽑기
값:
합계
최대
UnionTo
UnionAllTo