Five tips on how to use Gorm better
Gorm is one of the most used ORMs for the Go language. It is complete and very easy to use. But sometimes the documentation does not cover all the cases.
There are some functionalities that once known can help you to write better code and simplify your work. Let's see five tips on how to use Gorm better.
1. Use custom foreign key constraints
When you create relations between tables remember to update the constraints on the foreign keys. As default, Gorm set the mode “NO ACTION” for update and delete cases.
However, you could make your life easier by using specific modes like for example the “CASCADE” one. Every time a primary key is updated the relative foreign key will be too. Instead, if a referenced record is deleted also the rows that reference it will be deleted as well.
In PostgreSQL, the available constraints are:
- SET NULL: set the foreign key to null
- CASCADE: do the same action as done on the referenced row.
- SET DEFAULT: set the foreign key to the default value (null or empty if not specified)
- NO ACTION and RESTRICT: in few words, they do not allow some operations on the referenced row. Look to the documentation to read more details about them.
2. Not using debug when stuck
One of the easiest ways to find errors is to use the inner debug utility available with Gorm. You just need to prepend “. Debug()” to your function call and you are done! Now, all the queries will be executed as before but in addition, the statement is printed.
db.Debug().
Table("users").
Select("users.name, emails.email").
Joins("left join emails on emails.user_id = users.id").
Scan(&results)
3. Joins and Preload
One of the most useful features of Gorm is the automatic management of relations. The functions “Preload” and “Join” help to do this, but when is better to use one or the other?
The Joins function is optimized for one-to-one relations and it makes the query faster by directly adding the join to the query. Preload instead can be used in any case, but it first reads all the records and then manually updates the relations in the final result.
db.Preload("Orders").Find(&users)
db.Joins("Company").Joins("Manager").Joins("Account").First(&user, 1)
// You can't do this!
// db.Joins("Orders").Find(&users)
// because an user can have more than one order
4. Find and First
Find and first are both used to retrieve data, but there is a big difference between them in how they handle errors. By using “Find”, if no value is found an error is raised. Instead, if no rows are retrieved with “First” nothing happens. The value returned will be empty and the error nil.
db.First(&user) // an error is raised if the table is empty
db.Limit(1).Find(&user) // no error
5. AutoMigrate your model to always have the latest version
While working on your project it could happen that a new table or column are needed. Taking track of new changes can be difficult, but for this case, Gorm provides the Migrate function.
This function takes input from the model to create new tables and update the database accordingly. The approach is conservative, Gorm only does additions or updates of new functionalities.
db.AutoMigrate(&User{}, &Product{}, &Order{})