A Persistence Framework for Scala and NoSQL
This is the first baby step in replacing custom reflection-based code with shapeless.
longevity.model.PType[M, P]
now has an abstract member with type
longevity.model.PEv[M, P]
. This is filled in by the @longevity.model.annotations.persistent
family of annotations, so it is not a concern to you if you are using these annotations to
construct your PTypes
. If not, you might consider using the new
@longevity.model.annotations.pEv
annotation to create the PEv
for you.@longevity.model.annotations.polyPersistent
and
@longevity.model.annotations.polyComponent
- now need to be sealed. This will require moving
subtypes into the same file.longevity.test.TestDataGenerator
API has been simplified. If you were using
this class in a way for which the new version is no longer sufficient, please let us know, and we
will see what we can do to help you out.longevity.test.CustomGenerator
and longevity.test.CustomGeneratorPool
have been removed. Custom test generation to account for constraints enforced within your domain
model can now be accomplished using ScalaCheck's Arbitrary
and
Gen
, See the user manual page on enforcing
constraints for more information.longevity.model
.Repo.retrieve
and Repo.retrieveOne
methods. This
way, we get "implicit not found" compiler errors for the PEv
before the Key
. This will give
more relevant error messages when the retrieve methods are called without explicating the P
type
parameter.PState.map
to PState.modify
. This follows more standard lense-type
terminology, and removes the incorrect impression that this is a monadic method.PState.modifyF
, which acts like modify
, except for functions that return an
effectful result.autocreateSchema
to autoCreateSchema
.autoOpenConnection
.Repo.openConnection
.Repo.closeSession
to Repo.closeConnection
.cassandra.autoCreateKeyspace
.longevity.config.LongevityConfig.apply(com.typesafe.config.Config)
to
LongevityConfig.fromTypesafeConfig
. This was necessary to prevent the library we use to parse
the Typesafe config from infinite looping on a configuration error.longevity.persistent.FOPState
and variants. Now that we have generalized
effects, these classes are special case. And they already take up a lot of space in API.longevity.persistent.Repo.createMany
and related
longevity.persistent.PWithEv
. These provided very little value added at the expense of
cluttering the API with confusing stuff.Future
effect with generic effect F
in
longevity.context.LongevityContext
and longevity.persistence.Repo
.The changes in this release are many, and the overall picture is hard to grasp by looking through a bullet list of the changes. For this reason, we present a quick migration guide here to get you from 0.22 to 0.23. Making the changes in the migration guide will probably get you 95-100% of the way there.
Replace this:
@domainModel object MyModel
with this:
@domainModel trait MyModel
Replace @persistent
with @persistent[MyModel]
, @component
with @component[MyModel]
, and
@keyVal[P]
with @keyVal[MyModel, P]
Remove the keySet = Set(key(props.a), key(props.b))
as an argument to the @persistent
annotation. Put the following lines in the companion object for your persistent class instead:
implicit val aKey = key(props.a)
implicit val bKey = key(props.b)
Replace this:
val context = LongevityContext(MyModel)
with this:
val context = LongevityContext[MyModel]()
Replace references to Repo[P]
with Repo[MyModel]
Replace calls like this:
context.repoPool[P]
with this:
context.repo
For repository methods createSchema
and closeSession
, replace calls like this:
context.repoPool.createSchema()
with call chains like this:
context.repo.createSchema()
Merge longevity.persistence.Repo
and longevity.persistence.RepoPool
APIs. There is now single repository, and the create/retrieve/update/delete/query methods now all take the persisten type as a type parameter. To migrate, code that used to look like this:
longevityContext.repoPool[User].create(user)
now looks like this:
longevityContext.repo.create[User](user)
In most cases, you can leave off type parameter, as the compiler can easily infer it:
longevityContext.repo.create(user)
Replace longevity.model.DomainModel
with a longevity.model.ModelType
type-class. Everything that used to live in DomainModel
now lives in ModelType
.
longevity.model.annotations.domainModel
now annotates a marker class or trait, instead of the object that was to become the old DomainModel
. This annotation macro adds an implicit object modelType
into the companion object of the annotated class. ModelType
now takes a type parameter M
that refers to the phantom class annotated with domainModel
.
longevity.context.LongevityContext
now takes a type parameter M
for the model class. In place of the explicit DomainModel
argument, it now takes an implicit ModelType[M]
, which can easily be found in the companion object of M
, as built by the annotation macro. longevity.context.Repo
also now takes a type parameter M
.
Add longevity.model.ModelEv
type-class. ("Ev" is short for "evidence" here.) The longevity.model.annotations.domainModel
annotation macro now adds an implicit object modelEv
into the companion object of the annotated class. This evidence class is private to the package that the domain model is found in. longevity.model.PType
now has a type parameter M
for the model, and an implicit ModelEv[M]
is required to initialize a PType[M, P]
. Because the generated model evidence is private to the model package, persistent types outside of the model package will not find the evidence, and will fail to compile. This prevents the user from accidentally creating a persistent type that falls outside the model.
Add longevity.model.PEv
type-class. ("Ev" is short for "evidence" here.) The longevity.model.PType
now includes an implicit val ev: PEv[M, P]
. Because the companion object of a persistent class is normally the corresponding PType
, this evidence should be available where needed. longevity.persistence.Repo
methods that used to take an implicit TypeKey[P]
argument, now take an implicit PEv[M, P]
argument. As users will not be able to find an implicit PEv[M, P]
available without the type P
actually being part of the model, (excepting the case where the user goes to extended lengths to subvert our type system), it will now be a compile-time error to call these repository methods with a non-persistent object. This is a great improvement over the old situation, since a TypeKey[P]
is available for any type P
for which there is a TypeTag[P]
available.
Replace longevity.model.KeyVal[P]
with longevity.model.KVType[M, P, V]
, which includes an implicit val longevity.model.KVEv[M, P, V]
. @longevity.model.annotations.keyVal
now takes a type parameter M
along with the type parameter P
. The @keyVal
annotation now creates or augments the companion object as a KVType[M, P, V]
.
Methods PType.key
and PType.primaryKey
now take implicit KVEv
arguments, to make sure the key value type provided matches a KVType
that is provided to the ModelType
.
The old constructors and factory methods for creating a longevity.model.ModelType
have been replaced with a single constructor that takes lists of longevity.model.PTypes
, longevity.model.CTypes
, and longevity.model.KVTypes
. The runtime package scanning constructor has been replaced by a compile-time package scanning. The new scanner, longevity.model.annotations.packscanToList
, is used by longevity.model.annotations.domainModel
, but you can use it yourself if you like. If you have been using the @domainModel
annotation, these changes should not affect you.
longevity.model.PTypePool
and longevity.model.CTypePool
have been removed.
Instead of passing in a keySet
to the @persistent
annotation, users should now specify their keys themselves, directly in the body of the companion object, as implicit values. The PType.keySet
has been made private, and is populated by reflecting on the members of the companion object.
Methods longevity.persistence.Repo.retrieve
and longevity.persistence.Repo.retrieveOne
now take an implicit Key[M, P, V]
instead of an implicit TypeKey[V]
. This will typically be found by implicit resolution in the companion object of P
.
Remove method longevity.model.PType.prop
. You can extend longevity.model.ptype.Prop
instead, but note that we advise you to use the longevity.model.annotations.persistent
annotation to generate properties.
Repo.retrieveByQuery
to Repo.queryToFutureVec
. The return type of this
method has also been adjusted from Future[Seq[PState[P]]]
to Future[Vector[PState[P]]]
.Repo.queryToItereator
.Repo.streamByQuery
to Repo.queryToAkkaStream
.Repo.queryToFS2
.Repo.queryToIterateeIo
.Repo.queryToPlay
.JDBC
back end.longevity.config.SQLiteConfig
to
JdbcConfig
. Rename longevity.config.LongevityConfig.sqlite
to
jdbc
. Rename longevity.config.TestConfig.sqlite
to jdbc
.longevity.writeTimestamps
.longevity-mongo-deps
to longevity-mongodb-deps
.longevity.config.Mongo
to
longevity.config.MongoDB
. Rename longevity.config.MongoConfig
to
longevity.config.MongoBDConfig
.longevity.config.SQLite
and
longevity.config.SQLiteConfig
.longevity.model.PType.partitionKey
to
primaryKey
.longevity.subdomain
to
longevity.model
. Also longevity.exceptions.subdomain
to
longevity.exceptions.model
.longevity.model.Subdomain
to
DomainModel
.longevity.model.annotations.subdomain
to domainModel
.LongevityConfig
, BackEnd
,
MongoConfig
, CassandraConfig
, TestConfig
, and
PersistenceConfig
from package longevity.context
to new package
longevity.config
.