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

Reply via email to