repo.retrieve
You can look up a persistent object from the database using the keys you
defined in your PType
. All you need is a key value. One way to do this
is to construct one yourself, like so:
val username = Username("smithy")
val f: Future[Option[PState[User]]] = repo.retrieve[User](username)
If you look at the API
docs for
Repo.retrieve
, you will see that the method above is actually divided into two parts. The
repo.retrieve[User]
returns a Repo.Retrieve[User]
object. We then call apply
on this object -
the (username)
part in the above code sample - which actually does the work. The reason why the
API is divided up in this way is to prevent you from having to supply Username
as a type
parameter. Otherwise the call would look like this:
repo.retrieve[User, Username](username) // this won't compile
Due to the way that type inference in Scala is done, there is no way that the User
type can be
inferred in this case. (The presence of the User
type on the left-hand side of the assignment
doesn’t help.)
The Repo.Retrieve[P].apply
method takes two implicit arguments. Like Repo.create
, we require a
PEnv[M, P]
, to ensure that the persistent class is actually part of the domain model. The retrieve
method also requires an implicit longevity.model.ptype.Key[M, P, V]
argument, to assure that the
key value supplied actually matches up with a key defined in the persistent type for
P
. This is why we typically define our keys as implicit values.
Take note that Repo.retrieve
returns an optional PState
, since there is never a guarantee that
a key value will match an existing persistent object. If you feel confident that the persistent
object does exist, you can use Repo.retrieveOne
instead. This is a simple wrapper method for
retrieve
, that opens up the Option[PState[P]]
for you. If the option is a None
, this will
result in a NoSuchElementException
.
You can also get a key value from an
aggregation in
a related entity. For example, a BlogPost
aggregates a set of authors for that post:
case class BlogPost(
uri: BlogPostUri,
title: String,
slug: Option[Markdown] = None,
content: Markdown,
labels: Set[String] = Set(),
postDate: DateTime,
blog: BlogUri,
authors: Set[Username])
Let’s retrieve all the authors for a blog post:
def getAuthorsForPost(blogPost: BlogPost): Future[Seq[PState[User]]] = {
val futures: Seq[Future[PState[User]]] = blogPost.authors.toSeq.map { author =>
repo.retrieveOne(author)
}
Future.sequence(futures)
}
Once you get back your PState
, you can of course use it to examine the persistent object itself
with PState.get
. You can modify it with PState.modify
, and you can pass the state on to
Repo.update
or Repo.delete
.
Repo.retrieve
will always result in a database call. Longevity will
not cache versions for you and pull them from the cache. Not caching
provides a guarrantee that the retrieved object is up to date with
the latest state of the database, and reduces the chances of a write
collision. We may revisit this in the future, but we do not consider
it an excessive burden on the longevity user to employ their own
cache, if need be.