From bea64d552f9cd3ca40e295800f28415470f5bc9e Mon Sep 17 00:00:00 2001 From: Jinzhu Date: Fri, 26 Feb 2016 21:58:36 +0800 Subject: [PATCH] github pages --- README.md | 3 - SUMMARY.md | 32 -- advanced.html | 786 ++++++++++++++++++++++++++++ associations.html | 787 ++++++++++++++++++++++++++++ callbacks.html | 717 +++++++++++++++++++++++++ curd.html | 1238 ++++++++++++++++++++++++++++++++++++++++++++ database.html | 779 ++++++++++++++++++++++++++++ database.md | 31 -- development.html | 707 +++++++++++++++++++++++++ getting-started.md | 0 gitbook | 1 + index.html | 704 +++++++++++++++++++++++++ logger.png | Bin 0 -> 66982 bytes models.html | 747 ++++++++++++++++++++++++++ 14 files changed, 6466 insertions(+), 66 deletions(-) delete mode 100644 README.md delete mode 100644 SUMMARY.md create mode 100644 advanced.html create mode 100644 associations.html create mode 100644 callbacks.html create mode 100644 curd.html create mode 100644 database.html delete mode 100644 database.md create mode 100644 development.html delete mode 100644 getting-started.md create mode 160000 gitbook create mode 100644 index.html create mode 100644 logger.png create mode 100644 models.html diff --git a/README.md b/README.md deleted file mode 100644 index 4409686b..00000000 --- a/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# GORM - -This is GORM diff --git a/SUMMARY.md b/SUMMARY.md deleted file mode 100644 index 8a0a43d5..00000000 --- a/SUMMARY.md +++ /dev/null @@ -1,32 +0,0 @@ -# Summary - -* [Getting Started](getting-started.md) -* [Database](database.md) - * [Connecting to a Database](#connecting-to-a-database) - * [Migration]() - * [Schema]() -* [Models]() - * [Model Defination]() - * [Naming Conventions & Overriding]() - * [Associations]() - * [Belongs To]() - * [Has One]() - * [Has Many]() - * [Many To Many]() - * [Polymorphism]() - * [Association Mode]() -* [CRUD: Reading and Writing Data]() - * [Create]() - * [Query]() - * [Preloading (Eager Loading)]() - * [Update]() - * [Delete / Soft Delete]() - * [Callbacks]() -* [Advanced Usage]() - * [Error Handling]() - * [Transactions]() - * [Raw SQL & SQL Builder]() - * [Composite Primary Key]() - * [Overriding Logger]() -* [Development]() - * [Write Plugins]() diff --git a/advanced.html b/advanced.html new file mode 100644 index 00000000..d4445759 --- /dev/null +++ b/advanced.html @@ -0,0 +1,786 @@ + + + + Advanced Usage · GORM Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+ +
+ +
+ + + + + + +
+
+
+ +

Advanced Usage

+ + + +

Error Handling

+
query := db.Where("name = ?", "jinzhu").First(&user)
+query := db.First(&user).Limit(10).Find(&users)
+// query.Error will return the last happened error
+
+// So you could do error handing in your application like this:
+if err := db.Where("name = ?", "jinzhu").First(&user).Error; err != nil {
+    // error handling...
+}
+
+// RecordNotFound
+// If no record found when you query data, gorm will return RecordNotFound error, you could check it like this:
+db.Where("name = ?", "hello world").First(&User{}).Error == gorm.RecordNotFound
+// Or use the shortcut method
+db.Where("name = ?", "hello world").First(&user).RecordNotFound()
+
+if db.Model(&user).Related(&credit_card).RecordNotFound() {
+    // no credit card found error handling
+}
+
+

Transactions

+

To perform a set of operations within a transaction, the general flow is as below. +The database handle returned from db.Begin() should be used for all operations within the transaction. +(Note that all individual save and delete operations are run in a transaction by default.)

+
// begin
+tx := db.Begin()
+
+// do some database operations (use 'tx' from this point, not 'db')
+tx.Create(...)
+...
+
+// rollback in case of error
+tx.Rollback()
+
+// Or commit if all is ok
+tx.Commit()
+
+

A Specific Example

+
func CreateAnimals(db *gorm.DB) err {
+  tx := db.Begin()
+  // Note the use of tx as the database handle once you are within a transaction
+
+  if err := tx.Create(&Animal{Name: "Giraffe"}).Error; err != nil {
+     tx.Rollback()
+     return err
+  }
+
+  if err := tx.Create(&Animal{Name: "Lion"}).Error; err != nil {
+     tx.Rollback()
+     return err
+  }
+
+  tx.Commit()
+  return nil
+}
+
+

Raw SQL

+
db.Exec("DROP TABLE users;")
+db.Exec("UPDATE orders SET shipped_at=? WHERE id IN (?)", time.Now, []int64{11,22,33})
+
+

Row & Rows

+

It is even possible to get query result as *sql.Row or *sql.Rows

+
row := db.Table("users").Where("name = ?", "jinzhu").Select("name, age").Row() // (*sql.Row)
+row.Scan(&name, &age)
+
+rows, err := db.Model(&User{}).Where("name = ?", "jinzhu").Select("name, age, email").Rows() // (*sql.Rows, error)
+defer rows.Close()
+for rows.Next() {
+    ...
+    rows.Scan(&name, &age, &email)
+    ...
+}
+
+// Raw SQL
+rows, err := db.Raw("select name, age, email from users where name = ?", "jinzhu").Rows() // (*sql.Rows, error)
+defer rows.Close()
+for rows.Next() {
+    ...
+    rows.Scan(&name, &age, &email)
+    ...
+}
+
+

Scan Rows

+
rows, err := db.Model(&User{}).Where("name = ?", "jinzhu").Select("name, age, email").Rows() // (*sql.Rows, error)
+defer rows.Close()
+
+for rows.Next() {
+  var user User
+  db.ScanRows(rows, &user)
+  // do something
+}
+
+

Composite Primary Key

+
type Product struct {
+    ID           string `gorm:"primary_key"`
+    LanguageCode string `gorm:"primary_key"`
+}
+
+

Logger

+

Gorm has built-in logger support

