The last repository we want to create in this tutorial is a repository based on the ORM package GORM. Create a new file
repository_postgresql_gorm.go in our domain package
website and copy the contents of the repository there.
You will need the
gorm.io/gorm package to make everything work, so add it to your project:
go get gorm.io/gorm
Let’s go through what our repository looks like.
Check out GORM great documentation if you want to learn more about how to use it.
GORM is based on models, i.e., structs that represent a database row and describe the table schema using struct tags. In our repository, we have defined the
gormWebsite model, which describes the structure of the
websites table. Look at how the struct tags define the table columns, and the
TableName() method sets the table name. As you can probably guess, since the entire table is defined in code, we do not have to use SQL to perform operations on the database, even to create the table.
If you want to learn more about declaring models in GORM, check out the documentation.
The repository constructor
The repository structure
PostgreSQLGORMRepository (and the constructor
NewPostgreSQLGORMRepository) takes only one argument, the
gorm.DB object that represents, as in the previous cases, a concurrent safe connection to the database.
GORM has the
AutoMigrate() method to perform automatic migration, which is, creating or modifying a table schema as defined in the model struct. Look at the line
34. We create a database object that respects the passed
context.Context using the
WithContext() function, and then call the
AutoMigrate() method with the model object as an argument. It is enough to create
websites table in the database with the columns defined in the model.
To insert records into a DB table, we can use the GORM
DB.Create() method, which takes a model object as an argument. Since we are operating on a domain object of type
Website, we should remember to convert it to
gormWebsite, which we do in lines
38-42. After successfully inserting the record, the GORM function
DB.Create() also updates the value of the inserted object with the generated ID. So we just need to convert the inserted value back to
54) and return this object from our
Create() method as an inserted
Website record. In this method, as with previous repository implementations, we also handle the unique constraint violation error. Since the PostgreSQL driver for GORM internally uses the
pgx package, all we need to do is check that we get an appropriate error of type
To get all the records from the table, we just need to initialize an empty slice of
gormWebsite objects for results and set it as an argument to GORM’s
Find() method (line
61). Then, to be able to return a slice of type
Website, the result needs to be converted, which we do in lines
GetByName() method is very similar to
All() except that we use the GORM
Where() function to add the SQL
WHERE clause to our query, and we handle the
gorm.ErrRecordNotFound error that is returned when there is no record with the given criteria. Note that the GORM requires
? instead of
$1 as a placeholder in the
Where() query. As with the
All() method, we use the
Find() function here to get the result, but this time with a single
gormWebsite object as an argument. In the end, we convert the result to our
Website domain object.
If you have followed the previous methods, then
Update() is nothing new for you. We use the GORM
Save() function here to update the value of a
gormWebsite object in the database. Finally, in addition to checking that we did not create a duplicate by updating, we also get the number of rows affected by this change. If it is equal to 0, we return the
ErrUpdateFailed error, as in previous repository implementations.