Quoting Jiri Jetmar <[email protected]>:
Hello gents,
Heyas,
as mentioned I spent some days working on our domain model using the
Qi4J/DCI approach.
I;m still very impressed how lightweight the qi4j "way" behaves - in
comparison with e.g. JPA with all the needed annotations,
configurations, etc.. It is incredible easy to add/modify/refactor an
Entity or Attribute, and use it immediately in the code... Wow.. :)
Nevertheless I have some questions that I could not answer by my self
or by looking
to the samples and test source code. Would be nice guys if you can
take a look
on these questions..
Q: How to express ManyToMany associations. Something like this :
interface Group {
ManyAssociation<User> users();
}
interface User {
ManyAssociation<Group> groups();
}
The Group Entity can have multiple Users and the User itself can be
associated
with many Groups. Both associations are required and I want to create
both Entities
in one UnitOfWork and hence in one Transaction. Do I need something
like a cardinality
helper Entity like "GroupToUserManyToMany" that maps the User and Group ?
Many-to-many relationships are modeled as having one-directional
ManyAssociation. To get to other direction in many-to-many
relationship, you must then use Query API. Which way is best to have
ManyAssociation to - that depends completely which is most load-heavy
or comfortable-to-use or whatever criteria you choose. :)
Q : EntityStore versus IndexingStore
Ok, I think I get the concept behind this two storage techniques. The
questions is
when to use what and eventually it makes sence to use them in a combination.
Using CQRS it would be possible to use the EntityStore as a
transactional storage and the IndexingStore as read-only storage for
query/search operations. The replication between this two stores can
be done by using domain events. That means also that IndexingStore
would
be eventually consistent (assuming that the sourced domain events are
not transactional).
Would it be the right approach ? This strategy has also the advantage
that the write and the
read models does not need to use the same underlying storage
techniques. The write (transactional) store can use SQL and the read
(query) model something else (if required).
I think the purpose of Indexing is to be kind of background-storage.
The client code should never use EntityStore or Indexing services
directly, but rather rely on "get" method in unit of work when ID of
entity is known to get it, or use Query API to get a set of entities
which match some criteria. Query API *requires* Indexing, and
UnitOfWork *requires* EntityStore, but those are added in assembly
stage, and are in interaction mostly with Qi4j.
Q : SQL Performance
The IndexingSQL Store is producing a highly "obfuscated" schema. As
long as one
do not need to work on this schema, e.g. to build some views this does
not matter.
Evtl. it would be possible to use instead of qname_number the names of
the entity and attributes ? Like person_age (entityname_attributename
). Another question is the performance. Are there any experience how
postgresql behaves when there is an entity with e.g. 30 attributes
and one is reading them out and as a consequence the SQL query will
contain many JOIN statements ? I;m planing to do such a test by my
self on several TBs of data, but would be
nice if there are already some experience on that topic.
I have to admit that it truly is quite obfuscated. The qname_<number>
table name notation comes from the fact that SQL stricts maximum name
length of table. Therefore, something like
"org_my_some_domain_MyClass_myProperty" would quickly shoot over the
limit (I think it's some ridicilously low? like 32chars or something
like that). Therefore all tables have surrogate name (there is a
lookup table though, I forgot the name... qi4j_lookup or qname_lookup
or something like that).
The reason for the big complexity is because the Qi4j Query API is so
unique (and quite expressive). Therefore, to scale to its
requirements, the data has to be stored in a way it is currently
stored. This results in complex queries. I personally don't have
experience with very complex queries. I think much more can be done in
somehow configuring IndexingSQL to create more indices and to give
hints to SQL query parser in RDBMS. This would need proper specing and
thinking over.
Q: Custom Datatypes
As we are doing some spatial queries it is required to i.) add spatial
datatypes (e.g. point)
and ii.) it is further needed that the generated SQL is supporting the
spatial extension (Postgis). These are basically additional (SQL)
functions that are used in the spatial query statement.
What would be the best approach to add the above features ?
You would need to model those custom datatypes using ValueComposites.
Currently all properties of any value composite will result in
qname_<number> table mentioned above. I guess one could make this
configurable, something like "for value composite X, instead of
generating qname-table, generate <custom table> and use <custom query
fragment> to query". This would need proper specing and thinking over
as well.
Q : Domain Model Versioning and/or Migration
To extend/modify the Domain Model using Qi4J is extremely easy and
lightweight - probably too
easy.. :-) During development this makes sense, but when there is
already one productive database
what is the strategy for versioning and for migration from one version
to another ? When e.g.
one attribute is removed the corresponding qname_number table (in the
SQL Indexing case) has
to be removed as well, or when e.g. the datatype of that attribute is
changed the old data must
be migrated. Or the domain model contains a versioning concept
where "old" data are never migrated to new versions but for each
entity multiple versions are available. I;m not sure about all the
consequences, but would be interesting what is your
opinion/advice on this topic from you guys.
I think versioning in Qi4j operates over EntityStore and not Indexing.
Therefore, I think versioning would get re-built from scratch (and
re-populated with newest values from entitystore) if someone empties
the schema. It's been so long time since I worked on IndexingSQL that
I am really not sure at all anymore.
About the versioning itself: IIRC it retains old state of the entity,
until it is loaded. Then it converts it, and if unit of work succeeds,
it will commit newest-versioned entity state.
_______________________________________________
qi4j-dev mailing list
[email protected]
http://lists.ops4j.org/mailman/listinfo/qi4j-dev