+
// Enable Logger
+db.LogMode(true)
+
+// Diable Logger
+db.LogMode(false)
+
+// Debug a single operation
+db.Debug().Where("name = ?", "jinzhu").First(&User{})
+
+

logger

+

Customize Logger

+
// Refer gorm's default logger for how to: https://github.com/jinzhu/gorm/blob/master/logger.go#files
+db.SetLogger(gorm.Logger{revel.TRACE})
+db.SetLogger(log.New(os.Stdout, "\r\n", 0))
+
+ + +
+
+
+ +
+ + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/associations.html b/associations.html new file mode 100644 index 00000000..3a0283e4 --- /dev/null +++ b/associations.html @@ -0,0 +1,787 @@ + + + + Associations · GORM Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+ +
+ +
+ + + + + + +
+
+
+ +

Associations

+ + + +

Belongs To

+
// User belongs to a profile, ProfileID is the foreign key
+type User struct {
+  gorm.Model
+  Profile   Profile
+  ProfileID int
+}
+
+type Profile struct {
+  gorm.Model
+  Name   string
+}
+
+db.Model(&user).Related(&profile)
+//// SELECT * FROM profiles WHERE id = 111; // 111 is user's foreign key ProfileID
+
+

Has One

+
// User has one CreditCard, UserID is the foreign key
+type User struct {
+    gorm.Model
+    CreditCard   CreditCard
+}
+
+type CreditCard struct {
+    gorm.Model
+    UserID   uint
+    Number   string
+}
+
+var card CreditCard
+db.Model(&user).Related(&card, "CreditCard")
+//// SELECT * FROM credit_cards WHERE user_id = 123; // 123 is user's primary key
+// CreditCard is user's field name, it means get user's CreditCard relations and fill it into variable card
+// If the field name is same as the variable's type name, like above example, it could be omitted, like:
+db.Model(&user).Related(&card)
+
+

Has Many

+
// User has many emails, UserID is the foreign key
+type User struct {
+    gorm.Model
+    Emails   []Email
+}
+
+type Email struct {
+    gorm.Model
+    Email   string
+    UserID  uint
+}
+
+db.Model(&user).Related(&emails)
+//// SELECT * FROM emails WHERE user_id = 111; // 111 is user's primary key
+
+

Many To Many

+
// User has and belongs to many languages, use `user_languages` as join table
+type User struct {
+    gorm.Model
+    Languages         []Language `gorm:"many2many:user_languages;"`
+}
+
+type Language struct {
+    gorm.Model
+    Name string
+}
+
+db.Model(&user).Related(&languages)
+//// SELECT * FROM "languages" INNER JOIN "user_languages" ON "user_languages"."language_id" = "languages"."id" WHERE "user_languages"."user_id" = 111
+
+

Polymorphism

+

Supports polymorphic has-many and has-one associations.

+
  type Cat struct {
+    Id    int
+    Name  string
+    Toy   Toy `gorm:"polymorphic:Owner;"`
+  }
+
+  type Dog struct {
+    Id   int
+    Name string
+    Toy  Toy `gorm:"polymorphic:Owner;"`
+  }
+
+  type Toy struct {
+    Id        int
+    Name      string
+    OwnerId   int
+    OwnerType string
+  }
+
+

Note: polymorphic belongs-to and many-to-many are explicitly NOT supported, and will throw errors.

+

Association Mode

+

Association Mode contains some helper methods to handle relationship things easily.

+
// Start Association Mode
+var user User
+db.Model(&user).Association("Languages")
+// `user` is the source, it need to be a valid record (contains primary key)
+// `Languages` is source's field name for a relationship.
+// If those conditions not matched, will return an error, check it with:
+// db.Model(&user).Association("Languages").Error
+
+
+// Query - Find out all related associations
+db.Model(&user).Association("Languages").Find(&languages)
+
+
+// Append - Append new associations for many2many, has_many, will replace current association for has_one, belongs_to
+db.Model(&user).Association("Languages").Append([]Language{languageZH, languageEN})
+db.Model(&user).Association("Languages").Append(Language{Name: "DE"})
+
+
+// Delete - Remove relationship between source & passed arguments, won't delete those arguments
+db.Model(&user).Association("Languages").Delete([]Language{languageZH, languageEN})
+db.Model(&user).Association("Languages").Delete(languageZH, languageEN)
+
+
+// Replace - Replace current associations with new one
+db.Model(&user).Association("Languages").Replace([]Language{languageZH, languageEN})
+db.Model(&user).Association("Languages").Replace(Language{Name: "DE"}, languageEN)
+
+
+// Count - Return the count of current associations
+db.Model(&user).Association("Languages").Count()
+
+
+// Clear - Remove relationship between source & current associations, won't delete those associations
+db.Model(&user).Association("Languages").Clear()
+
+ + +
+
+
+ +
+ + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/callbacks.html b/callbacks.html new file mode 100644 index 00000000..94dfccf2 --- /dev/null +++ b/callbacks.html @@ -0,0 +1,717 @@ + + + + Callbacks · GORM Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+ +
+ +
+ + + + + + +
+
+
+ +

Callbacks

+ + + +

Callbacks are methods defined on the pointer of struct. +If any callback returns an error, gorm will stop future operations and rollback all changes.

+

Here is the list of all available callbacks: +(listed in the same order in which they will get called during the respective operations)

+

Creating An Object

+
BeforeSave
+BeforeCreate
+// save before associations
+// save self
+// save after associations
+AfterCreate
+AfterSave
+
+

Updating An Object

+
BeforeSave
+BeforeUpdate
+// save before associations
+// save self
+// save after associations
+AfterUpdate
+AfterSave
+
+

Destroying An Object

+
BeforeDelete
+// delete self
+AfterDelete
+
+

After Find

+
// load data from database
+AfterFind
+
+

Example

+
func (u *User) BeforeUpdate() (err error) {
+    if u.readonly() {
+        err = errors.New("read only user")
+    }
+    return
+}
+
+// Rollback the insertion if user's id greater than 1000
+func (u *User) AfterCreate() (err error) {
+    if (u.Id > 1000) {
+        err = errors.New("user id is already greater than 1000")
+    }
+    return
+}
+
+

Save/delete operations in gorm are running in a transaction. +Changes made in that transaction are not visible unless it is commited. +So if you want to use those changes in your callbacks, you need to run your SQL in the same transaction. +For this Gorm supports passing transactions to callbacks like this:

