Skip to content

Latest commit

 

History

History
111 lines (76 loc) · 3.88 KB

IDS.md

File metadata and controls

111 lines (76 loc) · 3.88 KB

With MapperDao tables with surrogate, natural, composite keys can be mapped to entities. MapperDao works with Ids by having the type of the Id (i.e. Int) and a wrapper type for the Id that describes the Id, i.e. SurrogateIntId or NaturalStringId. Most components of MapperDao contain ID, PC and T types. ID is the raw type of the key, i.e. Int. PC is the trait that manages the key, i.e. SurrogateIntId. T is the actual mapped entity.

So for example, all mappings are done via Entity[ID,PC,T] class:

case class JobPosition(id: Int, name: String)

object JobPositionEntity extends Entity[Int,NaturalIntId, JobPosition] ...

In the above example, the key type ID=Int, the trait to be mixed in is PC=NaturalIntId and T=JobPosition. Hence JobPosition has a natural key which is also part of the class, JobPosition.id

Now, the NaturalIntId looks like:

trait NaturalIntId extends DeclaredIds[Int]

Hence it is a key with an Int value.

MapperDao.select uses this for the ids argument:

def select[ID, PC, T](entity: Entity[PC, T], id: ID)

Typically this will be called as mapperDao.select(JobPositionEntity,5) with scala inference working out ID,PC and T.

An other example is Dao mixins like

trait CRUD[ID, PC <: DeclaredIds[ID], T]
...

So if we wanted to mixin CRUD to our Dao for an entity with a String Natural Key:

case class My(...)
class MyDao extends CRUD[String,NaturalStringId,My]

or maybe use the pre-defined NaturalStringIdCRUD:

class MyDao extends NaturalStringIdCRUD[My]

Surrogate Ids

Surrogate keys are typically autogenerated and managed by the database. A non-persisted entity doesn't contain a value for the surrogate key. But as soon as the entity is persisted (i.e. after mapperDao.insert() or mapperDao.select()) then the value becomes part of the persisted entity.

All surrogate id traits are called like Surrogate*Id and can be easily looked up within say Eclipse. As an example, here is the SurrogateIntId:

trait SurrogateIntId extends DeclaredIds[Int] {
	val id: Int
}

Since this trait is mixed in the entity in the constructor, i.e. def constructor(implicit m) = new Product with SurrogateIntId ... the entity aquires the id property if it is persisted.

Natural Ids

Natural Ids will typically be part of the entity. Persisted and non-persisted entities will contain the values of those keys.

Typical natural id traits are NaturalIntId, NaturalLongId, NaturalStringId, and NaturalStringAndStringIds. NaturalStringAndStringIds can be used for entities with 2 string ids.

It is interesting to see how can we pass 2 String id's to mapperdao.select method:

def select[ID, PC, T](entity: Entity[PC, T], id: ID)

It only takes 1 parameter for the ID. So how does NaturalStringAndStringIds work?

trait NaturalStringAndStringIds extends DeclaredIds[(String, String)]

So it declares the id as a 2-string tuple. Hence we can mapperDao.select(MyEntity,(s1,s2))

Similarily the entity is declared as object MyEntity extends Entity[(String,String),NaturalStringAndStringIds,...

No id ?

There are occasions when an entity doesn't have an id. I.e. in a one-to-many relationship between a person and his houses, assuming the house table refers to person table via house.person_id, the house table doesn't need a key. Those entities can be mapped with the NoId trait.

Custom Ids

With1Id[ID1] , With2Ids[ID1, ID2] and With3Ids[ID1, ID2, ID3] are provided so that custom key combinations can be created. I.e. for an entity with a tripple String,Int,Long key then With3Ids[String,Int,Long] will do.

trait With1Id[ID1] extends DeclaredIds[ID1]
trait With2Ids[ID1, ID2] extends DeclaredIds[(ID1, ID2)]
trait With3Ids[ID1, ID2, ID3] extends DeclaredIds[(ID1, ID2, ID3)]

But also user traits can extend DeclaredIds to provide custom PC traits. Those traits can even aquire properties only for persisted instances.