diff --git a/documents/README.md b/documents/README.md index 59e9a70d..bdd799b9 100644 --- a/documents/README.md +++ b/documents/README.md @@ -2,62 +2,70 @@ The fantastic ORM library for Golang, aims to be developer friendly. +[![Join the chat at https://gitter.im/jinzhu/gorm](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/jinzhu/gorm?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![wercker status](https://app.wercker.com/status/0cb7bb1039e21b74f8274941428e0921/s/master "wercker status")](https://app.wercker.com/project/bykey/0cb7bb1039e21b74f8274941428e0921) [![GoDoc](https://godoc.org/github.com/jinzhu/gorm?status.svg)](https://godoc.org/github.com/jinzhu/gorm) -[![Join the chat at https://gitter.im/jinzhu/gorm](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/jinzhu/gorm?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) ## Overview * Full-Featured ORM (almost) -* Chainable API -* Auto Migrations -* Relations (Has One, Has Many, Belongs To, Many To Many, Polymorphism) +* Associations (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 +* Composite Primary Key +* SQL Builder +* Auto Migrations +* Logger +* Extendable, write Plugins based on GORM callbacks * Every feature comes with tests * Developer Friendly ## Install -``` +```sh go get -u github.com/jinzhu/gorm ``` -## Upgrading +## Upgrading To V1.0 -[Change Log](changelog.html) +* [CHANGELOG](changelog.html) -## Basic Usage +## Quick Start ```go +package main + +import ( + "github.com/jinzhu/gorm" + _ "github.com/jinzhu/gorm/dialects/sqlite" +) + 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, err := gorm.Open("sqlite", "test.db") + if err != nil { + panic("faield to connect database") + } + + // Create db.Create(&Product{Code: "L1212", Price: 1000}) + // Read 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 + // Update - update product's price to 2000 + db.Model(&product).Update("Price", 2000) - db.Delete(&product) // delete product + // Delete - delete product + db.Delete(&product) } ``` diff --git a/documents/SUMMARY.md b/documents/SUMMARY.md index a7ff82f0..b6a66634 100644 --- a/documents/SUMMARY.md +++ b/documents/SUMMARY.md @@ -6,7 +6,7 @@ * [Migration](database.md#migration) * [Models](models.md) * [Model Defination](models.md#model-defination), - * [Naming Conventions & Overriding](models.md#conventions-overriding-conventions), + * [Conventions & Overriding](models.md#conventions), * [Associations](associations.md) * [Belongs To](associations.md#belongs-to) * [Has One](associations.md#has-one) @@ -25,6 +25,7 @@ * [Error Handling](advanced.md#error-handling) * [Transactions](advanced.md#transactions) * [Raw SQL & SQL Builder](advanced.md#sql-builder) + * [Generic database interface sql.DB](advanced.md#generic-database-interface-sqldb) * [Composite Primary Key](advanced.md#compose-primary-key) * [Overriding Logger](advanced.md#logger) * [Development](development.md) diff --git a/documents/advanced.md b/documents/advanced.md index 0d8c5827..a7afa3bc 100644 --- a/documents/advanced.md +++ b/documents/advanced.md @@ -114,6 +114,22 @@ for rows.Next() { } ``` +## Generic database interface sql.DB + +Get generic database interface from `*gorm.DB` connection [*sql.DB](http://golang.org/pkg/database/sql/#DB) + +```go +// 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() +``` + ## Composite Primary Key ```go diff --git a/documents/database.md b/documents/database.md index 98b6077d..275d1e04 100644 --- a/documents/database.md +++ b/documents/database.md @@ -4,15 +4,31 @@ ## Connecting to a database +When connect to a database, you need to import the database's driver first, for example: + +```go +import _ "github.com/go-sql-driver/mysql" +``` + +GORM has wrapped some drivers, for easier to remember the import path, so you could import the mysql driver with + +```go +import _ "github.com/jinzhu/gorm/dialects/mysql" +// import _ "github.com/jinzhu/gorm/dialects/postgres" +// import _ "github.com/jinzhu/gorm/dialects/sqlite" +// import _ "github.com/jinzhu/gorm/dialects/mssql" +``` + #### MySQL -**NOTE** don't forgot params `parseTime` to handle data type `time.Time`, [more support parameters](https://github.com/go-sql-driver/mysql#parameters) +**NOTE** in order to handle `time.Time` you need to include `parseTime` as param [more supported parameters](https://github.com/go-sql-driver/mysql#parameters) ```go import ( "github.com/jinzhu/gorm" - _ "github.com/go-sql-driver/mysql" + _ "github.com/jinzhu/gorm/dialects/mysql" ) + func main() { db, err := gorm.Open("mysql", "user:password@/dbname?charset=utf8&parseTime=True&loc=Local") } @@ -23,8 +39,9 @@ func main() { ```go import ( "github.com/jinzhu/gorm" - _ "github.com/lib/pq" + _ "github.com/jinzhu/gorm/dialects/postgres" ) + func main() { db, err := gorm.Open("postgres", "user=gorm dbname=gorm sslmode=disable") } @@ -35,8 +52,9 @@ func main() { ```go import ( "github.com/jinzhu/gorm" - _ "github.com/mattn/go-sqlite3" + _ "github.com/jinzhu/gorm/dialects/sqlite" ) + func main() { db, err := gorm.Open("sqlite3", "/tmp/gorm.db") } @@ -44,37 +62,17 @@ func main() { #### Write Dialect for unsupported databases -GORM officially support above databases, for unsupported databaes, you could write a dialect for that. +GORM officially support above databases, but you could write a dialect for those unsupported databaes, -Refer: https://github.com/jinzhu/gorm/blob/master/dialect.go - - -## Generic database object *sql.DB - -[*sql.DB](http://golang.org/pkg/database/sql/#DB) - -```go -// 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() -``` +Refer: [https://github.com/jinzhu/gorm/blob/master/dialect.go](https://github.com/jinzhu/gorm/blob/master/dialect.go) ## 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 +**WARNING** AutoMigrate will ONLY create tables, missing columns and missing indexes, **WON'T** change existing column's type or delete unused columns to protect your data ```go db.AutoMigrate(&User{}) @@ -88,7 +86,7 @@ db.Set("gorm:table_options", "ENGINE=InnoDB").AutoMigrate(&User{}) ### Has Table ```go -// Check if model `User`'s table has been created or not +// Check model `User`'s table exists or not db.HasTable(&User{}) // Check table `users` exists or not @@ -98,30 +96,39 @@ db.HasTable("users") ### Create Table ```go +// Create table for model `User` db.CreateTable(&User{}) -db.Set("gorm:table_options", "ENGINE=InnoDB").CreateTable(&User{}) // will append "ENGINE=InnoDB" to the SQL statement when creating table `users` +db.Set("gorm:table_options", "ENGINE=InnoDB").CreateTable(&User{}) ``` ### Drop table ```go +// Drop model `User`'s table db.DropTable(&User{}) + +// Drop table `users +db.DropTable("users") + +// Drop model's `User`'s table and table `products` +db.DropTableIfExists(&User{}, "products") ``` ### ModifyColumn -Change column's type +Modify column's type to given value ```go -// change column description's data type to `text` for model `User`'s table +// change column description's data type to `text` for model `User` db.Model(&User{}).ModifyColumn("description", "text") ``` ### DropColumn ```go +// Drop column description from model `User` db.Model(&User{}).DropColumn("description") ``` @@ -139,16 +146,16 @@ db.Model(&User{}).AddForeignKey("city_id", "cities(id)", "RESTRICT", "RESTRICT") ### Indexes ```go -// Add index +// Add index for columns `name` with given name `idx_user_name` db.Model(&User{}).AddIndex("idx_user_name", "name") -// Multiple column index +// Add index for columns `name`, `age` with given name `idx_user_name_age` 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 +// Add unique index for multiple columns db.Model(&User{}).AddUniqueIndex("idx_user_name_age", "name", "age") // Remove index diff --git a/documents/models.md b/documents/models.md index 8ae3c726..240315c3 100644 --- a/documents/models.md +++ b/documents/models.md @@ -6,29 +6,79 @@ ```go 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 + gorm.Model + Birthday time.Time + Age int + Name string `gorm:"size:255"` // Default size for string is 255, reset it with this tag + Num int `gorm:"AUTO_INCREMENT"` + + CreditCard CreditCard // One-To-One relationship (has one - use CreditCard's UserID as foreign key) + Emails []Email // One-To-Many relationship (has many - use Email's UserID as foreign key) + + BillingAddress Address // One-To-One relationship (belongs to - use BillingAddressID as foreign key) + BillingAddressID sql.NullInt64 + + ShippingAddress Address // One-To-One relationship (belongs to - use ShippingAddressID as foreign key) + ShippingAddressID int + + IgnoreMe int `gorm:"-"` // Ignore this field + Languages []Language `gorm:"many2many:user_languages;"` // Many-To-Many relationship, 'user_languages' is join table +} + +type Email struct { + ID int + UserID int `gorm:"index"` // Foreign key (belongs to), tag `index` will create index for this column + Email string `gorm:"type:varchar(100);unique_index"` // `type` set sql type, `unique_index` will create unique index for this column + Subscribed bool +} + +type Address struct { + ID int + Address1 string `gorm:"not null;unique"` // Set field as not nullable and unique + Address2 string `gorm:"type:varchar(100);unique"` + Post sql.NullString `gorm:"not null"` +} + +type Language struct { + ID int + Name string `gorm:"index:idx_name_code"` // Create index with name, and will create combined index if find other fields defined same name + Code string `gorm:"index:idx_name_code"` // `unique_index` also works +} + +type CreditCard struct { + gorm.Model + UserID uint + Number string } ``` -## Conventions & Overriding Conventions +## 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 +Base model definition `gorm.Model`, including fields `ID`, `CreatedAt`, `UpdatedAt`, `DeletedAt`, you could embed it in your model, or only write those fields you want ```go -// Model's definition +// Base Model's definition type Model struct { ID uint `gorm:"primary_key"` CreatedAt time.Time UpdatedAt time.Time DeletedAt *time.Time } + +// Add fields `ID`, `CreatedAt`, `UpdatedAt`, `DeletedAt` +type User struct { + gorm.Model + Name string +} + +// Only need field `ID`, `CreatedAt` +type User struct { + ID uint + CreatedAt time.Time + Name string +} ``` ### Table name is the pluralized version of struct name @@ -63,6 +113,7 @@ type User struct { CreatedAt time.Time // column name will be `created_at` } +// Overriding Column Name 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` @@ -74,11 +125,11 @@ type Animal struct { ```go type User struct { - ID uint // field named `ID` is the default primary key for `User` + ID uint // field named `ID` will be the default primary field Name string } -// your could also use tag `primary_key` to set other field as primary key +// Set a field to be primary field with tag `primary_key` type Animal struct { AnimalId int64 `gorm:"primary_key"` // set AnimalId to be primary key Name string @@ -108,4 +159,4 @@ 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. +Delete records having `DeletedAt` field, it won't be deleted from database, but only set field `DeletedAt`'s value to current time, and the record is not findable when querying, refer [Soft Delete](curd.html#soft-delete)