+
func (u *User) AfterCreate(tx *gorm.DB) (err error) {
+    tx.Model(u).Update("role", "admin")
+    return
+}
+
+ + +
+
+
+ +
+ + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/curd.html b/curd.html new file mode 100644 index 00000000..06f4838b --- /dev/null +++ b/curd.html @@ -0,0 +1,1238 @@ + + + + CRUD: Reading and Writing Data · GORM Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+ +
+ +
+ + + + + + +
+
+
+ +

CRUD: Reading and Writing Data

+ + + +

Create

+

Create Record

+
user := User{Name: "Jinzhu", Age: 18, Birthday: time.Now()}
+
+db.NewRecord(user) // => returns `true` as primary key is blank
+
+db.Create(&user)
+
+db.NewRecord(user) // => return `false` after `user` created
+
+// Associations will be inserted automatically when save the record
+user := User{
+    Name:            "jinzhu",
+    BillingAddress:  Address{Address1: "Billing Address - Address 1"},
+    ShippingAddress: Address{Address1: "Shipping Address - Address 1"},
+    Emails:          []Email{{Email: "jinzhu@example.com"}, {Email: "jinzhu-2@example@example.com"}},
+    Languages:       []Language{{Name: "ZH"}, {Name: "EN"}},
+}
+
+db.Create(&user)
+//// BEGIN TRANSACTION;
+//// INSERT INTO "addresses" (address1) VALUES ("Billing Address - Address 1");
+//// INSERT INTO "addresses" (address1) VALUES ("Shipping Address - Address 1");
+//// INSERT INTO "users" (name,billing_address_id,shipping_address_id) VALUES ("jinzhu", 1, 2);
+//// INSERT INTO "emails" (user_id,email) VALUES (111, "jinzhu@example.com");
+//// INSERT INTO "emails" (user_id,email) VALUES (111, "jinzhu-2@example.com");
+//// INSERT INTO "languages" ("name") VALUES ('ZH');
+//// INSERT INTO user_languages ("user_id","language_id") VALUES (111, 1);
+//// INSERT INTO "languages" ("name") VALUES ('EN');
+//// INSERT INTO user_languages ("user_id","language_id") VALUES (111, 2);
+//// COMMIT;
+
+

Create With Associations

+

Refer Associations for more details

+

Default Values

+

You could defined default value in the sql tag, then the generated creating SQL will ignore these fields that including default value and its value is blank, and after inserted the record into databae, gorm will load those fields's value from database.

+
type Animal struct {
+    ID   int64
+    Name string `sql:"default:'galeone'"`
+    Age  int64
+}
+
+var animal = Animal{Age: 99, Name: ""}
+db.Create(&animal)
+// INSERT INTO animals("age") values('99');
+// SELECT name from animals WHERE ID=111; // the returning primary key is 111
+// animal.Name => 'galeone'
+
+

Setting Primary Key In Callbacks

+

If you want to set primary key in BeforeCreate callback, you could use scope.SetColumn, for example:

+
func (user *User) BeforeCreate(scope *gorm.Scope) error {
+  scope.SetColumn("ID", uuid.New())
+  return nil
+}
+
+

Extra Creating option

+
// Add extra SQL option for inserting SQL
+db.Set("gorm:insert_option", "ON CONFLICT").Create(&product)
+// INSERT INTO products (name, code) VALUES ("name", "code") ON CONFLICT;
+
+

Query

+
// Get the first record
+db.First(&user)
+//// SELECT * FROM users ORDER BY id LIMIT 1;
+
+// Get the last record
+db.Last(&user)
+//// SELECT * FROM users ORDER BY id DESC LIMIT 1;
+
+// Get all records
+db.Find(&users)
+//// SELECT * FROM users;
+
+// Get record with primary key
+db.First(&user, 10)
+//// SELECT * FROM users WHERE id = 10;
+
+

Query With Where (Plain SQL)

+
// Get the first matched record
+db.Where("name = ?", "jinzhu").First(&user)
+//// SELECT * FROM users WHERE name = 'jinzhu' limit 1;
+
+// Get all matched records
+db.Where("name = ?", "jinzhu").Find(&users)
+//// SELECT * FROM users WHERE name = 'jinzhu';
+
+db.Where("name <> ?", "jinzhu").Find(&users)
+
+// IN
+db.Where("name in (?)", []string{"jinzhu", "jinzhu 2"}).Find(&users)
+
+// LIKE
+db.Where("name LIKE ?", "%jin%").Find(&users)
+
+// AND
+db.Where("name = ? and age >= ?", "jinzhu", "22").Find(&users)
+
+// Time
+db.Where("updated_at > ?", lastWeek).Find(&users)
+
+db.Where("created_at BETWEEN ? AND ?", lastWeek, today).Find(&users)
+
+

Query With Where (Struct & Map)

+
// Struct
+db.Where(&User{Name: "jinzhu", Age: 20}).First(&user)
+//// SELECT * FROM users WHERE name = "jinzhu" AND age = 20 LIMIT 1;
+
+// Map
+db.Where(map[string]interface{}{"name": "jinzhu", "age": 20}).Find(&users)
+//// SELECT * FROM users WHERE name = "jinzhu" AND age = 20;
+
+// Slice of primary keys
+db.Where([]int64{20, 21, 22}).Find(&users)
+//// SELECT * FROM users WHERE id IN (20, 21, 22);
+
+

Query With Not

+
db.Not("name", "jinzhu").First(&user)
+//// SELECT * FROM users WHERE name <> "jinzhu" LIMIT 1;
+
+// Not In
+db.Not("name", []string{"jinzhu", "jinzhu 2"}).Find(&users)
+//// SELECT * FROM users WHERE name NOT IN ("jinzhu", "jinzhu 2");
+
+// Not In slice of primary keys
+db.Not([]int64{1,2,3}).First(&user)
+//// SELECT * FROM users WHERE id NOT IN (1,2,3);
+
+db.Not([]int64{}).First(&user)
+//// SELECT * FROM users;
+
+// Plain SQL
+db.Not("name = ?", "jinzhu").First(&user)
+//// SELECT * FROM users WHERE NOT(name = "jinzhu");
+
+// Struct
+db.Not(User{Name: "jinzhu"}).First(&user)
+//// SELECT * FROM users WHERE name <> "jinzhu";
+
+

