【Go】xormの使い方 その②

# はじめに
前回に続いて、xorm使い方その②です。
前回の続きですので、xormの導入などは終わっている程で話を進めます。
今回はいろんなメソッドを解説しようと思います。
今回解説するのは、以下の通りです。

# 目次

- Table
- Select
- Sum, SumInt
- Where, And, Or
- OrderBy, Asc, Desc
- SQL, Query


# 環境

go 1.15
github.com/go-sql-driver/mysql v1.6.0
xorm.io/xorm v1.2.3

# DBのデータ

今回はこちらのデータを使用します。
![スクリーンショット 2021-09-05 23.36.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/986475/0b372c59-e6d4-3766-5d0e-e951fe604a68.png)

# enginの用意

```go
package main

import (
	"fmt"
	"log"
	"time"

	_ "github.com/go-sql-driver/mysql"
	"xorm.io/xorm"
)

type User struct {
	Id       int64 `xorm:"id"`
	Name     string
	Age      int
	Password string    `xorm:"password"`
	Created  time.Time `xorm:"created"`
	Updated  time.Time `xorm:"updated"`
}

func main() {
	engine, err := xorm.NewEngine("mysql", "root:root@tcp([127.0.0.1]:3306)/sample_db?charset=utf8mb4&parseTime=true")
	if err != nil {
		log.Fatal(err)
	}

	err = engine.Sync2(new(User))
	if err != nil {
		log.Fatal(err)
	}

	// メソッドを実行します
	// Table(*engine)
	// Select(*engine)
	// SetID(*engine)
	// Sum(*engine)
	// SumsInt(*engine)
	// WhereAnd(*engine)
	// WhereOr(*engine)
	// OrderBy(*engine)
	// Asc(*engine)
	// Desc(*engine)
	// SQL(*engine)
	// Query(*engine)
}
```

これでenginの用意が整いました。
以下は、main.goにメソッドを作成したら、こうなるというのを解説していきます。

## Table

これは操作するテーブルを指定するだけです。
簡単です。

```go
func Table(engine xorm.Engine) {
	user := User{}
	// ここでテーブルをユーザーテーブルを指定します。
	session := engine.Table("user")
	_, err := session.Where("id = ?", 1).Get(&user)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("user:", user)
}
```

出力結果

```
user: {1 花子 30 パスワード 2021-08-29 16:47:24 +0900 JST 2021-08-29 16:47:24 +0900 JST}
```

テーブルを指定して、sessionに入れます。
それをWhereで条件を指定し、Getでマッピングします。
Tableでテーブルを指定しなくても、構造体から勝手に判断してくれます。
前回やった下記のコードでも同じように取得出来ます。

```go
func Get(engine xorm.Engine) {
	user := User{}
	_, err := engine.Where("id = ?", 1).Get(&user)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("user:", user)
}
```

結果は同じですが、Tableを使った方が明示的で分かりやすいです。

## Select

SQLのSELECTと同じです。カラム名を指定します。

```go
func Select(engine xorm.Engine) {
	user := User{}
	// ここでテーブルをユーザーテーブルを指定します。
	session := engine.Table("user")
	result, err := session.Select("name").Get(&user)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("user:", user)
	fmt.Println("result:", result)
}
```

出力結果

```
user: {0 花子 0  0001-01-01 00:00:00 +0000 UTC 0001-01-01 00:00:00 +0000 UTC}
result: true
```

カラムを指定しても、Getの返り値resultはtrueかfalseです。
構造体Userにはnameのカラムだけ入るので、結果は名前だけ更新されています。

## Sum, SumInt

指定したカラムの値を合計します。
カラムの数を数えるのではないのでご注意ください。

```go
func Sum(engine xorm.Engine) {
	user := User{}
	sumFloat64, _ := engine.Sum(user, "id")
	print(" sumFloat64: ", sumFloat64)
}

func SumsInt(engine xorm.Engine) {
	user := User{}
	sumInt, _ := engine.SumInt(user, "id")
	print(" sumInt: ", sumInt)
}
```

出力結果

```
sumFloat64: +6.000000e+000
sumInt: 6 
```

普通のSumはFloat64が返ってきます。
intで返して欲しい場合は、SumIntを使います。

## Where, And, Or

この3つはSQLと同じように使います。

```go
func WhereAnd(engine xorm.Engine) {
	users := []User{}
	session := engine.Table("user")
	err := session.Where("id > ?", 1).And("age = ?", 30).Find(&users)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("whereAndUsers:", users)
}

func WhereOr(engine xorm.Engine) {
	users := []User{}
	session := engine.Table("user")
	err := session.Where("id > ?", 1).Or("age = ?", 30).Find(&users)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("whereOrUsers:", users)
}
```

WhereAndはidが1より大きく、かつ、ageが30のユーザーを取得します。
WhereOrはidが1より大きい、もしくは、ageが30のユーザーを取得します。

出力結果

