Hibernate 4: How to dynamically manage tables in a db - java

This questions has been asked a few times, but most of the answers are a few years old so I'll post this hoping someone has figured out an answer.
Problem: We have a production live system that is currently working great with hibernate 4/jboss/etc. The problem is a few of our production sites are integrated with legacy systems that are using the same database, and creating data in new tables.
We've been given a requirement to action against these tables from our system. Unfortunately, the way these legacy systems work, I can't define a default entity type to match against these tables, and the table names/columns vary widely.
What I can do is find the name of the tables.
What I can't do is get hibernate to manage these tables like I want to. I've spent the last week looking for a solution, but the biggest problem I have is that the entity manager is immutable after instantiated.
Older stackoverflow questions:
Adding Tables and Columns in Hibernate on The Fly?
Has anyone have any hints on where I can possibly make this requirement achievable?
Thanks in advance.

Here's an outline of a way that this could work. Basically, you'd use Hibernate's reverse engineering tools to generate class files, then compile them on the fly, and then create a new Configuration with them and use that to generate a new EntityManager.
Hibernate reverse engineering
There's a set of IDE and Ant tools that Hibernate provides for reverse engineering and code generation which, among other thing, can generate code based on a database definition. Generally, their expectation is that people are going to generate code/mapping files based on a database either once, or during the build. What you want to do is generate those artifacts from your running program, which is definitely off-label usage. I'd start with the Ant task. End goal of this step is to have generated POJOs representing the contents of the tables in your database.
In process compilation
Now that you've got your Java files, you need to compile them. See this question for an example of using Process to run javac on your files. If you compile them to your classpath, they'll be available to your process.
Build a new configuration
Using the ejb3=true flag when you generated the POJOs, you should know be able to add them to a Configuration object already annotated. I'm not sure what the best way will be for you to actually identify the newly generated classes so that you can .addAnnotatedClass(). It may be best to capture output from the hbm2java, or perhaps to scan the output folder for the new Java files, or perhaps there's another way that your program can 'know' about the new entities. In any case, you can then use that Configuration to create a new EntityManager that maps to your new database structures.

Related

Creating HSQL create table query from class

I have a much used project that I am working on currently updating. There are several places where this project can be installed, and in the future it is not certain what version is used where and to what version one might be updated to in the future. Right now they are all the same, though.
My problem stems from the fact that there might be many changes to the hibernate entity classes, and it must be easy to update to a newer version without any hassle, and no loss of database content. Just replace WAR and start and it should migrate itself.
To my knowledge Hibernate does no altering of tables unless hibernate.hbm2ddl.auto=create, but which actually throws away all the data?
So right now when the Spring context has fully loaded, it executes a bean that will migrate the database to the current version by going through all the changes from versionX to versionY (what version it previously was is saved in the database), and manually alter the table.
It's not much hassle doing a few hard-coded ALTER TABLE to add some columns, but when it comes to adding complete new tables, it feels silly to have to write all that...
So my question(s) is this:
Is there any way to send an entity class and a dialect to Hibernate
code somewhere, and get back a valid SQL query for creating a table?
And even better, somehow create an SQL string for adding a column to a table, dialect-safe?
I hope this is not a silly question, and I have not missed something obvious when it comes to Hibernate...
have you tried
hibernate.hbm2ddl.auto=update
it retains all the database with the data and append only columns and tables you have changed in entity.
I don't think you'll be able to fully automate this. Hibernate has the hbm2ddl tool (available as an ant task or a maven plugin) to generate the required DDL statements from your hibernate configuration to create an empty database but I'm not aware of any tools that can do an automatic "diff" between two versions. In any case you're probably better off doing the diff carefully by hand, as only you know your object model well enough to be able to pick the right defaults for new properties of existing entities etc.
Once you have worked out your diffs you can use a tool like liquibase to manage them and handle actually applying the updates to a database at application start time.
Maybe you should try a different approach. In stead of generating an schema at runtime update, make one 'by hand' (could be based on a hibernate generated script though).
Store a version number in the database and create an update script for every next version. The only thing you have to do now is determine in which version the database currently is and sequentially run the necessary update scripts to get it to the current version.
To make it extra robust you can make a unit/integration test which runs every possible database update and checks the integrity of the resulting database.
I used this method for an application I build and it works flawlessly. An other example of an implementation of this pattern is Android. They have an upgrade method in their API
http://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html#onUpgrade(android.database.sqlite.SQLiteDatabase, int, int)
Don't use Hibernate's ddl. It throws away your data if you want to migrate. I suggest you take a look at Liquibase. Liquibase is a database version control. It works using changesets. Each changeset can be created manually or you can let Liquibase read your Hibernate config and generate a changeset.
Liquibase can be started via Spring so it should fit right in with your project ;-)

