GoRose ORM
_______ ______ .______ ______ _______. _______
/ _____| / __ \ | _ \ / __ \ / || ____|
| | __ | | | | | |_) | | | | | | (----`| |__
| | |_ | | | | | | / | | | | \ \ | __|
| |__| | | `--' | | |\ \----.| `--' | .----) | | |____
\______| \______/ | _| `._____| \______/ |_______/ |_______|
Gorose — это фреймворк ORM на языке Golang, вдохновлённый Eloquent от Laravel.
В версии 2.0 Gorose использует модульную архитектуру, взаимодействует через API интерфейса и строго полагается на нижний уровень. Каждый модуль можно разобрать и даже настроить по своему вкусу.
Схема модулей выглядит следующим образом:
require github.com/gohouse/gorose/v2 v2.1.2
Используйте так:
import "github.com/gohouse/gorose/v2"
docker run -it --rm ababy/gorose sh -c "go run main.go"
Образ Docker: ababy/gorose. Образ Docker содержит пакеты и среду выполнения, необходимые для работы с gorose. Посмотреть Dockerfile
go get -u github.com/gohouse/gorose/v2
db.Table().Fields().Distinct().Where().GroupBy().Having().OrderBy().Limit().Offset().Select()
db.Table().Data().Insert()
db.Table().Data().Where().Update()
db.Table().Where().Delete()
package main
import (
"fmt"
"github.com/gohouse/gorose/v2"
_ "github.com/mattn/go-sqlite3"
)
var err error
var engin *gorose.Engin
func init() {
// Глобальная инициализация и повторное использование баз данных
// Здесь движок необходимо сохранить глобально, используя либо глобальные переменные, либо синглтоны
// Конфигурация & gorose. Config {} — это конфигурация одной базы данных
// Если вы настраиваете кластер с разделением чтения и записи, используйте & gorose. ConfigCluster {}
engin, err = gorose.Open(&gorose.Config{Driver: "sqlite3", Dsn: "./db.sqlite"})
// Пример MySQL, не забудьте импортировать драйвер MySQL из github.com/go-sql-driver/mysql
// engin, err = gorose.Open(&gorose.Config{Driver: "mysql", Dsn: "root:root@tcp(localhost:3306)/test?charset=utf8&parseTime=true"})
}
func DB() gorose.IOrm {
return engin.NewOrm()
}
func main() {
// Собственный SQL, возвращает результаты напрямую
res,err := DB().Query("select * from users where uid>? limit 2", 1)
fmt.Println(res)
affected_rows,err := DB().Execute("delete from users")
fmt.Printf("affected rows: %d\n", affected_rows)
}
``` Вот перевод текста на русский язык:
**где uid=?», 1)**
fmt.Println(affected_rows, err)
// orm chan operation, fetch one row
res, err := DB().Table("users").First()
// res's type is map[string]interface{}
fmt.Println(res)
// rm chan operation, fetch more rows
res2, _ := DB().Table("users").Get()
// res2's type is []map[string]interface{}
fmt.Println(res2)
}
## Использование
Gorose предоставляет привязку объектов данных (map, struct), поддерживая строковые имена таблиц и возврат данных в виде карты. Это обеспечивает большую гибкость.
Рекомендуется использовать привязку данных в качестве приоритета для выполнения операций запроса, чтобы можно было контролировать тип источника данных.
Gorose предлагает стандартные типы `gorose. Map` и `gorose. Data`, чтобы упростить инициализацию привязок и данных.
## Конфигурация и инициализация ссылок
Простая конфигурация
```go
var configSimple = &gorose.Config{
Driver: "sqlite3",
Dsn: "./db.sqlite",
}
Более сложные конфигурации позволяют настроить кластер или даже несколько баз данных в кластере одновременно. База данных случайным образом выбирает базу данных кластера для выполнения соответствующих операций чтения и записи, где мастер является базой данных записи, а ведомый — базой данных чтения. Необходимо выполнить репликацию ведущий-ведомый, здесь только ответственность за чтение и запись.
var config = &gorose.ConfigCluster{
Master: []&gorose.Config{}{configSimple}
Slave: []&gorose.Config{}{configSimple}
Prefix: "pre_",
Driver: "sqlite3",
}
Начальное использование
var engin *gorose.Engin
engin, err := Open(config)
if err != nil {
panic(err.Error())
}
Создание пользовательских таблиц users
DROP TABLE IF EXISTS "users";
CREATE TABLE "users" (
"uid" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"name" TEXT NOT NULL,
"age" integer NOT NULL
);
INSERT INTO "users" VALUES (1, 'gorose', 18);
INSERT INTO "users" VALUES (2, 'goroom', 18);
INSERT INTO "users" VALUES (3, 'fizzday', 18);
Определение структуры таблицы
type Users struct {
Uid int `gorose:"uid"`
Name string `gorose:"name"`
Age int `gorose:"age"`
}
// Устанавливаем имя таблицы. Если нет, по умолчанию используется имя структуры
func (u *Users) TableName() string {
return "users"
}
Собственная операция запроса
// Здесь объект структуры должен быть привязан
// Если вы не определяете структуру, вы можете напрямую использовать карту map, пример map
// var u = gorose.Data{}
// var u = gorose.Map{} Оба варианта возможны.
var u Users
session := engin.NewSession()
// Здесь Bind () используется для хранения результатов. Если вы используете инициализацию NewOrm (), вы можете использовать NewOrm (). Table (). Query () напрямую.
_,err := session.Bind(&u).Query("select * from users where uid=? limit 2", 1)
fmt.Println(err)
fmt.Println(u)
fmt.Println(session.LastSql())
Собственное добавление, удаление и обновление
session.Execute("insert into users(name,age) values(?,?)(?,?)", "gorose",18,"fizzday",19)
session.Execute("update users set name=? where uid=?","gorose",1)
session.Execute("delete from users where uid=?", 1)
var u Users
db := engin.NewOrm()
err := db.Table(&u).Fields("name").AddFields("uid","age").Distinct().Where("uid",">",0).OrWhere("age",18).
Group("age").Having("age>1").OrderBy("uid desc").Limit(10).Offset(1).Select()
type user gorose.Map
// Или следующие определения типов могут быть правильно проанализированы
type user2 map[string]interface{}
type users3 []user
type users4 []map[string]string
type users5 []gorose.Map
type users6 []gorose.Data
Начните использовать привязку карты
db.Table(&user).Select()
db.Table(&users4).Limit(5).Select()
Примечание: если структура данных среза не используется, можно получить только один фрагмент данных. ``` // fetch a row var u Users // bind result to user{} err = db.Table(&u).Fields("uid,name,age").Where("age",">",0).OrderBy("uid desc").Select() if err!=nil { fmt.Println(err) } fmt.Println(u, u.Name) fmt.Println(db.LastSql())
// fetch multi rows // bind result to []Users, db and context condition parameters are reused here // If you don't want to reuse, you can use DB() to open a new session, or db.Reset() // db.Reset() only removes contextual parameter interference, does not change links, DB() will change links. var u2 []Users err = db.Limit(10).Offset(1).Select() fmt.Println(u2)
// count var count int64 // Here reset clears the parameter interference of the upper query and can count all the data. If it is not clear, the condition is the condition of the upper query. // At the same time, DB () can be called new, without interference. count,err = db.Reset().Count() // or count, err = DB().Table(&u).Count() fmt.Println(count, err)
**Advanced Usage**
- Chunk Data Fragmentation, Mass Data Batch Processing (Cumulative Processing)
`When a large amount of data needs to be manipulated, the chunk method can be used if it is unreasonable to take it out at one time and then operate it again.
The first parameter of chunk is the amount of data specified for a single operation. According to the volume of business, 100 or 1000 can be selected.
The second parameter of chunk is a callback method for writing normal data processing logic
The goal is to process large amounts of data senselessly
The principle of implementation is that each operation automatically records the current operation position, and the next time the data is retrieved again, the data is retrieved from the current position.`
```go
User := db.Table("users")
User.Fields("id, name").Where("id",">",2).Chunk(2, func(data []gorose.Data) error {
// for _,item := range data {
// fmt.Println(item)
// }
fmt.Println(data)
// don't forget return error or nil
return nil
})
// print result:
// map[id:3 name:gorose]
// map[id:4 name:fizzday]
// map[id:5 name:fizz3]
// map[id:6 name:gohouse]
[map[id:3 name:gorose] map[name:fizzday id:4]]
[map[id:5 name:fizz3] map[id:6 name:gohouse]]
Loop Data fragmentation, mass data batch processing (from scratch)
Similar to chunk method, the implementation principle is that every operation is to fetch data from the beginning. Reason: When we change data, the result of the change may affect the result of our data taking as where condition, so we can use Loop.
User := db.Table("users")
User.Fields("id, name").Where("id",">",2).Loop(2, func(data []gorose.Data) error {
// for _,item := range data {
// fmt.Println(item)
// }
// here run update / delete
// don't forget return error or nil
return nil
})
// SELECT * FROM users
// WHERE id > 1
// and ( name = 'fizz'
// or ( name = 'fizz2'
// and ( name = 'fizz3' or website like 'fizzday%')
// )
// )
// and job = 'it' LIMIT 1
User := db.Table("users")
User.Where("id", ">", 1).Where(func() {
User.Where("name", "fizz").OrWhere(func() {
User.Where("name", "fizz2").Where(func() {
User.Where("name", "fizz3").OrWhere("website", "like", "fizzday%")
})
})
}).Where("job", "it").First()
xxx.Join("pre_tablename")
into xxx.Join("tablename")
,the join table name auto prefix change err:=DB().Bind().Query()
into res,err:=DB().Query()
with multi return,leave the Bind()
method as wellalipay | paypal: click | |
---|---|---|
![]() |
![]() |
![]() |
сумма | аватар |
---|---|
100 юаней |
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )