Update scripts

Hello,

First I would like to report a problem with update/initial script generating and @MappedSuperclass and @Embeddable combination. I had a class that was @MappedSuperclass and included @Embeddable entity in itself. This embeddable contained ManyToOne associations to other entities. A little bit over-engineered maybe, but EclipseLink supports it alright. Whilst the update script generated was perfectly fine, the initial script was missing foreign keys corresponding to the associations that were part of the aforementioned @Embeddable class. We are trying to use Cuba for a new project and this problem manifested after deploying prototype to the server and showing it to the client - integrity has not been kept as it should have been - quite embarrassing.

That leads me to a question - why did you decide to have special script for clean DB and update script for already initialized DB? This creates massive redundancy of DDL/DML. It would work as well to have just update scripts and in case of initializing new DB, the whole series of these scripts would be run. This approach also gives you possibility - whenever you decide - to merge multiple update scripts into a new single one and thus simplify a state that is too complicated. We are actually using this approach on other projects without any issues. Also whole frameworks are written based on this approach. The problem is, that whenever you change your entities the initial scripts is recompiled and it is really hard to validate, if it is not missing anything - as it was in my scenario.

You may not agree what the right approach to this is, but what makes a good tool a good tool is an ability to tweak it, when it does not suffice. My last question is - if really don’t like this behavior, how can I extend Cuba studio to create update scripts in the way I am suggesting? There is lots of things I like about Cuba, so I hope there is a way to go around this and writing all my update scripts in hand is really not one acceptable ones, thanks for understanding.

Hello Jan,

Thank you for reporting the problem - we’ll check it ASAP and let you know when it will be fixed.

As for init/update scripts redundancy, we’ve always thought about update scripts (migrations) as of something short-lived that you can (and sometimes should) cut off at some point. Consider the following situations:

  • At the beginning of a project, you constantly modify your data model, add/remove entities and fields, change types, lengths, etc. You will want to try out all your changes, generating tons of update scripts for your local development database. Do you really want to ship all these messy scripts with your project when it goes to production, and possibly to many customers?

  • When in production, sometimes you need to write complex update scripts manually with data migration, even creating and executing temporary procedures. These update scripts make no sense when you need to create a new database schema for a new customer which is going to use your latest application version.

So I think you now understand our view on the problem.

Also, the init scripts are recompiled not entirely but only in the part defining a modified entity, which should be more easy to track when using a VCS diff.

As for extending Studio, it’s impossible now. If you are not satisfied with the Studio scripts generation mechanism, you can create your own or use a third-party tool like Liquibase and invoke it through a Gradle task or on application server start.

Thank you for a quick reply!

I understand, probably it is about being used to one way or the other. I managed to achieve maintainable compromise for us by overriding DbUpdaterImpl service in Spring. It is possible to watch over the init scripts using VCS, that is true - although the best would be to not have to watch two scripts, but just one. The biggest problem with your approach I see is high probability of merge conflicts when developing in a big team where more developers are changing the database model. The init scripts are going to get changed all the time.

It would be nice and enough for our cause if the migrations generator was part of the platform, not the studio. Generating a migration could then be a task in gradle, which would make things more portable.

Jan,

Good to hear that you have sorted the scripts issue to some extent.

From our experience, I can say that merge conflicts are quite rare because even when you work in a team, developers mostly work on their vertical slices of functionality that do not intersect too much. Of course it can be different in your situation so let us know if you have real problems with it.

Regarding moving the DB update functionality out of Studio. Firstly, Studio has a convenient internal object model representing entities, so it is technically wise to use it instead of replicating in a Gradle task. Also, we try to keep some balance between the free and payed part of our products by the obvious reason. Now the split is quite clear - the runtime part is mostly free and design-time is mostly payed, so we need some strong motivation to move the DB scripts generation mechanism which is obviously a design-time feature out of the payed part.

Btw, is this special ‘clean DB’ script available from Studio: generating one script per entity/without all the changes applied during development?

:ticket: See the following issue in our bug tracker:

https://youtrack.cuba-platform.com/issue/STUDIO-3417