Query With Inline Condition

+
// Get by primary key
+db.First(&user, 23)
+//// SELECT * FROM users WHERE id = 23 LIMIT 1;
+
+// Plain SQL
+db.Find(&user, "name = ?", "jinzhu")
+//// SELECT * FROM users WHERE name = "jinzhu";
+
+db.Find(&users, "name <> ? AND age > ?", "jinzhu", 20)
+//// SELECT * FROM users WHERE name <> "jinzhu" AND age > 20;
+
+// Struct
+db.Find(&users, User{Age: 20})
+//// SELECT * FROM users WHERE age = 20;
+
+// Map
+db.Find(&users, map[string]interface{}{"age": 20})
+//// SELECT * FROM users WHERE age = 20;
+
+

Query With Or

+
db.Where("role = ?", "admin").Or("role = ?", "super_admin").Find(&users)
+//// SELECT * FROM users WHERE role = 'admin' OR role = 'super_admin';
+
+// Struct
+db.Where("name = 'jinzhu'").Or(User{Name: "jinzhu 2"}).Find(&users)
+//// SELECT * FROM users WHERE name = 'jinzhu' OR name = 'jinzhu 2';
+
+// Map
+db.Where("name = 'jinzhu'").Or(map[string]interface{}{"name": "jinzhu 2"}).Find(&users)
+
+

Query Chains

+

Gorm has a chainable API, you could use it like this

+
db.Where("name <> ?","jinzhu").Where("age >= ? and role <> ?",20,"admin").Find(&users)
+//// SELECT * FROM users WHERE name <> 'jinzhu' AND age >= 20 AND role <> 'admin';
+
+db.Where("role = ?", "admin").Or("role = ?", "super_admin").Not("name = ?", "jinzhu").Find(&users)
+
+

Extra Querying option

+
// Add extra SQL option for selecting SQL
+db.Set("gorm:query_option", "FOR UPDATE").First(&user, 10)
+//// SELECT * FROM users WHERE id = 10 FOR UPDATE;
+
+

FirstOrInit

+

Get the first matched record, or initialize a record with search conditions.

+
// Unfound
+db.FirstOrInit(&user, User{Name: "non_existing"})
+//// user -> User{Name: "non_existing"}
+
+// Found
+db.Where(User{Name: "Jinzhu"}).FirstOrInit(&user)
+//// user -> User{Id: 111, Name: "Jinzhu", Age: 20}
+db.FirstOrInit(&user, map[string]interface{}{"name": "jinzhu"})
+//// user -> User{Id: 111, Name: "Jinzhu", Age: 20}
+
+

Attrs

+

Ignore some values when searching, but use them to initialize the struct if record is not found.

+
// Unfound
+db.Where(User{Name: "non_existing"}).Attrs(User{Age: 20}).FirstOrInit(&user)
+//// SELECT * FROM USERS WHERE name = 'non_existing';
+//// user -> User{Name: "non_existing", Age: 20}
+
+db.Where(User{Name: "noexisting_user"}).Attrs("age", 20).FirstOrInit(&user)
+//// SELECT * FROM USERS WHERE name = 'non_existing';
+//// user -> User{Name: "non_existing", Age: 20}
+
+// Found
+db.Where(User{Name: "Jinzhu"}).Attrs(User{Age: 30}).FirstOrInit(&user)
+//// SELECT * FROM USERS WHERE name = jinzhu';
+//// user -> User{Id: 111, Name: "Jinzhu", Age: 20}
+
+

Assign

+

Ignore some values when searching, but assign it to the result regardless it is found or not.

+
// Unfound
+db.Where(User{Name: "non_existing"}).Assign(User{Age: 20}).FirstOrInit(&user)
+//// user -> User{Name: "non_existing", Age: 20}
+
+// Found
+db.Where(User{Name: "Jinzhu"}).Assign(User{Age: 30}).FirstOrInit(&user)
+//// SELECT * FROM USERS WHERE name = jinzhu';
+//// user -> User{Id: 111, Name: "Jinzhu", Age: 30}
+
+

FirstOrCreate

+

Get the first matched record, or create with search conditions.

+
// Unfound
+db.FirstOrCreate(&user, User{Name: "non_existing"})
+//// INSERT INTO "users" (name) VALUES ("non_existing");
+//// user -> User{Id: 112, Name: "non_existing"}
+
+// Found
+db.Where(User{Name: "Jinzhu"}).FirstOrCreate(&user)
+//// user -> User{Id: 111, Name: "Jinzhu"}
+
+

Attrs

+

Ignore some values when searching, but use them to create the struct if record is not found. like FirstOrInit

+
// Unfound
+db.Where(User{Name: "non_existing"}).Attrs(User{Age: 20}).FirstOrCreate(&user)
+//// SELECT * FROM users WHERE name = 'non_existing';
+//// INSERT INTO "users" (name, age) VALUES ("non_existing", 20);
+//// user -> User{Id: 112, Name: "non_existing", Age: 20}
+
+// Found
+db.Where(User{Name: "jinzhu"}).Attrs(User{Age: 30}).FirstOrCreate(&user)
+//// SELECT * FROM users WHERE name = 'jinzhu';
+//// user -> User{Id: 111, Name: "jinzhu", Age: 20}
+
+

Assign

+

Ignore some values when searching, but assign it to the record regardless it is found or not, then save back to database. like FirstOrInit

+
// Unfound
+db.Where(User{Name: "non_existing"}).Assign(User{Age: 20}).FirstOrCreate(&user)
+//// SELECT * FROM users WHERE name = 'non_existing';
+//// INSERT INTO "users" (name, age) VALUES ("non_existing", 20);
+//// user -> User{Id: 112, Name: "non_existing", Age: 20}
+
+// Found
+db.Where(User{Name: "jinzhu"}).Assign(User{Age: 30}).FirstOrCreate(&user)
+//// SELECT * FROM users WHERE name = 'jinzhu';
+//// UPDATE users SET age=30 WHERE id = 111;
+//// user -> User{Id: 111, Name: "jinzhu", Age: 30}
+
+

Select

