Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Golang ORM (Object Relational Mapping)

Ikenna Okpala
January 21, 2015
680

Golang ORM (Object Relational Mapping)

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

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.

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

Video Link: https://skillsmatter.com/skillscasts/6162-orms-with-golang

Ikenna Okpala

January 21, 2015
Tweet

Transcript

  1. ORM • Object Relational Mapping ◦ Convert data between two

    different type systems ◦ In memory representation of domain objects (better abstractions of reality)
  2. 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.
  3. 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.
  4. How? • Support for popular databases • CRUD • SQL

    Generation • Relationships / Association Traversals • Tx hooks • Schema Migration • Managing Cache (???)
  5. 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
  6. 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
  7. 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")")
  8. 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 )
  9. 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")
  10. 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
  11. 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
  12. 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.