테스트용 필드 정의

func (User) Fields() []ent.Field {
	return []ent.Field{
		field.String("name").
			Unique(),
		field.Int("age").
			Positive(),
		field.Enum("sex").
			Values("male", "female"),
		field.Time("created").
			Default(time.Now).
			Immutable(),
		field.UUID("user_uuid", uuid.New()).
			Default(func() uuid.UUID {
				return uuid.Must(uuid.NewRandom())
			}).
			Immutable(),
	}
}

정의된 구조체

type User struct {
	config `json:"-"`
	// ID of the ent.
	ID int `json:"id,omitempty"`
	// Name holds the value of the "name" field.
	Name string `json:"name,omitempty"`
	// Age holds the value of the "age" field.
	Age int `json:"age,omitempty"`
	// Sex holds the value of the "sex" field.
	Sex user.Sex `json:"sex,omitempty"`
	// Created holds the value of the "created" field.
	Created time.Time `json:"created,omitempty"`
	// UserUUID holds the value of the "user_uuid" field.
	UserUUID uuid.UUID `json:"user_uuid,omitempty"`
}

데이터베이스 접속

SQLite3

package main

import (
    "log"

    "todo/ent"
    _ "github.com/mattn/go-sqlite3"
)

func main() {
    // file mode
    client, err := ent.Open("sqlite3", "file:<file.db>?_fk=1")
    
    // mem mode
    client, err := ent.Open("sqlite3", "file:todo?mode=memory&cache=shared&_fk=1")
    
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()
}

PostgreSQL

package main

import (
    "log"

    "todo/ent"
    _ "github.com/lib/pq"
)

func main() {
    client, err := ent.Open("postgres","host=<host> port=<port> user=<user> dbname=<database> password=<pass>")
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()
}

MySQL

package main

import (
    "log"

    "todo/ent"
    _ "github.com/go-sql-driver/mysql"
)

func main() {
    client, err := ent.Open("mysql", "<user>:<pass>@tcp(<host>:<port>)/<database>?parseTime=True")
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()
}

스키마 생성

// ... connect database client

ctx := context.Background()
if err := client.Schema.Create(ctx); err != nil {
        log.Fatalf("failed creating schema resources: %v", err)
}

데이터베이스 접속하고 스키마 생성

package main

import (
	"context"
	"log"

	"todo/ent"

	// sqlite3 드라이버
	_ "github.com/mattn/go-sqlite3"
)

func main() {
	// sqlite3로 오픈
	client, err := ent.Open("sqlite3", "./todo.db?_fk=1")
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	ctx := context.Background()		// 앞으로 사용할 함수들에 사용합니다.

	// 스키마 생성
	if err := client.Schema.Create(ctx); err != nil {
		log.Fatalf("failed creating schema resources: %v", err)
	}

}

Create - 데이터 입력

데이터 입력은 Create/Save 함수를 사용합니다. Save 함수는 데이터베이스에 데이터 입력 후, 입력한 데이터 구조체를 리턴 합니다.  SaveX 함수는 데이터 저장 과정 중, 에러 발생 시 에러를 리턴 하지 않고, 패닉을 발생 시킵니다.

///// 구조
client.{Schema Name}.Create().
Set{Field}().
.
.
.
Save(ctx)
/////

///// 예제
bob, err := client.User.Create().
SetName("Bob").
SetAge(18).
SetSex(user.SexMale).
Save(ctx)

chris := client.User.Create().
SetName("chris").
SetAge(20).
SetSex(user.SexFemale).
SaveX(ctx)	// if err -> panic err

Table

sqlite> select * from users;
1|Bob|18|male|2021-04-17 14:21:24.923808846+09:00|a8f5d4f2-fc5e-4cc5-8a41-be524bd9a1f3
2|chris|20|female|2021-04-17 14:21:24.931267299+09:00|97e6526f-9299-4908-9fca-1c7ce78d351e
id name age sex created uuid
1 Bob 18 male 2021-04-17 14:21:24.923808846+09:00 a8f5d4f2-fc5e-4cc5-8a41-be524bd9a1f3
2 chris 20 female 2021-04-17 14:21:24.931267299+09:00 97e6526f-9299-4908-9fca-1c7ce78d351e

Update - 데이터 수정

데이터를 수정합니다.

구조체 데이터가 있을 경우

Create() 혹은 쿼리 후 리턴 받은 구조체로 Update 하는 방법 입니다.

bobby := client.User.Create().
	SetName("bobby").
	SetAge(719).	// 잘못 입력한 나이
	SetSex(user.SexFemale).
	SaveX(ctx)