+
db.Select("name, age").Find(&users)
+//// SELECT name, age FROM users;
+
+db.Select([]string{"name", "age"}).Find(&users)
+//// SELECT name, age FROM users;
+
+db.Table("users").Select("COALESCE(age,?)", 42).Rows()
+//// SELECT COALESCE(age,'42') FROM users;
+
+

Order

+
db.Order("age desc, name").Find(&users)
+//// SELECT * FROM users ORDER BY age desc, name;
+
+// Multiple orders
+db.Order("age desc").Order("name").Find(&users)
+//// SELECT * FROM users ORDER BY age desc, name;
+
+// ReOrder
+db.Order("age desc").Find(&users1).Order("age", true).Find(&users2)
+//// SELECT * FROM users ORDER BY age desc; (users1)
+//// SELECT * FROM users ORDER BY age; (users2)
+
+

Limit

+
db.Limit(3).Find(&users)
+//// SELECT * FROM users LIMIT 3;
+
+// Cancel limit condition with -1
+db.Limit(10).Find(&users1).Limit(-1).Find(&users2)
+//// SELECT * FROM users LIMIT 10; (users1)
+//// SELECT * FROM users; (users2)
+
+

Offset

+
db.Offset(3).Find(&users)
+//// SELECT * FROM users OFFSET 3;
+
+// Cancel offset condition with -1
+db.Offset(10).Find(&users1).Offset(-1).Find(&users2)
+//// SELECT * FROM users OFFSET 10; (users1)
+//// SELECT * FROM users; (users2)
+
+

Count

+
db.Where("name = ?", "jinzhu").Or("name = ?", "jinzhu 2").Find(&users).Count(&count)
+//// SELECT * from USERS WHERE name = 'jinzhu' OR name = 'jinzhu 2'; (users)
+//// SELECT count(*) FROM users WHERE name = 'jinzhu' OR name = 'jinzhu 2'; (count)
+
+db.Model(&User{}).Where("name = ?", "jinzhu").Count(&count)
+//// SELECT count(*) FROM users WHERE name = 'jinzhu'; (count)
+
+db.Table("deleted_users").Count(&count)
+//// SELECT count(*) FROM deleted_users;
+
+

Group & Having

+
rows, err := db.Table("orders").Select("date(created_at) as date, sum(amount) as total").Group("date(created_at)").Rows()
+for rows.Next() {
+    ...
+}
+
+rows, err := db.Table("orders").Select("date(created_at) as date, sum(amount) as total").Group("date(created_at)").Having("sum(amount) > ?", 100).Rows()
+for rows.Next() {
+    ...
+}
+
+type Result struct {
+    Date  time.Time
+    Total int64
+}
+db.Table("orders").Select("date(created_at) as date, sum(amount) as total").Group("date(created_at)").Having("sum(amount) > ?", 100).Scan(&results)
+
+

Joins

+
rows, err := db.Table("users").Select("users.name, emails.email").Joins("left join emails on emails.user_id = users.id").Rows()
+for rows.Next() {
+    ...
+}
+
+db.Table("users").Select("users.name, emails.email").Joins("left join emails on emails.user_id = users.id").Scan(&results)
+
+// multiple joins with parameter
+db.Joins("JOIN emails ON emails.user_id = users.id AND emails.email = ?", "jinzhu@example.org").Joins("JOIN credit_cards ON credit_cards.user_id = users.id").Where("credit_cards.number = ?", "411111111111").Find(&user)
+
+

Pluck

+

Get selected attributes as map

+
var ages []int64
+db.Find(&users).Pluck("age", &ages)
+
+var names []string
+db.Model(&User{}).Pluck("name", &names)
+
+db.Table("deleted_users").Pluck("name", &names)
+
+// Requesting more than one column? Do it like this:
+db.Select("name, age").Find(&users)
+
+

Scan

+

Scan results into another struct.

+
type Result struct {
+    Name string
+    Age  int
+}
+
+var result Result
+db.Table("users").Select("name, age").Where("name = ?", 3).Scan(&result)
+
+// Raw SQL
+db.Raw("SELECT name, age FROM users WHERE name = ?", 3).Scan(&result)
+
+

Scopes

+
func AmountGreaterThan1000(db *gorm.DB) *gorm.DB {
+    return db.Where("amount > ?", 1000)
+}
+
+func PaidWithCreditCard(db *gorm.DB) *gorm.DB {
+    return db.Where("pay_mode_sign = ?", "C")
+}
+
+func PaidWithCod(db *gorm.DB) *gorm.DB {
+    return db.Where("pay_mode_sign = ?", "C")
+}
+
+func OrderStatus(status []string) func (db *gorm.DB) *gorm.DB {
+    return func (db *gorm.DB) *gorm.DB {
+        return db.Scopes(AmountGreaterThan1000).Where("status in (?)", status)
+    }
+}
+
+db.Scopes(AmountGreaterThan1000, PaidWithCreditCard).Find(&orders)
+// Find all credit card orders and amount greater than 1000
+
+db.Scopes(AmountGreaterThan1000, PaidWithCod).Find(&orders)
+// Find all COD orders and amount greater than 1000
+
+db.Scopes(OrderStatus([]string{"paid", "shipped"})).Find(&orders)
+// Find all paid, shipped orders
+
+

Specifying The Table Name

+
// Create `deleted_users` table with struct User's definition
+db.Table("deleted_users").CreateTable(&User{})
+
+var deleted_users []User
+db.Table("deleted_users").Find(&deleted_users)
+//// SELECT * FROM deleted_users;
+
+db.Table("deleted_users").Where("name = ?", "jinzhu").Delete()
+//// DELETE FROM deleted_users WHERE name = 'jinzhu';
+
+

Update

+

Update All Fields

+

Save will include all fields when perform the Updating SQL, even it is not changed

+
db.First(&user)
+
+user.Name = "jinzhu 2"
+user.Age = 100
+db.Save(&user)
+
+//// UPDATE users SET name='jinzhu 2', age=100, birthday='2016-01-01', updated_at = '2013-11-17 21:34:10' WHERE id=111;
+
+

Update Changed Fields

+

If you only want to update changed Fields, you could use Update, Updates

