Slide 1

Slide 1 text

ORMs Ikenna Okpala 21st Jan. 2015 Go London User Group: January Meetup

Slide 2

Slide 2 text

ORM ● Object Relational Mapping ○ Convert data between two different type systems ○ In memory representation of domain objects (better abstractions of reality)

Slide 3

Slide 3 text

ORMs thus far…. ● Hailed as worthwhile at first ● Tagged unusable by some as time went on ● Some assumptions made that cost dearly ● Leading to some hot debates. ● But they are still around.

Slide 4

Slide 4 text

Why? ● Structure / Modularity(The M in MVC, Object Representation / Relational Mapping) ● Agnostic Database Integration (configs) ● Boilerplate Reduction (Spaghetti, Complex Queries, DRY) ● Providing hooks Tx lifecycle (Before/After) ● Easier data validation (Maintaining Data integrity) ● Sensible Defaults (Better naming, Connascence/Cognizance etc) ● RAW SQL strings have a high chance of compiling with semantic errors and @ runtime.

Slide 5

Slide 5 text

How? ● Support for popular databases ● CRUD ● SQL Generation ● Relationships / Association Traversals ● Tx hooks ● Schema Migration ● Managing Cache (???)

Slide 6

Slide 6 text

Go’s Philosophy ● As it Affects ORMs ○ Duality (Class / Type) ○ Non existence of a type hierarchy ■ Struct embedding (Composition) ■ Plumbing not encouraged ■ they don't have to announce their relationships

Slide 7

Slide 7 text

Go ORMs ❖ jinzhu/gorm ❖ coopernurse/gorp ❖ astaxie/beedb now beego/orm ❖ go-xorm/xorm ❖ coocood/qbs ❖ upper.io/db ❖ eaigner/hood ❖ Not regarded as ORMs ➢ jmoiron/sqlx ➢ eaigner/jet ➢ jaekwon/go-modeldb

Slide 8

Slide 8 text

database/sql package models // Author model type Author struct { ID int64 `db:"ID"json:"id"` Name string `db:"display_name"json:"name"` NickName string `db:"user_nicename"json:"nickname"` Email string `db:"user_email"json:"email"` URL string `db:"user_url"json:"url"` } db, _ := sql.Open("mysql", os.Getenv("SQL_MYSQL_DSN")")

Slide 9

Slide 9 text

database/sql db.Exec( "INSERT INTO author (display_name, user_nicename, email, url) VALUES (?, ?, ?)", "Foo", "Bar", '[email protected]', 'gfb.com/author/1' ) row := db.QueryRow("SELECT id, display_name, user_nicename, email, url FROM users WHERE id = ?", 1) row.Scan(&author.ID, &author.Name, &author.NickName, &author.Email, &author.URL) db.Exec( "UPDATE author SET display_name=?, user_nicename=?, email=?, url=? WHERE id = ?", &author.ID, &author.Name, &author.NickName, &author.Email, &author.URL ) db.Exec( "DELETE FROM author WHERE id = ?", author.ID )

Slide 10

Slide 10 text

coopernurse/gorp 1. Supports MySQL, PostgresSQL, SQLite 2. CRUD 3. SQL migrations a. dbmap.CreateTables() b. dbmap.CreateTablesIfNotExists() 4. Hooks (PostGet,PreInsert ,PostInser,PreUpdat,PostUpdat,PreDelet,PostDelete) 5. Bind arbitrary SQL queries to a struct 6. Bind slice to SELECT query results without type assertions 7. Use positional or named bind parameters in custom SELECT queries 8. more.. var posts []Post _, err = dbmap.Select(&posts, "select * from posts order by post_id")

Slide 11

Slide 11 text

jmoiron/sqlx 1. Is not regarded as an ORM from the authors view (I kind of disagree and agree to some extent) 2. Supports MySQL, PostgresSQL, SQLite 3. CRUD 4. Bind arbitrary SQL queries to a struct a. Scannability (scan safety) b. sql = fmt.Sprintf(`SELECT * FROM comments WHERE comment_approved <> 'spam' AND comment_post_ID IN (%s)`, pIDs) err = db.Unsafe().Select(&comments, sql) 5. A lot more flexible and better for legacy database

Slide 12

Slide 12 text

jinzhu/gorm 1. Supports MySQL, PostgreSQL, SQLite 2. Heavily influenced by Activerecord 3. CRUD authors := []Author{} err = db.Select(&authors, "SELECT * FROM author") db.Save(&Author{Name: "Foo", NickName: "Bar", Email: '[email protected]', URL: 'gfb.com/author/1'}) author.FirstName = "Big" db.Save(author) db.Delete(author) 4. Schema migrations a. db.AutoMigrate(&Author{}) b. db.CreateTable(&Author{}) c. db.DropTable(&User{}) and db.DropTableIfExists(&User{}) 5. Polymorphism and more... 6. Legacy DB support not great, A lot better for starting from scratch

Slide 13

Slide 13 text

Noteworthy ● Serialization is implemented the same way on all ● Be careful of go struct tags opaque strings which happily compile with semantic errors and can fail at runtime all too easily. ● Easily write verbose code ● Do all your logic outside your Go Structs (DAO) ● Avoid using YAML, JSON or XML for configuration (Deployment is a bit steep) Use ENV instead.

Slide 14

Slide 14 text

Thanks @ikenna_okpala