log.Printf("%#v", *bobby)	// 수정 전 bobby 출력

bobby = bobby.Update().
	SetAge(19).		// 나이 수정
	SaveX(ctx)

log.Printf("%#v", *bobby)	// 수정 후 bobby 출력

출력

... , ID:3, Name:"bobby", Age:719, Sex:"female", ...
... , ID:3, Name:"bobby", Age:19, Sex:"female", ...

Table

sqlite> select * from users;
1|Bob|18|male|2021-04-17 14:21:24.923808846+09:00|a8f5d4f2-fc5e-4cc5-8a41-be524bd9a1f3
2|chris|20|female|2021-04-17 14:21:24.931267299+09:00|97e6526f-9299-4908-9fca-1c7ce78d351e
3|bobby|19|female|2021-04-17 14:29:50.30755959+09:00|ca0ca04e-244d-4e72-ae22-b7a14abef6be
id name age sex created uuid
1 Bob 18 male 2021-04-17 14:21:24.923808846+09:00 a8f5d4f2-fc5e-4cc5-8a41-be524bd9a1f3
2 chris 20 female 2021-04-17 14:21:24.931267299+09:00 97e6526f-9299-4908-9fca-1c7ce78d351e
3 bobby 19 female 2021-04-17 14:29:50.30755959+09:00 ca0ca04e-244d-4e72-ae22-b7a14abef6be

ID로 수정

bob := client.User.UpdateOneID(1).
	SetName("bob").
	SaveX(ctx)

Table

sqlite> select * from users;
1|bob|18|male|2021-04-17 14:21:24.923808846+09:00|a8f5d4f2-fc5e-4cc5-8a41-be524bd9a1f3
2|chris|20|female|2021-04-17 14:21:24.931267299+09:00|97e6526f-9299-4908-9fca-1c7ce78d351e
3|bobby|19|female|2021-04-17 14:29:50.30755959+09:00|ca0ca04e-244d-4e72-ae22-b7a14abef6be
id name age sex created uuid
1 bob 18 male 2021-04-17 14:21:24.923808846+09:00 a8f5d4f2-fc5e-4cc5-8a41-be524bd9a1f3
2 chris 20 female 2021-04-17 14:21:24.931267299+09:00 97e6526f-9299-4908-9fca-1c7ce78d351e
3 bobby 19 female 2021-04-17 14:29:50.30755959+09:00 ca0ca04e-244d-4e72-ae22-b7a14abef6be

Where 조건으로 수정

client.User.Update().Where(
		user.Or(
			user.AgeGTE(19),	// age >= 19 or name == "chris"
			user.Name("chris"),
		),
	).
	SetSex(user.SexMale).
	SaveX(ctx)

table

sqlite> select * from users;
1|bob|18|male|2021-04-17 14:21:24.923808846+09:00|a8f5d4f2-fc5e-4cc5-8a41-be524bd9a1f3
2|chris|20|male|2021-04-17 14:21:24.931267299+09:00|97e6526f-9299-4908-9fca-1c7ce78d351e
3|bobby|19|male|2021-04-17 14:29:50.30755959+09:00|ca0ca04e-244d-4e72-ae22-b7a14abef6be
id name age sex created uuid
1 bob 18 male 2021-04-17 14:21:24.923808846+09:00 a8f5d4f2-fc5e-4cc5-8a41-be524bd9a1f3
2 chris 20 male 2021-04-17 14:21:24.931267299+09:00 97e6526f-9299-4908-9fca-1c7ce78d351e
3 bobby 19 male 2021-04-17 14:29:50.30755959+09:00 ca0ca04e-244d-4e72-ae22-b7a14abef6be

Read - 데이터 쿼리 하기

테이블 모두 읽기

users := client.User.
	Query().
	AllX(ctx)

for i, u := range users {
	fmt.Printf("%d | id:%d name:%s age:%d sex:%s created:%s\n", i, u.ID, u.Name, u.Age, u.Sex, u.Created.String())
}

출력

0 | id:1 name:bob age:18 sex:male created:2021-04-17 14:21:24.923808846 +0900 +0900
1 | id:2 name:chris age:20 sex:male created:2021-04-17 14:21:24.931267299 +0900 +0900
2 | id:3 name:bobby age:19 sex:male created:2021-04-17 14:29:50.30755959 +0900 +0900

Where 필터링

users := client.User.
	Query().
	Where(user.AgeGTE(19)). // age >= 19
	AllX(ctx)