+
// Update single attribute if it is changed
+db.Model(&user).Update("name", "hello")
+//// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111;
+
+// Update single attribute with combined conditions
+db.Model(&user).Where("active = ?", true).Update("name", "hello")
+//// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111 AND active=true;
+
+
+// Update multiple attributes with `map`, will only update those changed fields
+db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})
+//// UPDATE users SET name='hello', age=18, actived=false, updated_at='2013-11-17 21:34:10' WHERE id=111;
+
+// Update multiple attributes with `struct`, will only update those changed & non blank fields
+db.Model(&user).Updates(User{Name: "hello", Age: 18})
+//// UPDATE users SET name='hello', age=18, updated_at = '2013-11-17 21:34:10' WHERE id = 111;
+
+// WARNING when update with struct, GORM will only update those fields that with non blank value
+// For below Update, nothing will be updated as "", 0, false are blank values of their types
+db.Model(&user).Updates(User{Name: "", Age: 0, Actived: false})
+
+

Update Selected Fields

+

If you only want to update or ignore some fields when updating, you could use Select, Omit

+
db.Model(&user).Select("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})
+//// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111;
+
+db.Model(&user).Omit("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})
+//// UPDATE users SET age=18, actived=false, updated_at='2013-11-17 21:34:10' WHERE id=111;
+
+

Update Changed Fields Without Callbacks

+

Updating operations above will invoke BeforeUpdate, AfterUpdate, Update UpdatedAt timestamp, Save Associations callbacks, if you don't call them, you could use UpdateColumn, UpdateColumns

+
// Update single attribute, similar with `Update`
+db.Model(&user).UpdateColumn("name", "hello")
+//// UPDATE users SET name='hello' WHERE id = 111;
+
+// Update multiple attributes, similar with `Updates`
+db.Model(&user).UpdateColumns(User{Name: "hello", Age: 18})
+//// UPDATE users SET name='hello', age=18 WHERE id = 111;
+
+

Batch Updates

+

Callbacks won't run when do batch updates

+
db.Table("users").Where("id IN (?)", []int{10, 11}).Updates(map[string]interface{}{"name": "hello", "age": 18})
+//// UPDATE users SET name='hello', age=18 WHERE id IN (10, 11);
+
+// Update with struct only works with none zero values, or use map[string]interface{}
+db.Model(User{}).Updates(User{Name: "hello", Age: 18})
+//// UPDATE users SET name='hello', age=18;
+
+// Get updated records count with `RowsAffected`
+db.Model(User{}).Updates(User{Name: "hello", Age: 18}).RowsAffected
+
+

Update with SQL Expression

+
DB.Model(&product).Update("price", gorm.Expr("price * ? + ?", 2, 100))
+//// UPDATE "products" SET "price" = price * '2' + '100', "updated_at" = '2013-11-17 21:34:10' WHERE "id" = '2';
+
+DB.Model(&product).Updates(map[string]interface{}{"price": gorm.Expr("price * ? + ?", 2, 100)})
+//// UPDATE "products" SET "price" = price * '2' + '100', "updated_at" = '2013-11-17 21:34:10' WHERE "id" = '2';
+
+DB.Model(&product).UpdateColumn("quantity", gorm.Expr("quantity - ?", 1))
+//// UPDATE "products" SET "quantity" = quantity - 1 WHERE "id" = '2';
+
+DB.Model(&product).Where("quantity > 1").UpdateColumn("quantity", gorm.Expr("quantity - ?", 1))
+//// UPDATE "products" SET "quantity" = quantity - 1 WHERE "id" = '2' AND quantity > 1;
+
+

Change Updating Values In Callbacks

+

If you want to change updating values in callbacks using BeforeUpdate, BeforeSave, you could use scope.SetColumn, for example:

+
func (user *User) BeforeSave(scope *gorm.Scope) (err error) {
+  if pw, err := bcrypt.GenerateFromPassword(user.Password, 0); err == nil {
+    scope.SetColumn("EncryptedPassword", pw)
+  }
+}
+
+

Extra Updating option

+
// Add extra SQL option for updating SQL
+db.Model(&user).Set("gorm:update_option", "OPTION (OPTIMIZE FOR UNKNOWN)").Update("name, "hello")
+//// UPDATE users SET name='hello', updated_at = '2013-11-17 21:34:10' WHERE id=111 OPTION (OPTIMIZE FOR UNKNOWN);
+
+

Delete

+
// Delete an existing record
+db.Delete(&email)
+//// DELETE from emails where id=10;
+
+// Add extra SQL option for deleting SQL
+db.Set("gorm:delete_option", "OPTION (OPTIMIZE FOR UNKNOWN)").Delete(&email)
+//// DELETE from emails where id=10 OPTION (OPTIMIZE FOR UNKNOWN);
+
+

Batch Delete

+
db.Where("email LIKE ?", "%jinzhu%").Delete(Email{})
+//// DELETE from emails where email LIKE "%jinhu%";
+
+

Soft Delete

+

If struct has DeletedAt field, it will get soft delete ability automatically! +Then it won't be deleted from database permanently when call Delete.

+
db.Delete(&user)
+//// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE id = 111;
+
+// Batch Delete
+db.Where("age = ?", 20).Delete(&User{})
+//// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE age = 20;
+
+// Soft deleted records will be ignored when query them
+db.Where("age = 20").Find(&user)
+//// SELECT * FROM users WHERE age = 20 AND deleted_at IS NULL;
+
+// Find soft deleted records with Unscoped
+db.Unscoped().Where("age = 20").Find(&users)
+//// SELECT * FROM users WHERE age = 20;
+
+// Delete record permanently with Unscoped
+db.Unscoped().Delete(&order)
+//// DELETE FROM orders WHERE id=10;
+
+ + +
+
+
+ +
+ + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/database.html b/database.html new file mode 100644 index 00000000..bb008130 --- /dev/null +++ b/database.html @@ -0,0 +1,779 @@ + + + + Database · GORM Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+ +
+ +
+ + + + + + +
+
+
+ +

Database

+ + + +

Connecting to a database

+

MySQL

+

NOTE don't forgot params parseTime to handle data type time.Time, more support parameters

+
import (
+    "github.com/jinzhu/gorm"
+    _ "github.com/go-sql-driver/mysql"
+)
+func main() {
+  db, err := gorm.Open("mysql", "user:password@/dbname?charset=utf8&parseTime=True&loc=Local")
+}
+
+

PostgreSQL

+
import (
+    "github.com/jinzhu/gorm"
+    _ "github.com/lib/pq"
+)
+func main() {
+  db, err := gorm.Open("postgres", "user=gorm dbname=gorm sslmode=disable")
+}
+
+

Sqlite3

+
import (
+    "github.com/jinzhu/gorm"
+    _ "github.com/mattn/go-sqlite3"
+)
+func main() {
+  db, err := gorm.Open("sqlite3", "/tmp/gorm.db")
+}
+
+

Write Dialect for unsupported databases

+

GORM officially support above databases, for unsupported databaes, you could write a dialect for that.

+

Refer: https://github.com/jinzhu/gorm/blob/master/dialect.go

+

Generic database object *sql.DB

+

*sql.DB

+
// Get generic database object *sql.DB to use its functions
+db.DB()
+
+// Connection Pool
+db.DB().SetMaxIdleConns(10)
+db.DB().SetMaxOpenConns(100)
+
+  // Ping
+db.DB().Ping()
+
+

Migration

+ +

Auto Migration

+

Automatically migrate your schema, to keep your schema update to date

+

WARNING AutoMigrate will ONLY create tables, columns and indexes if doesn't exist, +WON'T change existing column's type or delete unused columns to protect your data

+
db.AutoMigrate(&User{})
+
+db.AutoMigrate(&User{}, &Product{}, &Order{})
+
+// Add table suffix when create tables
+db.Set("gorm:table_options", "ENGINE=InnoDB").AutoMigrate(&User{})
+
+

Has Table

+
// Check if model `User`'s table has been created or not
+db.HasTable(&User{})
+
+// Check table `users` exists or not
+db.HasTable("users")
+
+

Create Table

+
db.CreateTable(&User{})
+
+db.Set("gorm:table_options", "ENGINE=InnoDB").CreateTable(&User{})
+// will append "ENGINE=InnoDB" to the SQL statement when creating table `users`
+
+

Drop table

+
db.DropTable(&User{})
+
+

ModifyColumn

+

Change column's type

+
// change column description's data type to `text` for model `User`'s table
+db.Model(&User{}).ModifyColumn("description", "text")
+
+

DropColumn

+
db.Model(&User{}).DropColumn("description")
+
+

Add Foreign Key

+
// Add foreign key
+// 1st param : foreignkey field
+// 2nd param : destination table(id)
+// 3rd param : ONDELETE
+// 4th param : ONUPDATE
+db.Model(&User{}).AddForeignKey("city_id", "cities(id)", "RESTRICT", "RESTRICT")
+
+

Indexes

+
// Add index
+db.Model(&User{}).AddIndex("idx_user_name", "name")
+
+// Multiple column index
+db.Model(&User{}).AddIndex("idx_user_name_age", "name", "age")
+
+// Add unique index
+db.Model(&User{}).AddUniqueIndex("idx_user_name", "name")
+
+// Multiple column unique index
+db.Model(&User{}).AddUniqueIndex("idx_user_name_age", "name", "age")
+
+// Remove index
+db.Model(&User{}).RemoveIndex("idx_user_name")
+
+ + +
+
+
+ +
+ + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/database.md b/database.md deleted file mode 100644 index f32e1c97..00000000 --- a/database.md +++ /dev/null @@ -1,31 +0,0 @@ -## Connecting To A Database - -```go -import ( - "github.com/jinzhu/gorm" - _ "github.com/lib/pq" - _ "github.com/go-sql-driver/mysql" - _ "github.com/mattn/go-sqlite3" -) - -func init() { - db, err := gorm.Open("postgres", "user=gorm dbname=gorm sslmode=disable") - // db, err := gorm.Open("mysql", "user:password@/dbname?charset=utf8&parseTime=True&loc=Local") - // db, err := gorm.Open("sqlite3", "/tmp/gorm.db") - - // You can also use an existing database connection handle - // dbSql, _ := sql.Open("postgres", "user=gorm dbname=gorm sslmode=disable") - // db, _ := gorm.Open("postgres", dbSql) - - // Get database connection handle [*sql.DB](http://golang.org/pkg/database/sql/#DB) - db.DB() - - // Then you could invoke `*sql.DB`'s functions with it - db.DB().Ping() - db.DB().SetMaxIdleConns(10) - db.DB().SetMaxOpenConns(100) - - // Disable table name's pluralization - db.SingularTable(true) -} -``` diff --git a/development.html b/development.html new file mode 100644 index 00000000..77aac966 --- /dev/null +++ b/development.html @@ -0,0 +1,707 @@ + + + + Development · GORM Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+ +
+ +
+ + + + + + +
+
+
+ +

Gorm Development

+ + + +

Architecture

+

The most notable component of Gorm isgorm.DB, which hold database connection. It could be initialized like this:

+
db, err := gorm.Open("postgres", "user=gorm dbname=gorm sslmode=disable")
+

Gorm has chainable API, gorm.DB is the bridge of chains, it save related information and pass it to the next chain.

+

Lets use below code to explain how it works:

+
db.Where("name = ?", "jinzhu").Find(&users)
+
+// equivalent code
+newdb := db.Where("name =?", "jinzhu")
+newdb.Find(&user)
+

newdb is db's clone, in addition, it contains search conditions from the Where method. +Find is a query method, it creates a Scope instance, and pass it as argument to query callbacks.

+

There are four kinds of callbacks corresponds to sql's CURD: create callbacks, update callbacks, query callbacks, delete callbacks.

+

Callbacks

+

Register a new callback

+
func updateCreated(scope *Scope) {
+    if scope.HasColumn("Created") {
+        scope.SetColumn("Created", NowFunc())
+    }
+}
+
+db.Callback().Create().Register("update_created_at", updateCreated)
+// register a callback for Create process
+

Delete an existing callback

+
db.Callback().Create().Remove("gorm:create")
+// delete callback `gorm:create` from Create callbacks
+

Replace an existing callback

+
db.Callback().Create().Replace("gorm:create", newCreateFunction)
+// replace callback `gorm:create` with new function `newCreateFunction` for Create process
+

Register callback orders

+
db.Callback().Create().Before("gorm:create").Register("update_created_at", updateCreated)
+db.Callback().Create().After("gorm:create").Register("update_created_at", updateCreated)
+db.Callback().Query().After("gorm:query").Register("my_plugin:after_query", afterQuery)
+db.Callback().Delete().After("gorm:delete").Register("my_plugin:after_delete", afterDelete)
+db.Callback().Update().Before("gorm:update").Register("my_plugin:before_update", beforeUpdate)
+db.Callback().Create().Before("gorm:create").After("gorm:before_create").Register("my_plugin:before_create", beforeCreate)
+

Callback API

+

Gorm is powered by callbacks, so you could refer below links to learn how to write callbacks

+

Create callbacks

+

Update callbacks

+

Query callbacks

+

Delete callbacks

+

View https://github.com/jinzhu/gorm/blob/master/scope.go for all available API

+ + +
+
+
+ +
+ + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/getting-started.md b/getting-started.md deleted file mode 100644 index e69de29b..00000000 diff --git a/gitbook b/gitbook new file mode 160000 index 00000000..294951f2 --- /dev/null +++ b/gitbook @@ -0,0 +1 @@ +Subproject commit 294951f22af41edbbe758fdcd0903195a332b524 diff --git a/index.html b/index.html new file mode 100644 index 00000000..24813353 --- /dev/null +++ b/index.html @@ -0,0 +1,704 @@ + + + + Getting Started with GORM · GORM Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+ +
+ +
+ + + + + + +
+
+
+ +

GORM

+

The fantastic ORM library for Golang, aims to be developer friendly.

+

wercker status +GoDoc +Join the chat at https://gitter.im/jinzhu/gorm

+

Overview

+
    +
  • Full-Featured ORM (almost)
  • +
  • Chainable API
  • +
  • Auto Migrations
  • +
  • Relations (Has One, Has Many, Belongs To, Many To Many, Polymorphism)
  • +
  • Callbacks (Before/After Create/Save/Update/Delete/Find)
  • +
  • Preloading (eager loading)
  • +
  • Transactions
  • +
  • Embed Anonymous Struct
  • +
  • Soft Deletes
  • +
  • Customizable Logger
  • +
  • Iteration Support via Rows
  • +
  • Every feature comes with tests
  • +
  • Developer Friendly
  • +
+

Install

+
go get -u github.com/jinzhu/gorm
+

Basic Usage

+
type Product struct {
+  gorm.Model
+  Code string
+  Price uint
+}
+
+var db *gorm.DB
+
+func init() {
+  var err error
+  db, err = gorm.Open("sqlite", "test.db")
+}
+
+func main() {
+  db.Create(&Product{Code: "L1212", Price: 1000})
+
+  var product Product
+  db.First(&product, 1) // find product with id 1
+  db.First(&product, "code = ?", "L1212") // find product with code l1212
+
+  db.Model(&product).Update("Price", 2000) // update product's price to 2000
+
+  db.Delete(&product) // delete product
+}
+
+

Author

+

jinzhu

+ +

Contributors

+

https://github.com/jinzhu/gorm/graphs/contributors

+

License

+

Released under the MIT License.

+ + +
+
+
+ +
+ + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/logger.png b/logger.png new file mode 100644 index 0000000000000000000000000000000000000000..8c46588f0ea9b725e5c569c6fbfc5989ca60155b GIT binary patch literal 66982 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 + + + Models · GORM Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+ +
+ +
+ + + + + + +
+
+
+ +

Models

+ + + +

Model Defination

+
type User struct {
+  gorm.Model
+    Birthday     time.Time
+    Age          int
+    Name         string  `sql:"size:255"` // Default size for string is 255, you could reset it with this tag
+    Num          int     `sql:"AUTO_INCREMENT"`
+    IgnoreMe     int `sql:"-"`   // Ignore this field
+}
+
+

Conventions & Overriding Conventions

+

gorm.Model struct

+

Gorm has defined struct gorm.Model, which could be embeded in your models, it will add fields ID, CreatedAt, UpdatedAt, DeletedAt to your model

+
// Model's definition
+type Model struct {
+  ID        uint `gorm:"primary_key"`
+  CreatedAt time.Time
+  UpdatedAt time.Time
+  DeletedAt *time.Time
+}
+
+

Table name is the pluralized version of struct name

+
type User struct {} // default table name is `users`
+
+// set User's table name to be `profiles
+type (User) TableName() string {
+  return "profiles"
+}
+
+func (u User) TableName() string {
+    if u.Role == "admin" {
+        return "admin_users"
+    } else {
+        return "users"
+    }
+}
+
+// Disable table name's pluralization globally
+db.SingularTable(true) // if set this to true, `User`'s default table name will be `user`, table name setted with `TableName` won't be affected
+
+

Column name is the snake case of field's name

+
type User struct {
+  ID uint             // column name will be `id`
+  Name string         // column name will be `name`
+  Birthday time.Time  // column name will be `birthday`
+  CreatedAt time.Time // column name will be `created_at`
+}
+
+type Animal struct {
+    AnimalId    int64     `gorm:"column:beast_id"`         // set column name to `beast_id`
+    Birthday    time.Time `gorm:"column:day_of_the_beast"` // set column name to `day_of_the_beast`
+    Age         int64     `gorm:"column:age_of_the_beast"` // set column name to `age_of_the_beast`
+}
+
+

Field ID as primary key

+
type User struct {
+  ID uint  // field named `ID` is the default primary key for `User`
+  Name string
+}
+
+// your could also use tag `primary_key` to set other field as primary key
+type Animal struct {
+  AnimalId int64 `gorm:"primary_key"` // set AnimalId to be primary key
+  Name     string
+  Age      int64
+}
+
+

Field CreatedAt used to store record's created time

+

Create records having CreatedAt field will set it to current time.

+
db.Create(&user) // will set `CreatedAt` to current time
+
+// To change its value, you could use `Update`
+db.Model(&user).Update("CreatedAt", time.Now())
+
+

Use UpdatedAt used to store record's updated time

+

Save records having UpdatedAt field will set it to current time.

+
db.Save(&user) // will set `UpdatedAt` to current time
+db.Model(&user).Update("name", "jinzhu") // will set `UpdatedAt` to current time
+
+

Use DeletedAt to store record's deleted time if field exists

+

Delete records having DeletedAt field, it won't delete the record from database, but will set field DeletedAt's value to current time.

+ + +
+
+
+ +
+ + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +