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 CREATE
the 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
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 second was using Hibernate API programmatically creating service registry builder and using schema exporter to generate the schema.
The demand for dynamically changing the table name was done by implementing
naming strategy
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
to the MetadataBuilder
.
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 jpa-and-xml
or hibernate-programatic-approach
)
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 cd hibernate-standalone
java -cp target/hibernate-standalone-1.0-SNAPSHOT-jar-with-dependencies.jar:<./postgresql-driver.jar>:. cz.chalda.Main
Note
|
You can watch names of all tables at PostgreSQL with query
|
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
persistence.xml
file.
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 <entity-mapping>
attribute.
This configuration file is placed in the root of the project and is referred in the persistence.xml
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
cz.chalda.Main.
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.
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 SessionFactory
and Session
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
https://antoniogoncalves.org/2014/12/11/generating-database-schemas-with-jpa-2-1
http://java-in-code.blogspot.cz/2016/08/native-hibernate-configuration-although.html
https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/chapters/bootstrap/Bootstrap.html
https://www.javahelps.com/2015/07/hibernate-hello-world-using-xml-mapping.html