for i, u := range users {
	fmt.Printf("%d | id:%d name:%s age:%d sex:%s created:%s\n", i, u.ID, u.Name, u.Age, u.Sex, u.Created.String())
}

출력

0 | id:2 name:chris age:20 sex:male created:2021-04-17 14:21:24.931267299 +0900 +0900
1 | id:3 name:bobby age:19 sex:male created:2021-04-17 14:29:50.30755959 +0900 +0900

하나만 받아오기

Only(), OnlyX() 를 사용합니다.

bob := client.User.
	Query().
	Where(user.Name("bob")).
	OnlyX(ctx)

fmt.Printf("id:%d name:%s age:%d sex:%s created:%s\n", bob.ID, bob.Name, bob.Age, bob.Sex, bob.Created.String())

출력

id:1 name:bob age:18 sex:male created:2021-04-17 14:21:24.923808846 +0900 +0900

Select 사용하기

하나의 필드 select 후 값 바로 읽기

받을 값 함수
문자열 String()/StringX()
문자열 리스트 Strings()/StringsX()
숫자 Int()/IntX()
숫자 리스트 Ints()/IntsX()
실수 Float64()/Float64X()
실수 리스트 Float64s()/Float64sX()
Bool Bool()/BoolX()
Bool 리스트 Bools()/BoolsX()
기타 Scan()/ScanX()
names := client.User.
		Query().
		Select(user.FieldName).	// select 필드가 하나일 경우
		StringsX(ctx)

	fmt.Printf("%#v\n", names)

출력

[]string{"bob", "bobby", "chris"}

복수의 필드 Select

Only 사용

bob := client.User.
	Query().
	Where(user.Name("bob")).
    Select(user.FieldName, user.FieldAge).
	OnlyX(ctx)

fmt.Printf("%#v\n", bob)

출력

Select한 필드를 제외한 나머지 필드는 0, "", nil값이 저장 됩니다.

... , ID:1, Name:"bob", Age:18, Sex:"", Created:time.Time{wall:0x0, ext:0, loc:(*time.Location)(nil)}, UserUUID:uuid.UUID{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}

Scan 사용

Scan() ScanX() 사용 시 스캔 값을 저장할 타입은 슬라이스 형태 타입으로 넣어줘야 합니다.

새로 정의한 구조체에 값 넣기

type OneUser struct {
	Name string
	Age  int
}

users := []OneUser{}

client.User.
	Query().
    Where(user.Name("bob")).
	Select(user.FieldName, user.FieldAge).ScanX(ctx, &users)

fmt.Printf("%#v\n", users)

출력

[]main.OneUser{main.OneUser{Name:"bob", Age:18}}

기본 자료형 사용

var names []string

client.User.
	Query().Where(user.Name("bob")).
	Select(user.FieldName).ScanX(ctx, &names)

fmt.Printf("%#v\n", names)

출력

[]string{"bob"}

Delete - 데이터 삭제

하나 삭제

쿼리한 값으로 삭제 합니다.

bobby := client.User.	// bobby 얻기
	Query().
	Where(user.Name("bobby")).
	OnlyX(ctx)

client.User.			// bobby 삭제
	DeleteOne(bobby).
	ExecX(ctx)

sql table

sqlite> select * from users;
1|bob|18|male|2021-04-17 14:21:24.923808846+09:00|a8f5d4f2-fc5e-4cc5-8a41-be524bd9a1f3
2|chris|20|male|2021-04-17 14:21:24.931267299+09:00|97e6526f-9299-4908-9fca-1c7ce78d351e
id name age sex created uuid
1 bob 18 male 2021-04-17 14:21:24.923808846+09:00 a8f5d4f2-fc5e-4cc5-8a41-be524bd9a1f3
2 chris 20 male 2021-04-17 14:21:24.931267299+09:00 97e6526f-9299-4908-9fca-1c7ce78d351e

ID로 삭제

client.User.
	DeleteOneID(1).
	ExecX(ctx)

sql table

sqlite> select * from users;
2|chris|20|male|2021-04-17 14:21:24.931267299+09:00|97e6526f-9299-4908-9fca-1c7ce78d351e
id name age sex created uuid
2 chris 20 male 2021-04-17 14:21:24.931267299+09:00 97e6526f-9299-4908-9fca-1c7ce78d351e

Where로 삭제

client.User.
	Delete().
	Where(user.SexEQ(user.SexMale)).	// sex == male
	ExecX(ctx)

sql table

sqlite> select * from users;
id name age sex created uuid