【问题标题】:How to use Hibernate SchemaUpdate class with a JPA persistence.xml?如何使用带有 JPA persistence.xml 的 Hibernate SchemaUpdate 类?
【发布时间】:2010-04-15 12:41:57
【问题描述】:

我有一个使用 SchemaUpdate 在控制台上显示要更改/创建的表的主要方法,它在我的 Hibernate 项目中运行良好:

 public static void main(String[] args) throws IOException {
  //first we prepare the configuration
  Properties hibProps = new Properties();
  hibProps.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("jbbconfigs.properties"));
  Configuration cfg = new AnnotationConfiguration();
  cfg.configure("/hibernate.cfg.xml").addProperties(hibProps);

  //We create the SchemaUpdate thanks to the configs
  SchemaUpdate schemaUpdate = new SchemaUpdate(cfg);


  //The update is executed in script mode only
  schemaUpdate.execute(true, false);
  ...  

我想在 JPA 项目中重用这段代码,没有 hibernate.cfg.xml 文件(也没有 .properties 文件),但有一个 persistence.xml 文件(在 META-INF 目录中自动检测到JPA 规范)。

这个太简单的改编我试过了,

Configuration cfg = new AnnotationConfiguration();
cfg.configure();

但它因该异常而失败。

Exception in thread "main" org.hibernate.HibernateException: /hibernate.cfg.xml not found

有人做过吗? 谢谢。

【问题讨论】:

    标签: hibernate jpa persistence.xml


    【解决方案1】:

    Kariem 是在正确的轨道上,但让我尝试澄清一下。

    假设您有一个普通的 JPA 标准配置,除了类路径上的 Hibernate jar 之外,没有任何特定于 Hibernate 的内容。如果您在 J2SE 引导模式下运行,那么您已经有一些看起来像这样的代码,无论是在 Java 中还是作为 Spring 配置等:

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

    要运行 SchemaUpdate,只需使用它:

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

    我不确定这将如何在容器环境中运行,但在简单的 J2SE 或 Spring 类型的配置中,这就是它的全部内容。

    【讨论】:

    • 在 Play Framework 上,我在 Ejb3Configuration 上使用 getHibernateConfiguration() 并获得“未提供数据源”。如何提供连接(DB.datasource.getConnection() on play)?
    • SchemaUpdate 构造函数不再有参数。 execute() 方法不再接受 booleans。
    【解决方案2】:

    您应该使用 Ejb3Configuration 而不是 普通 配置。请参阅实体管理器文档,位于休眠文档中bootstrapping section 的末尾。

    (从上述来源复制,稍作修改)

    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
    

    如您所见,您可以混合多种不同类型的配置。

    如果只是模式更新部分,你可以在你的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>
    

    更多参考资料请参见here

    【讨论】:

      【解决方案3】:

      非常感谢彼得,您的回复很好。 这是我们的 SchemaUpdater 类的完整代码:

      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());
                  }
              }
          }
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-04
        • 1970-01-01
        • 2015-08-08
        • 2017-11-20
        • 1970-01-01
        • 2011-11-07
        相关资源
        最近更新 更多