Examples and Internals of slick-codegen
This is the 17th article of Scala Advent Calendar 2017.
Yesterday, @yoshiyoshifujii wrote about "Considering Errors from Infrastructure Layers".
Background
slick-codegen is a program that automatically generates code corresponding to a DB schema. It is a reliable tool that eliminates the need to write similar code repeatedly. If you are using Slick, you may have used it at least once.
Although slick-codegen is introduced in the official documentation (Schema Code Generation), the explanation is insufficient, making it difficult to understand how to customize it in practice. Additionally, there is a sample repository (slick/slick-codegen-customization-example) that introduces some usage methods, but there are many other ways to use it. Reading the API documentation is also helpful, but it would be nice to know what can be done more casually.
Therefore, I will introduce some samples and explain how to customize them.
slick-codegen Code
Sometimes, reading the code is the best way to understand it. slick-codegen consists of five small Scala codes, so it's not difficult to read.
Overall Image
To help you understand, I will briefly explain the overall structure.
A custom generator that you create inherits from SourceCodeGenerator
.
class CustomGenerator(model: m.Model) extends SourceCodeGenerator(model) {
...
}
SourceCodeGenerator
implements AbstractSourceCodeGenerator
and OutputHelpers
.
class SourceCodeGenerator(model: m.Model) extends AbstractSourceCodeGenerator(model) with OutputHelpers{
...
}
Furthermore, AbstractSourceCodeGenerator
uses AbstractGenerator
.
abstract class AbstractSourceCodeGenerator(model: m.Model) extends AbstractGenerator[String,String,String](model) with StringGeneratorHelpers{
...
}
AbstractGenerator
uses GeneratorHelpers
.
abstract class AbstractGenerator[Code,TermName,TypeName](model: m.Model) extends GeneratorHelpers[Code,TermName,TypeName]{ codegen =>
...
}
So, the relationship between classes is as follows:
Your class ← SourceCodeGenerator
← AbstractSourceCodeGenerator
← AbstractGenerator
Each class is defined in a file with the same name, so it's easy to follow the code.
Sample Collection
For the sample schema, I prepared the following SQL and executed it on MySQL.
create table user(
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY ( id )
);
create table item(
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
user_id INT,
FOREIGN KEY (user_id) REFERENCES user(id) ON DELETE CASCADE,
PRIMARY KEY ( id )
);
Converting java.sql.time to org.joda.time.DateTime
First, I will introduce a sample that converts java.sql.time
to org.joda.time.DateTime
. This is a convenient feature.
Setting Default Values
Next, I will explain how to set default values. This is useful when you want to set default values for columns like createdAt
and updatedAt
.
Automatically Converting to JSON
Then, I will introduce a sample that automatically converts to JSON. This is useful when you want to return JSON data in an API.
Using Custom ID Types
Finally, I will explain how to use custom ID types. This is useful when you want to distinguish ID types for each resource.
Conclusion
In this article, I introduced some samples of slick-codegen and explained how to customize them. By using slick-codegen effectively, you can reduce the amount of code you need to write.