如何将 Hibernate SchemaUpdate 类与 JPA persistence.xml 一起使用?

发布于 2024-08-28 19:32:41 字数 1062 浏览 6 评论 0原文

我有一个使用 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 文件(根据 JPA 规范在 META-INF 目录中自动检测)。

我尝试了这种过于简单的改编,

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

但由于该例外而失败了。

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

有人这样做过吗? 谢谢。

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

I'd like to reuse this code in a JPA project, having no hibernate.cfg.xml file (and no .properties file), but a persistence.xml file (autodetected in the META-INF directory as specified by the JPA spec).

I tried this too simple adaptation,

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

but it failed with that exception.

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

Has anybody done that?
Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

独﹏钓一江月 2024-09-04 19:32:41

卡里姆(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 类型的配置中,这就是全部。

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.

手长情犹 2024-09-04 19:32:41

您应该使用 Ejb3Configuration 而不是普通配置。请参阅实体管理器文档,位于 引导部分

(从上面的源代码复制并稍加修改)

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>

请参阅此处更多参考。

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.

北渚 2024-09-04 19:32:41

非常感谢彼得,你的回复很好。
这是我们的 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());
            }
        }
    }

}

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

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文