How do I get the Hibernate Configuration after the EntityManagerFactory has been built?
Asked Answered
T

2

6

My web framework (Play 1.2.5) creates an EJB3Configuration local to a method which it uses to create an EntityManagerFactory (source). I am working on a script and would like to run the generateSchemaUpdateScript() method from Configuration to make SQL scripts I can verify and run on production deploys. The problem I am having is that I cannot figure out how to access the Configuration object that was used or how to generate a Configuration object after the EntityManagerFactory has been built.

Thema answered 7/9, 2012 at 14:56 Comment(1)
I would suggest talking with the DBA about any schema tools available. They may be able to copy the schema for you or provide the script.Impetuous
G
7

You cannot get the configuration object back from the entitymanagerfactory because hibernate implementation EntityManagerFactoryImpl does not hold a reference to the configuration object

Your choices are

  • duplicates the code from JPAPlugin in your script to create your own configuration object
  • configure hibernate tools to work on your classes. I never used this tool myself but I guess that properly configured he can generate the ddl for you
  • generates back the ddl script from your database
Goatherd answered 11/9, 2012 at 8:55 Comment(0)
K
2

Once the Entity manager factory has been created you are not supposed to have the handle to the Configuration object, partly because of the design that Configuration is supposed to exhibit immutable behavior in that you cannot change its properties.

I'm referring to Hibernate 3.6.8 source and the EJB3Configuration class has method

public AnnotationConfiguration getHibernateConfiguration() {
        //TODO make it really read only (maybe through proxying)
        return cfg;
    }

AnnotationConfiguration is declared as deprecated as all of its functionality is moved to Configuration class.

So I think that using this you can get the handle to your configuration once it's been created. You have to be very careful though not to change anything in that configuration.

This is explained in the javadocs here

After #buildEntityManagerFactory() has been called, you no longer can change the configuration state (no class adding, no property change etc)

Having said that, what you are trying to achieve to do is something which is STRICTLY NOT ADVISED especially on production database. See here

Hibernate has a property named “hibernate.hbm2ddl.auto” which is to assist the schema auto generation in case of evolving scripts. What you are trying to achieve programmatically has same effect as giving it a value of update like below in your persistence xml. In fact under the covers, the method generateSchemaUpdateScript is called by the configuration when you have the value of "hibernate.hbm2ddl.auto" set to "update"

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
             version="2.0">
   <persistence-unit name="xyz" transaction-type="RESOURCE_LOCAL">
        <properties>
            ....................
            <property name="hibernate.hbm2ddl.auto" value="update"/>
            ......................
        </properties>
    </persistence-unit>
</persistence>

You can refer to other possible values for this attribute here

However the Hibernate docs stricltly advises against using this against production database.

The definitive book on Hibernate "Java persistence with Hibernate" cautions this

WARNING We’ve seen Hibernate users trying to use SchemaUpdate to update the schema of a production database automatically. This can quickly end in disaster and won’t be allowed by your DBA.

and also few limitations about the update schema process

An additional option for this configuration property, update, can be useful during development: it enables the built-in SchemaUpdate tool, which can make schema evolution easier. If enabled, Hibernate reads the JDBC database metadata on startup and creates new tables and constraints by comparing the old schema with the current mapping metadata. Note that this functionality depends on the quality of the metadata provided by the JDBC driver, an area in which many drivers are lacking. In practice, this feature is therefore less exciting and useful than it sounds.

UPDATE 1 : If you don’t have access to EJB3Configuration and your ultimate aim is to create the update schema scripts for JPA annotated entities then you can programmatically create the EJB3Configuration in a java main class using a persistence xml file which contains the configuration details of your database and run the schema export tool . See this example how you can do it. So this way you could run the tool on JPA entities outside of your framework or even container.

UPDATE 2

The example code listed here shows how you could use Hibernate schema update when creating database migrations for play applications. Seems like this is what you wanted !

Kornegay answered 13/9, 2012 at 13:19 Comment(3)
For reasons out of my control, I do not have access to the EJB3Configuration instance, so I cannot grab the Configuration from that. I agree with your extra advice, my current plan was to run generateSchemaUpdateScript() against my development database and check in the update sql and let my DBA run that after verifying it.Thema
I have added a link in "UPDATE 2" section which looks like does what you want to do !Kornegay
The link up UPDATE 2 basically strips out some, but not all code from JPAPlugin. What I am going to end up doing is copying over the plugin wholesale like the accepted answer suggests (as much as this pains me). Thanks for all your help.Thema

© 2022 - 2024 — McMap. All rights reserved.