2015-09-21 92 views
7

這個問題是特別編程創建JPA EntityManagerFactory由Hibernate支持5,這意味着沒有配置XML文件不使用Spring。此外,這個問題是特別是關於創建與Hibernate攔截器EntityManagerFactoryJPA與Hibernate 5:編程創建的EntityManagerFactory

我知道如何創建Hibernate SessionFactory我想要的方式,但我不想休眠SessionFactory,我想要一個JPA EntityManagerFactory備份Hibernate SessionFactory。給定一個EntityManagerFactory有一種方法來獲得底層SessionFactory,但如果你有什麼是SessionFactory,並且你想要的只是一個EntityManagerFactory包裝它,它似乎是你運氣不好。

使用Hibernate 4.2.2版Ejb3Configuration已經過時了,但似乎沒有其他辦法以編程方式創建一個EntityManagerFactory,所以我在做這樣的事情:

@SuppressWarnings("deprecation") 
EntityManagerFactory buildEntityManagerFactory(
     UnmodifiableMap<String,String> properties, 
     UnmodifiableCollection<Class<?>> annotatedClasses, 
     Interceptor interceptor) 
{ 
    Ejb3Configuration cfg = new Ejb3Configuration(); 
    for(Binding<String,String> binding : properties) 
     cfg.setProperty(binding.key, binding.value); 
    for(Class<?> annotatedClass : annotatedClasses) 
     cfg.addAnnotatedClass(annotatedClass); 
    cfg.setInterceptor(interceptor); 
    return cfg.buildEntityManagerFactory(); 
} 

使用Hibernate 4.3.0 Ejb3Configuration被刪除,所以我不得不使用這個技巧的:(這是一個黑客,因爲我實例EntityManagerFactoryImpl這是包org.hibernate.jpa.internal

EntityManagerFactory buildEntityManagerFactory(
     UnmodifiableMap<String,String> properties, 
     UnmodifiableCollection<Class<?>> annotatedClasses, 
     Interceptor interceptor) 
{ 
    Configuration cfg = new Configuration(); 
    for(Binding<String,String> binding : properties) 
     cfg.setProperty(binding.key, binding.value); 
    for(Class<?> annotatedClass : annotatedClasses) 
     cfg.addAnnotatedClass(annotatedClass); 
    cfg.setInterceptor(interceptor); 
    StandardServiceRegistryBuilder ssrb = new StandardServiceRegistryBuilder(); 
    ssrb.applySettings(cfg.getProperties()); //??? why again? 
    ServiceRegistry serviceRegistry = ssrb.build(); 
    return new EntityManagerFactoryImpl(PersistenceUnitTransactionType.RESOURCE_LOCAL, /**/ 
      /*discardOnClose=*/true, /*sessionInterceptorClass=*/null, /**/ 
      cfg, serviceRegistry, null); 
} 

現在,隨着Hibernate 5他們改變了構造函數EntityManagerFactoryImpl,所以上面的代碼不起作用。我可以浪費幾個小時試圖弄清楚如何設置,以便我可以調用該構造函數,但是我確信在幾個Hibernate版本之後,這些將不再工作。

所以,這是我的問題:

有誰知道實現這個功能的一個非常乾淨的方式

EntityManagerFactory buildEntityManagerFactory( 
     UnmodifiableMap<String,String> properties, 
     UnmodifiableCollection<Class<?>> annotatedClasses, 
     Interceptor interceptor) 

,從而創建一個Hibernate EntityManagerFactory編程,這意味着沒有配置xml文件沒有使用彈簧帶Hibernate攔截器

有這個老問題:Hibernate create JPA EntityManagerFactory with out persistence.xml但它有一個老問題的Hibernate的答案,這個問題已經在這個問題中被預料到了。這是行不通的,因爲我希望它能夠與Hibernate 5一起工作,並且理想情況下,它不會使用任何廢棄的或內部的方法,以便有很長時間的工作機會。

+0

你真的需要攔截器(他們使它很難有原因的登記)。什麼是非常特殊的,不能用JPA EventListener替代,並且不會被黑客攻擊,解決方法等。 –

+0

@ M.Deinum JPA希望自己實例化我的實體偵聽器,要求它們具有無參數的構造函數。這是不可接受的,說得溫和。 Hibernate允許我提供攔截器的實際實例,所以我可以以任何我想要的方式構造它。此外,JPA實體監聽器不允許我實例化自己的實體。同樣,Hibernate攔截器讓我可以自由實例化我自己的實體。這是至關重要的。有關更多信息,請參閱http://stackoverflow.com/a/29433238/773113 –

+0

@MikeNakis您是否嘗試聯繫開發組?你有沒有解決這種情況?我和你們的問題非常相似。 – message

回答

0

最簡單的方法是傳遞org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor引用,該引用是對「持久性單元」信息的抽象。在普通的JPA引導中,Hibernate會通過persistence.xml(用於JPA調用「SE bootstrapping」)或javax.persistence.spi.PersistenceUnitInfo(用於JPA稱爲「EE引導」的內容)構建PersistenceUnitDescriptor

但它是一個抽象的原因:)你可以創建你自己的並傳遞你想要Hibernate使用的東西。預期的方式這個作品是從org.hibernate.jpa.boot.spi.Bootstrap開始,例如:

EntityManagerFactory emf = Bootstrap.getEntityManagerFactoryBuilder(
     new CustomPersistenceUnitDescriptor(), 
     Collections.emptyMap() 
).build(); 

... 

class CustomPersistenceUnitDescriptor implements PersistenceUnitDescriptor { 
    @Override 
    public Properties getProperties() { 
     final Properties properties = new Properties(); 
     properties.put(AvailableSettngs.INTERCEPTOR, new MyInterceptor(...); 
     return properties; 
    } 

    ... 
} 
+0

謝謝!在我有機會檢查這件事情並看看它是否適用於我的情況下,我會等一段時間。 –

+0

@MikeNakis我有類似於http://stackoverflow.com/a/42372648/48136中的答案的代碼解決了類似的問題(沒有攔截器)。請注意,通過重新使用'javax.persistence.Persistence'中的一些代碼來查找提供程序,可以避免直接使用'HibernatePersistenceProvider'。 – Brice

相關問題