header source
my icon
esplo.net
ぷるぷるした直方体
Cover Image for Examples and Internals of slick-codegen

Examples and Internals of slick-codegen

about9mins to read

This is the 17th article of Scala Advent Calendar 2017.

https://qiita.com/advent-calendar/2017/scala

Yesterday, @yoshiyoshifujii wrote about "Considering Errors from Infrastructure Layers".

https://qiita.com/yoshiyoshifujii/items/d63b0ca71c994f8c4ce1

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.

https://github.com/slick/slick/tree/v3.2.1/slick-codegen/src/main/scala/slick/codegen

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.

https://github.com/slick/slick/blob/v3.2.1/slick-codegen/src/main/scala/slick/codegen/SourceCodeGenerator.scala

class SourceCodeGenerator(model: m.Model) extends AbstractSourceCodeGenerator(model) with OutputHelpers{
  ...
}

Furthermore, AbstractSourceCodeGenerator uses AbstractGenerator.

https://github.com/slick/slick/blob/v3.2.1/slick-codegen/src/main/scala/slick/codegen/AbstractSourceCodeGenerator.scala

abstract class AbstractSourceCodeGenerator(model: m.Model) extends AbstractGenerator[String,String,String](model) with StringGeneratorHelpers{
  ...
}

AbstractGenerator uses GeneratorHelpers.

https://github.com/slick/slick/blob/v3.2.1/slick-codegen/src/main/scala/slick/codegen/AbstractGenerator.scala

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 ← SourceCodeGeneratorAbstractSourceCodeGeneratorAbstractGenerator
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.

Share