java library to maintain database structure

My application is always developing, so occasionally - when the version upgrades - some tables need to be created/altered/deleted, some data modified, etc. Generally some sql code needs to be executed.
Is there a Java library that can be used to keep my database structure up to date (by analyzing something like "db structure version" information and executing custom sql to code to update from one version to another)?
Also it would be great to have some basic actions (like add/remove column) ready to use with minimal configuration, ie name/type and no sql code.
Try DBDeploy. Although I haven't used it in the past, it sounds like this project would help in your case. DBDeploy is a database refactoring manager that:
"Automates the process of establishing
which database refactorings need to be
run against a specific database in
order to migrate it to a particular
build."
It is known to integrate with both Ant and Maven.
Try Liquibase.
Liquibase is an open source (Apache
2.0 Licensed), database-independent library for tracking, managing and
applying database changes. It is built
on a simple premise: All database
changes are stored in a human readable
yet trackable form and checked into
source control.
Supported features:
Extensibility
Merging changes from multiple developers
Code branches
Multiple Databases
Managing production data as well as various test datasets
Cluster-safe database upgrades
Automated updates or generation of SQL scripts that can be approved and
applied by a DBA
Update rollbacks
Database ”diff“s
Generating starting change logs from existing databases
Generating database change documentation
We use a piece of software called Liquibase for this. It's very flexible and you can set it up pretty much however you want it. We have it integrated with Maven so our database is always up to date.
You can also check Flyway (400 questions tagged on SOW) or mybatis (1049 questions tagged). To add to the comparison the other options mentioned: Liquibase (663 questions tagged) and DBDeploy (24 questions tagged).
Another resource that you can find useful is the feature comparison in the Flyway website (There are other related projects mentioned there).
You should take a look into OR Mapping libraries, e.g. Hibernate
Most ORM mappers have logic to do schema upgrades for you, I have successfully used Hibernate which gets at least the basic stuff right automatically.

JPA/Hibernate support for migration?

