One of the important changes that has occurred over the last 5-10 years is that open source databases such as Postgres have become remarkably mature.
When Java developers started to use Object Relational Mappers, there were several important benefits that we cared about:
- Database independence
- Database specified in Java-land (XML config files or annotations)
- Automatic schema updates
In my opinion, the value of the benefits provided in the list above has declined over time. The consequences of this are non-obvious.
Consider why companies might switch databases. I have seen this happen a number of times during my career. Here are the top reasons for migrating away from your current database.
- Licensing Cost (vendor decides to raise prices)
- Feature limitations (current database sucks at something important)
- Seeking different approach entirely (such as moving to Mongo)
You may have hosting costs, but, generally, this is money well spent.
If you have a relational model, and you chose Postgres, then your chances of migrating away from Postgres because of feature limits are also fairly slim. The only reason that you might make a switch is because you want a different model entirely, such as a NoSQL database such as DynamoDB.
In general, if you have decided to build your app on a relational model, and you chose Postgresql, then the next question is: why work at arms length?
JPA is designed to let you describe and interact with the DB purely from Java. With JPA, you generally define your model using Java classes. This database-neutral model of access does bring with it some important costs, in terms of how you express queries and other database operations.
JPA/Hibernate is no longer the best choice IMO because it hides the value of SQL behind an API that is decent at basic CRUD operations.
JPA is the new COBOL. I am not making this stuff up. Look at the trend:
The best way to handle database access from Java is to:
- Manage your relational model using native SQL.
- Adopt a migrations facility like Flyway or Liquibase.
- Reverse engineer your model into a data access library that enables highly expressive, native queries, like JOOQ.
Getting all of this working can take some work. Consider how useful it is to have the following:
- Direct access to views and stored procedures within your service tier
- No JPAs
- No Repository boilerplate
And when you change the schema? Here is what you do:
- Write a new migration, test it locally, and then apply it in production
- Re-generate your Data Access Library, and make appropriate changes in your Service tier.
If you are using a typesafe data access facility like JOOQ, then your IDE/compiler will help you find any problems introduced by the most recent schema update.