2010-04-15 86 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文件(在JPA規範中指定的META-INF目錄中自動檢測)。

我想這個問題太簡單改編,

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

但是,除此之外失敗。

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

有沒有人做到這一點? 謝謝。

回答

7

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類型的配置中,這就是它的全部。

+0

在遊戲框架,我用Ejb3Configuration getHibernateConfiguration(),我得到「沒有提供數據源」。我如何提供連接(DB.datasource.getConnection())? – 2013-07-16 14:13:01

3

您應該使用Ejb3Configuration而不是正常配置。請參閱hibernate文檔中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

非常感謝Peter,您的回覆工作正常。 這裏是我們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()); 
      } 
     } 
    } 

} 
相關問題