Auto Macros


Avoid Boilerplate Code


If you want to avoid writing lots of boilerplate code, scalikejdbc-syntax-support-macro can be greatly helpful for reducing such troublesome coding tasks.


Setup


In addition to the core library, you can add the following optional dependency in buid.sbt:

libraryDependencies += "org.scalikejdbc" %% "scalikejdbc-syntax-support-macro" % "4.3.0"

Usage


autoConstruct for extracting entities from ResultSet

When you don’t use the macros, the usual code to extract data from ResultSet should look like below:

case class Company(
  id: Long,
  name: String, 
  countryId: Option[Long],
  country: Option[Country] = None
)

object Company extends SQLSyntaxSupport[Company] {

  def apply(rs: WrappedResultSet, rn: ResultName[Company]): Company = new Company(
    id = rs.get(rn.id), 
    name = rs.get(rn.name), 
    countryId = rs.get(rn.countryId)
  )
}

When using scalikejdbc-syntax-support-macro, you can use #autoConstruct macro instead. As you can see, now the code is significantly simpler and much easier to maintain for the future.

case class Company(
  id: Long,
  name: String, 
  countryId: Option[Long],
  // This property never comes from ResultSet
  country: Option[Country] = None
)

object Company extends SQLSyntaxSupport[Company] {

  def apply(rs: WrappedResultSet, rn: ResultName[Company]): Company = 
    // "country" is execluded when binding values from ResultSet
    // Note that the property neeeds to have the default `None` value
    autoConstruct(rs, rn, "country")
}

The #autoConstruct method binds all the fields defined at the primary constructor automatically.

The country field in the above example class should be ignored. In such cases, you should specify an additional String parameter such as “country”. Of course, the “country” will be verified at Scala compilation time!


autoColumns to avoid accessing JDBC metadata

When your code loads ScalikeJDBC DAO objects, ScalikeJDBC automatically fetches all the column names for the table specified by SQLSyntaxSupport‘s tableName via the JDBC metadata API.

If you don’t prefer the behavior, you can choose to load column names from the entity class’s field names instead. The following code won’t access JDBC metadata and will resolve column names from the Company class’s fields and primary constructor’s parameters by simply converting them to snake-cased ones or applying name converters to them.

case class Company(id: Long, name: String, countryId: Option[Long], country: Option[Country] = None)

object Company extends SQLSyntaxSupport[Company] {

  override lazy val columns = autoColumns[Company]("country") 
  // this will be Seq("id", "name", "country_id")
}

If this webpage has a typo or something wrong, Please report or fix it. How?