Search code examples
scalatypestype-conversionsqueryl

Squeryl: Typed Primary keys


I would like to define my Primary Keys as specific types - not just Long or String

For example

case class Project(
                    var id: ProjectId = 0,

One advantage of this is if I accidently compare different keys - then the compiler will pick it up.

Obviously this gives the compile error

overriding method id in trait KeyedEntity of type => Long;
 variable id has incompatible type

Are there any example's where this type of approach is successfully implemented?

Appendix - a draft of what ProjectId could be

trait SelfType[T] {
  val self : T
}

class Content_typeId( val self: Int) extends SelfType[Int]
class ProjectId( val self: Long) extends SelfType[Long]
object ProjectId {
  implicit def baseToType(self: Long) = new ProjectId(self)
  implicit def typeToBase(higherSelf: ProjectId) : Long = higherSelf.self

}

Thanks Brent


Solution

  • Yup, it can be done, but you are going to want to upgrade to Squeryl 0.9.6. The latest available is RC3 at the moment. There are 2 changes that you'll want to take advantage of:

    1. You no longer need to extend KeyedEntity. Instead, you can define an implicit KeyedEntityDef that Squeryl will use to determine which field(s) of your object constitute the primary key.

    2. Squeryl 0.9.6 allows you to extend what types are supported using type classes.

    RC3 is very stable, I'm using it myself in several production projects, but there is no official documentation for these features yet. You can find examples on the list, where I see you've also posted this question.

    I'd also suggest looking at how both PrimitiveTypeMode (the process of exposing a TEF for a type) and PrimitiveTypeSupport (which is where the TypedExpressionFactory instances are defined). KeyedEntity itself is supported with a KeyedEntityDef By Squeryl and looking at that code may be helpful as well.