Thursday, May 6, 2010

Using Hibernate's SchemaExport Feature from within a Spring/JPA Context

My Spring-based application uses the Java Persistence Api (JPA) with Hibernate as persistence provider. As business requirement, I have the need to generate the SQL schema from my JPA annotated classes at application startup (As a disclaimer: I used the Maven Hibernate3 plugin in the past and there is also an Ant task provided by Hibernate, however in my case I needed a programmatic approach to have some more flexibility). Anyway, A logic choice for this would be Hibernate's SchemaExport class.

The problem is that Hibernate's SchemaExport class requires a org.hibernate.cfg.Configuration class to be passed in. Configuring this within Spring based applications is sparsely documented (Furthermore, the Configuration class is not easy to get hold off) but nevertheless there are some good pointers on how to get the Configuration object, when using straight Hibernate e.g:
Unfortunately, I am a bit on the cutting edge and I configured my persistence using
  • org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean and
  • org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter
How do you make that work? The best, albeit limited, information I found (as usual) on Stackoverflow:
That discussion pointed to the following blog post:
That was pretty much it. The blog post gave me some ideas about where to look next for answers (the Hibernate and Spring source code ;-), but the example just felt a bit heavy for my use-case. Everything was already configurred using Spring/JPA in my environment. Why shouldn't I be able to reuse my existing infrastructure to use the SchemaExport class?

The solution

After some more searching, I think I found a workable example:

In my class I inject the LocalContainerEntityManagerFactoryBean:

@Autowired LocalContainerEntityManagerFactoryBean fb;

Then I use the following code to setup SchemaExport:

org.hibernate.ejb.Ejb3Configuration cfg = new org.hibernate.ejb.Ejb3Configuration();
org.hibernate.ejb.Ejb3Configuration configured =     
                 cfg.configure(fb.getPersistenceUnitInfo(), fb.getJpaPropertyMap()); org.hibernate.tool.hbm2ddl.SchemaExport schemaExport = 
new org.hibernate.tool.hbm2ddl.SchemaExport(configured.getHibernateConfiguration());

And then do whatever you need to, such as printing the SQL Schema DDL to the console:       

schemaExport.create(true, false);

Not that bad after all. If you have similar needs, hopefully the Google gods are with you and this blog posting showed up in your search results. See you next time. 

6 comments:

paper writing service said...
This comment has been removed by a blog administrator.
ojow said...

Thanks, it worked for me.

Anonymous said...

Put me on the right track thanks for this posting!

Anonymous said...

Nice, just what I was looking for. I also had to provide a connection to SchemaExport:

org.hibernate.tool.hbm2ddl.SchemaExport(configured.getHibernateConfiguration(), fb.getDataSource().getConnection());

Gunnar Hillert said...

Glad that I was able to help!

Mattias J said...

This isn't working for me, and quite frankly I don't understand how it could. The org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean is a FactoryBean, which means it creates a bean of another class and puts in the Spring context, so the LocalContainerEntityManagerFactoryBean is never accessible from the context itself (is it?).

What does the Spring config look like for those of you who had this working? Version of Spring and Hibernate?