2010-04-15 2 views
17

Я основной метод, использующий SchemaUpdate для отображения на консоли, какие таблицы для изменения/создания и она отлично работает в моем проекте Hibernate:Как использовать Hibernate SchemaUpdate класс с JPA persistence.xml?

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 

Кто-нибудь это сделал? Спасибо.

ответ

7

Kariem находится на правильном пути, но позвольте мне попытаться уточнить.

Предположим, что у вас есть стандартная конфигурация ванильного JPA, не имеющая ничего общего с Hibernate, кроме банок 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, вот и все.

+0

На Play Framework, я использую getHibernateConfiguration() на Ejb3Configuration и я не получить «нет источника данных при условии». Как я могу предоставить соединение (DB.datasource.getConnection() для воспроизведения)? –

3

Вы должны использовать 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 еще несколько ссылок.

1

Большое вам спасибо, ваш ответ работал нормально. Вот полный код нашего класса 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()); 
      } 
     } 
    } 

} 
Смежные вопросы