How to use Hibernate SchemaUpdate class with a JPA persistence.xml?

前端 未结 3 562
再見小時候
再見小時候 2021-02-04 05:06

I\'ve a main method using SchemaUpdate to display at the console what tables to alter/create and it works fine in my Hibernate project:

 public static void main(         


        
相关标签:
3条回答
  • 2021-02-04 05:19

    You should use Ejb3Configuration instead of the normal configuration. Refer to the entity manager documentation, at the end of the bootstrapping section in the hibernate documentation.

    (copied from above source with minor adaptations)

    Ejb3Configuration cfg = new Ejb3Configuration();
    EntityManagerFactory emf = 
      cfg.addProperties(properties)                  // add some properties
         .setInterceptor(myInterceptorImpl)          // set an interceptor
         .addAnnotatedClass(MyAnnotatedClass.class)  // add a class to be mapped
         .addClass(NonAnnotatedClass.class)          // add an hbm.xml file using the Hibernate convention
         .addResource("mypath/MyOtherCLass.hbm.xml") // add an hbm.xml file
         .addResource("mypath/orm.xml" )             // add an EJB3 deployment descriptor
         .configure("/mypath/hibernate.cfg.xml")     // add a regular hibernate.cfg.xml
         .buildEntityManagerFactory();               // create the entity manager factory
    

    As you can see, you can mix a lot of different types of configuration.

    If it's only for the schema update part, you can just set a property in your persistence.xml: hibernate.hbm2ddl.auto:

    <persistence-unit name="app1">
       <provider>org.hibernate.ejb.HibernatePersistence</provider>
       <properties>
         …
         <property name="hibernate.hbm2ddl.auto" value="update"/>
       </properties>
    </properties>
    

    See here for a few more references.

    0 讨论(0)
  • 2021-02-04 05:34

    Kariem is on the right track, but let me attempt to clarify.

    Let's assume that you have a vanilla JPA-standard configuration with nothing Hibernate-specific, except for the Hibernate jars on the classpath. If you are running in J2SE bootstrap mode, you already have some code that looks something like this, either in Java or as Spring configuration, etc.:

    Map<String, Object> props = getJPAProperties();
    EntityManagerFactory emf = 
        Persistence.createEntityManagerFactory("persistence-unit-name", props);
    

    To run SchemaUpdate, simply use this instead:

    Map<String, Object> props = getJPAProperties();
    Ejb3Configuration conf = 
        new Ejb3Configuration().configure("persistence-unit-name", props);
    new SchemaUpdate(conf.getHibernateConfiguration()).execute(true, false);
    

    I'm not sure how this would operate in a container environment, but in a simple J2SE or Spring type of configuration, that's all there is to it.

    0 讨论(0)
  • 2021-02-04 05:34

    Thank you so much Peter, your reply worked fine. Here is the full code of our SchemaUpdater class:

    package reformyourcountry.dbupdate;
    
    import java.io.BufferedReader;
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.PrintStream;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import org.hibernate.ejb.Ejb3Configuration;
    import org.hibernate.tool.hbm2ddl.SchemaUpdate;
    
    import reformyourcountry.misc.DateUtil;
    
    /** Small utility to be run by a developer to identify the difference between
     * its entities and its DB schema. It produces an SQL to be copy/pasted and applied
     * on the DB manually. Each developers having its own DB, when a developer commits its
     * Java code with new entity attributes (needing new DB columns), he also commits
     * an updated SQL file with the SQL that other developers need to apply on their local DB.
     * Later, when deploying the next version of the application in production,
     * this SQL file with cumulated changes will be applied onto the production DB.  
     * 
     * Limitations: 
     * 1. the Hibernate schema update does not detect removed attributes. 
     * If you have to delete a column, you need to write the SQL manually;
     * 
     * 2. the Hibernate schema update does not detect changes on existing columns.
     * for example, if you add @Column(nullable=false), it will not generates an 
     * additional DB constraint.
     * 
     * @author Cédric Fieux & John Rizzo & Aymeric Levaux
     *
     */
    public class SchemaUpdater  {
    
        @SuppressWarnings({ "deprecation", "unchecked" })
        public static void main(String[] arg) throws IOException {
    
            ////// 1. Prepare the configuration (connection parameters to the DB, ect.)
            // Empty map. We add no additional property, everything is already in the persistence.xml
            Map<String,Object> map=new HashMap<String,Object>();   
            // Get the config from the persistence.xml file, with the unit name as parameter.
            Ejb3Configuration conf =  new Ejb3Configuration().configure("ConnectionPostgres",map);
            SchemaUpdate schemaUpdate =new SchemaUpdate(conf.getHibernateConfiguration());
    
            /////// 2. Get the SQL
            // Before we run the update, we start capturing the console output (to add ";" later)
            PrintStream initOut = System.out;
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream(1024);
            PrintStream newOut = new PrintStream(outputStream);
            System.setOut(newOut);
    
            //The update is executed in script mode only
            schemaUpdate.execute(true, false);
    
            //We reset the original out
            System.setOut(initOut);
    
            ////// 3. Prints that SQL at the console with a good format (adding a ";" after each line).
            System.out.println("--*******************************************Begin of SQL********************************************");
            System.out.println("-- "+DateUtil.formatyyyyMMdd(new Date()));
            BufferedReader ouReader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(outputStream.toByteArray())));
            String str = ouReader.readLine();
            while(str != null){  // For each (sometimes multiline) SQL statement
                // now, str equals "".
                str = ouReader.readLine();  // 
                while (str != null && !str.trim().equals("")) { // for each line of the same statement
                    System.out.println();  // previous line is finished.
                    System.out.print(str.toLowerCase());
                    str = ouReader.readLine();
                }
                // Statement is now finished
                System.out.println(";");
            }
            System.out.println("--*******************************************End of SQL********************************************");
    
            ////// 4. Print eventual exceptions.
            //If some exception occurred we display them
            if(!schemaUpdate.getExceptions().isEmpty()){
                System.out.println();
                System.out.println("SOME EXCEPTIONS OCCURED WHILE GENERATING THE UPDATE SCRIPT:");
                for (Exception e: (List<Exception>)schemaUpdate.getExceptions()) {
                    System.out.println(e.getMessage());
                }
            }
        }
    
    }
    
    0 讨论(0)
提交回复
热议问题