```
whereAndUsers: [{2 たけし 30 パスワード 2021-08-29 16:48:42 +0900 JST 2021-08-29 16:48:42 +0900 JST}]
```
```
whereOrUsers: [{1 花子 30 パスワード 2021-08-29 16:47:24 +0900 JST 2021-08-29 16:47:24 +0900 JST} {2 たけし 30 パスワード 2021-08-29 16:48:42 +0900 JST 2021-08-29 16:48:42 +0900 JST} {3 太郎 20 パスワード 2021-08-29 16:49:35 +0900 JST 2021-08-29 16:49:35 +0900 JST}]
```

## OrderBy, Asc, Desc

これも基本的には、ほとんどSQLと同じです。

```go
func OrderBy(engine xorm.Engine) {
	users := []User{}
	session := engine.Table("user")
	err := session.OrderBy("id DESC").Find(&users)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("users:", users)
}
```

出力結果

```
users: [{3 太郎 20 パスワード 2021-08-29 16:49:35 +0900 JST 2021-08-29 16:49:35 +0900 JST} {2 たけし 30 パスワード 2021-08-29 16:48:42 +0900 JST 2021-08-29 16:48:42 +0900 JST} {1 花子 30 パスワード 2021-08-29 16:47:24 +0900 JST 2021-08-29 16:47:24 +0900 JST}]
```

```go
func Asc(engine xorm.Engine) {
	users := []User{}
	session := engine.Table("user")
	err := session.Asc("id").Find(&users)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("AscUsers:", users)
}
```

出力結果

```
AscUsers: [{1 花子 30 パスワード 2021-08-29 16:47:24 +0900 JST 2021-08-29 16:47:24 +0900 JST} {2 たけし 30 パスワード 2021-08-29 16:48:42 +0900 JST 2021-08-29 16:48:42 +0900 JST} {3 太郎 20 パスワード 2021-08-29 16:49:35 +0900 JST 2021-08-29 16:49:35 +0900 JST}]
```

```go
func Desc(engine xorm.Engine) {
	users := []User{}
	session := engine.Table("user")
	err := session.Desc("id").Find(&users)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("DescUsers:", users)
}
```

出力結果

```
DescUsers: [{3 太郎 20 パスワード 2021-08-29 16:49:35 +0900 JST 2021-08-29 16:49:35 +0900 JST} {2 たけし 30 パスワード 2021-08-29 16:48:42 +0900 JST 2021-08-29 16:48:42 +0900 JST} {1 花子 30 パスワード 2021-08-29 16:47:24 +0900 JST 2021-08-29 16:47:24 +0900 JST}]
```

.OrderByでidだけを指定すると、ASCになります。
.OrderByのidの後ろのDESCはDescでもdesc大丈夫です。
ただ単に昇順や降順にするだけなら、.Ascか.Descを使った方が分かりやすいですね。

## SQL, Query

xormは生のSQLのQueryも実行出来ます。

```go
func SQL(engine xorm.Engine) {
	users := []User{}
	err := engine.SQL("select * from user").Find(&users)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("users:", users)
}
```

出力結果

```
users: [{1 花子 30 パスワード 2021-08-29 16:47:24 +0900 JST 2021-08-29 16:47:24 +0900 JST} {2 たけし 30 パスワード 2021-08-29 16:48:42 +0900 JST 2021-08-29 16:48:42 +0900 JST} {3 太郎 20 パスワード 2021-08-29 16:49:35 +0900 JST 2021-08-29 16:49:35 +0900 JST}]
```

```go
func Query(engine xorm.Engine) {
	results, err := engine.Query("select * from user")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("results:", results)
}
```

出力結果

```
results: [map[age:[51 48] created:[50 48 50 49 45 48 56 45 50 57 84 49 54 58 52 55 58 50 52 90] id:[49] name:[232 138 177 229 173 144] password:[227 131 145 227 130 185 227 131 175 227 131 188 227 131 137] updated:[50 48 50 49 45 48 56 45 50 57 84 49 54 58 52 55 58 50 52 90]] map[age:[51 48] created:[50 48 50 49 45 48 56 45 50 57 84 49 54 58 52 56 58 52 50 90] id:[50] name:[227 129 159 227 129 145 227 129 151] password:[227 131 145 227 130 185 227 131 175 227 131 188 227 131 137] updated:[50 48 50 49 45 48 56 45 50 57 84 49 54 58 52 56 58 52 50 90]] map[age:[50 48] created:[50 48 50 49 45 48 56 45 50 57 84 49 54 58 52 57 58 51 53 90] id:[51] name:[229 164 170 233 131 142] password:[227 131 145 227 130 185 227 131 175 227 131 188 227 131 137] updated:[50 48 50 49 45 48 56 45 50 57 84 49 54 58 52 57 58 51 53 90]]]
```

SQLもQueryもどちらも生のSQL文を使えますが、Queryはbyteで返って来ます。
SQLの方が使いやすそうです。


# さいごに

他にも色々ありますが、今回はこの辺で。

# 参考

https://pkg.go.dev/github.com/go-xorm/xorm

https://www.kancloud.cn/xormplus/xorm/167087