I'm currently working on a desktop application using JPA/Hibernate to persist data in a H2 database. I'm curious what my options are if I need to make changes to the database schema in the future for some reason. Maybe I'll have to introduce new entities, remove them or just change the types of properties in an entity.
Is there support in JPA/Hibernate to do this?
Would I have to manually script a solution?
I usually let Hibernate generate the DDL during development and then create a manual SQL migration script when deploying to the test server (which I later use for UAT and live servers as well).
The DDL generation in Hibernate does not offer support for data migration at all, if you only do as much as adding a non-null field, DDL generation cannot help you.
I have yet to find any truely useful migration abstraction to help with this.
There are a number of libraries (have a look at this SO question for examples), but when you're doing something like splitting an existing entity into a hierarchy using joined inheritance, you're always back to plain SQL.
Maybe I'll have to introduce new entities, remove them or just change the types of properties in an entity.
I don't have any experience with it but Liquibase provides some Hibernate Integration and can compare your mappings against a database and generate the appropriate change log:
The LiquiBase-Hibernate integration records the database changes required by your current Hibernate mapping to a change log file which you can then inspect and modify as needed before executing.
Still looking for an opportunity to play with it and find some answers to my pending questions:
does it work when using annotations?
does it require an hibernate.cfg.xml file (although this wouldn't be a big impediment)?
Update: Ok, both questions are covered by Nathan Voxland in this response and the answers are:
yes it works when using annotations
yes it requires an hibernate.cfg.xml (for now)
There are two options:
db-to-hibernate - mirror DB changes to your entities manually. This means your DB is "leading"
hibernate-to-db - either use hibernate.hbm2ddl.auto=update, or manually change the DB after changing your entity - here your object model is "leading"

Is it possible to generate JPA entity classes from a database schema at runtime?

IDEs like Netbeans allow generation of entity classes through a persistence context. If you had access to underlying generation method (not sure if it is an external tool or part of the IDE), could you generate database entity classes dynamically at runtime? The idea being that you could hook into the entity classes using reflection.
I know you can go the other way and generate the database from the entity class, however due to permissions issues in my work environment that would be a no go. However, if you reverse the process and pull the classes from the database it may be feasible in my environment. The idea being that the database would serve as a single point of configuration/control.
It's theoretically possible but what would be the point? Java is statically typed so you would only be able to use the generated classes by reflection and you would have no way of giving them behaviour, so removing the whole point of object-relational mapping. Loading the data into Maps or just using SQL record sets would be more convenient.
If you have an existing schema you can write classes that act in the way your application needs and declaratively map them onto the schema. That way the code is the simplest expression of your application logic and is persistence-agnostic.
You can find on JBoss website a tool to do the reverse engineering from database to java objects.
The source code is available, you should dig in!
https://www.jboss.org/tools/download/stable.html
Assuming you're using Hibernate, you might be able to use Hibernate Tools to generate the database schema. Although primarily designed for Eclipse and Ant, its theoretically possible to link it in and invoke it like any other JAR.

Hibernate Tools and the ever changing database

I am currently using Hibernate Tools 3.1; I customized naming convention and DAO templates. The database (SQL Server 2005) in early development phase and I'm in charge of rebuilding the mappings, entities, DAOs, configuration, whatever. Each time I have to reverse-engineer the tables and so I lose every customization I made on the mappings (*.hbm.xml files) like adjusting the identity columns, picking the fields used in equals and toString. I was considering to write the diff XML in a file and the "merge" that onto the generated mapping (see my related question) but I was wondering... is there any best practice/tool for dealing with these annoying, unavoidable, critical tasks?
I'd strongly recommend against continual reverse engineering. Reverse engineering is a great one time thing, but changes need to be managed as changes to both the hbm and the database.
We use migrations to manage db changes, and we include the associated changes in the hbm. If Hibernate has it (I believe it does) you may want to look into annotations instead of an hbm, they can be quite a bit easier to maintain.
This is two and a half years late, but I'll offer a dissenting opinion. You should be able to make any customizations you need to the mapping files through the hibernate.reveng.xml file or a custom ReverseEngineeringStrategy. For the classes themselves, you should always generate to base classes and extend them with classes containing custom code.
For example, generate com.company.vo.generated.CustomerGenerated and extend it with com.company.vo.custom.Customer. Code generation should overwrite all classes in the generated package but never in the custom package (although you can have Hibernate Tools generate these custom classes in the target directory so that you can copy and paste blanks into the custom directory as needed). This way you can override methods for equals, toString, etc in the custom classes and not lose your changes when you regenerate. Also note that the best practice is to not check in generated code into SCM.
There are some great examples on this site of how to achieve this using Maven, the Hibernate3 plugin, and the build helper plugin. Most of these have very helpful answers by Pascal Thivent. This method is working beautifully for me, and while there is a bit of a learning curve it's a wonderful thing to be able to propagate database changes to the app with a single Maven command.

Categories