Recently I played with Hibernate as I need a really simple application that would be capable to write and read data from the database while it would be portable for use with JDBC drivers from different vendors. I didn’t want to write an abstract layer which would be dependent on particular JDBC driver and need to be recompiled with each. I just wanted to add a driver on the classpath, change a property and let it run. No recompilation. And it’s what the Hibernate solved for me at the end.
On top of that, I wanted Hibernate to create the database schema. Mine is pretty simple thus the entity could be scanned and created based on its attributes.
More precisely what I wanted
a standalone java application
code being independent on specific JDBC driver
generating database schema independently on specific SQL syntax. Normally the
CREATEthe command could differ database from the database.
being able to influence database name before starting of the java application (e.g. by some descriptor or system property)
saving and querying data to/from the database
Two possible solution with the Hibernate
While elaborating with Hibernate I found two way how to achieve my goal.
The first way was using JPA with
persistence.xml definition of database connection properties
and entity used as schema. Then asking javax.persistence.Persistence
to generate the schema.
The demand for dynamically changing the table name was done by implementing
that adding a suffix to the original table name. This approach was taken in both
cases. In one the strategy to be used as defined in the
persistence.xml and using property
hibernate.physical_naming_strategy while in the second case the strategy was provided
Running the code example
I played with the both approaches under the project https://github.com/ochaloup/hibernate-standalone.
If you want to run the example you need to
get the repo
git clone https://github.com/ochaloup/hibernate-standalone(use the correct branch to work with either
package it (maven is configured to create fat jar containing hibernate library):
mvn clean package
get the JDBC driver (expected you will use the PostgreSQL one: https://jdbc.postgresql.org)
run PostgreSQL database (you can use docker to run it:
docker run -p 5432:5432 --rm -ePOSTGRES_USER=test -e POSTGRES_PASSWORD=test postgres:9.4 -c max-prepared-transactions=110 -c log-statement=all)
start the java program at root
java -cp target/hibernate-standalone-1.0-SNAPSHOT-jar-with-dependencies.jar:<./postgresql-driver.jar>:. cz.chalda.Main
You can watch names of all tables at PostgreSQL with query
JPA persistence.xml approach
This approach could be investigated at the branch https://github.com/ochaloup/hibernate-standalone/tree/jpa-and-xml.
The all connection configuration is defined in the
Here we define connection properties for the database, the dialect which defines how to query for the JDBC driver
and there is a defined table naming strategy if needed.
The example then uses the descriptor file
hibernate.hbm.xml which defines
This configuration file is placed in the root of the project and is referred in the
with the absolute path of
./. That means when running
java -cp … <program-name> the program
will expect the mapping file at the place the java is run at.\+
That’s why the mapping file is placed at the root and defines different table name for you too
(up to the fact of the existence of the naming strategy).
For interest, the example contains the mapping file hibernate.hbm.xml.out containing the whole mapping of the entity but with table name redefinition.
The logic of creating the database schema and the entity save and the load is hidden in the class
There you can see the usage of
javax.persistence.Persistence to generate the database schema
and then to get the
PersistenceUnit for being able to save and load the entity.
Programmatic hibernate approach
This approach could be investigated at the branch https://github.com/ochaloup/hibernate-standalone/tree/hibernate-programatic-approach.
There is no configuration files in this case. We configure all at cz.chalda.Main file.
The connection is configured via
StandardServiceRegistryBuilder and it is defined
credentials and the dialect too.
Next is the usage of the
MetadataBuilder class which offers registration for enhancement of the
PhysicalNamingStrategyStandard to change table name with suffix.
The last part is using
SchemaExport for database schema creation
while metadata is used again for getting
for being able to create and update the database data.
Thanks for attention.
Both approaches offer a way to run a standalone java app with Hibernate to save time to develop an integration layer to different JDBC drivers while showing some Hibernate extension points to be used for further application tuning.
Some sources used during the case investigation are here