0

I am trying to decide what the best way of storing my data would be. I want to build a cqrs application where I also apply DDD principles like aggregates in the command side. I started with with storing the aggregates in postgresql the 'normal' (relational) way using spring data jpa and hibernate.

I have a domain objects that are pure and dont have any annotations from the framework (spring, jpa, hibernate etc.). And in the infrastructure layer I have *Entity Objects for the aggregates to store the data in postgresql. But I was thinking if it would make sense to just have one table called 'Aggregate' that has an ID, type and data (jsonb) field. ID would be the aggregates Id, type would be an identifier for the aggregate class (e.g. BankAccount, Transaction etc.) and data would be the aggregates data in jsonb form. This way I wouldnt have to create *Entity objects in infrastructure layer with all the annotations and also would simplify the liquibase migrations, since I wouldnt have to create new migration files for every new aggregate implemented.

Another alternative would be to create the same tables for each Aggregate, so for BankAccount I would create a table with the fields Id, data (jsonb) and for Transaction a table with Id, data and so on.

Which solution would be preferred? The first one is simpler in terms of data migrations, because adding new attributes in aggregates wouldnt change the table because everything is in the data column in jsonb. Also no changes are needed for new aggregates implemented into the system. The second solution needs database migration every time I add a new aggregate, because the table needs to be created. But the the data is more separated each in his own table which could mean better performance in the future when there are thousands of rows in each table instead of millions of rows in a single table?

1 Answers1

1

You have a some problems but your solutions are extreme.

  1. You want "pure" domain objects but spring jpa forces your to use annotations.

    I'm pretty sure there is a work around for this: jpa without annotations. But you are not limited to using one ORM. Select another, or program your own repo layer with no ORM. Don't double up on classes with seperate annotated Entities

  2. You want to avoid migrations when properties change.

    Migrations for new properties aren't hard and won't happen as often as you fear. Also, putting your data in a json blob doesn't solve this issue. You will have to deal with the old rows where the objects have a different version to whatever the current definition is.

  3. You want to avoid migrations when you add a new type

    Again, this is an easy migration to do. Your solution of adding everything to the same table means you will need type and version columns and some logic to deal with changes, unknown types etc

  4. It's easier to just save the aggregate as one row, rather than updating linked tables.

    True, but at some point you might want a function "get the aggregate where the child has property = x" or "get the really big aggregate which means parsing 2Gb of json data" etc

Your proposed solution of using a RDMS with just one table and two columns isn't totally crazy. It's like a poor man's nosql database. But a proper nosql db would allow you to select on properties in your data and do other clever stuff.

If you want a quick solution for a proof of concept, it's fine to use this kind of thing. But there are reasons people use RMDBs, Migrations and NoSQL. You will be throwing out the baby with the bath water. Why not just add annotations to your models if you are willing to accept this kind of compromise with databases?

Ewan
  • 83,178